import { Router, Request, Response } from 'express'; import { getStore } from './store.js'; import { calculateAllResults } from './aggregation.js'; // List of connected SSE clients const clients: Response[] = []; export const sseRouter = Router(); /** * SSE endpoint: GET /api/results/stream */ sseRouter.get('/api/results/stream', (req: Request, res: Response) => { // Set SSE headers res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); // Add client to list clients.push(res); // Send initial data immediately on connect const store = getStore(); const criteriaCount = store.session.config.criteria.length; const results = calculateAllResults(store.scores, store.teams, criteriaCount); const payload = JSON.stringify({ results, timestamp: new Date().toISOString() }); res.write(`event: scores_updated\ndata: ${payload}\n\n`); // Remove client on disconnect req.on('close', () => { const index = clients.indexOf(res); if (index !== -1) { clients.splice(index, 1); } }); }); /** * Broadcast current results to all connected SSE clients. * Called whenever scores change. */ export function broadcastUpdate(): void { const store = getStore(); const criteriaCount = store.session.config.criteria.length; const results = calculateAllResults(store.scores, store.teams, criteriaCount); const payload = JSON.stringify({ results, timestamp: new Date().toISOString() }); const message = `event: scores_updated\ndata: ${payload}\n\n`; for (const client of clients) { client.write(message); } }