Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DgBEW6qAwgn2fcQbA2f4ZQ
31 lines
862 B
TypeScript
31 lines
862 B
TypeScript
import type { Response } from 'express';
|
|
import type { SyncEventPayload } from '../shared/types.js';
|
|
|
|
const clients = new Set<Response>();
|
|
|
|
export function addClient(res: Response, initial: SyncEventPayload): void {
|
|
res.writeHead(200, {
|
|
'content-type': 'text/event-stream',
|
|
'cache-control': 'no-cache',
|
|
connection: 'keep-alive',
|
|
'x-accel-buffering': 'no',
|
|
});
|
|
res.write('retry: 3000\n\n');
|
|
res.write(frame(initial));
|
|
clients.add(res);
|
|
res.on('close', () => clients.delete(res));
|
|
}
|
|
|
|
export function broadcast(payload: SyncEventPayload): void {
|
|
const data = frame(payload);
|
|
for (const res of clients) res.write(data);
|
|
}
|
|
|
|
function frame(payload: SyncEventPayload): string {
|
|
return `event: sync\ndata: ${JSON.stringify(payload)}\n\n`;
|
|
}
|
|
|
|
setInterval(() => {
|
|
for (const res of clients) res.write(': ping\n\n');
|
|
}, 25_000).unref();
|