Files
Codeman/src/web/routes/push-routes.ts
T
arkonandClaude Opus 4.6 a9d83ec4e3 chore: version packages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 23:55:39 +01:00

50 lines
1.8 KiB
TypeScript

/**
* @fileoverview Push notification routes.
* Manages VAPID keys, push subscriptions, and preference updates.
*/
import { FastifyInstance } from 'fastify';
import { v4 as uuidv4 } from 'uuid';
import { ApiErrorCode, createErrorResponse } from '../../types.js';
import { PushSubscribeSchema, PushPreferencesUpdateSchema } from '../schemas.js';
import { parseBody } from '../route-helpers.js';
import type { InfraPort } from '../ports/index.js';
export function registerPushRoutes(app: FastifyInstance, ctx: InfraPort): void {
app.get('/api/push/vapid-key', async () => {
return { success: true, data: { publicKey: ctx.pushStore.getPublicKey() } };
});
app.post('/api/push/subscribe', async (req) => {
const { endpoint, keys, userAgent, pushPreferences } = parseBody(PushSubscribeSchema, req.body);
const record = ctx.pushStore.addSubscription({
id: uuidv4(),
endpoint,
keys,
userAgent: userAgent ?? req.headers['user-agent'] ?? '',
createdAt: Date.now(),
pushPreferences: pushPreferences ?? {},
});
return { success: true, data: { id: record.id } };
});
app.put('/api/push/subscribe/:id', async (req) => {
const { id } = req.params as { id: string };
const { pushPreferences } = parseBody(PushPreferencesUpdateSchema, req.body);
const updated = ctx.pushStore.updatePreferences(id, pushPreferences);
if (!updated) {
return createErrorResponse(ApiErrorCode.NOT_FOUND, 'Subscription not found');
}
return { success: true };
});
app.delete('/api/push/subscribe/:id', async (req) => {
const { id } = req.params as { id: string };
const removed = ctx.pushStore.removeSubscription(id);
if (!removed) {
return createErrorResponse(ApiErrorCode.NOT_FOUND, 'Subscription not found');
}
return { success: true };
});
}