import { type FastifyInstance } from 'fastify'
import { requirePermission } from '../../../middleware/roleMiddleware'
export default async function sseRoute(server: FastifyInstance) {
server.get('/notifications/stream', {
sse: true,
preValidation: requirePermission('notifications.read'),
schema: {
tags: ['Notifications'],
summary: 'Stream notifications',
description: 'Real-time notification stream via SSE',
security: [{ cookieAuth: [] }]
}
}, async (request, reply) => {
const userId = request.user!.id
// Handle client reconnection
reply.sse.replay(async (lastEventId) => {
const missed = await notificationService.getMissedNotifications(userId, lastEventId)
for (const notification of missed) {
reply.sse.send({ id: notification.id, event: 'notification', data: notification })
}
})
// Keep connection open
reply.sse.keepAlive()
// Subscribe to new notifications
const unsubscribe = notificationService.subscribe(userId, (notification) => {
if (reply.sse.isConnected) {
reply.sse.send({ id: notification.id, event: 'notification', data: notification })
}
})
// Cleanup on disconnect
reply.sse.onClose(() => {
unsubscribe()
server.log.debug({ userId }, 'SSE connection closed')
})
})
}