import type http from 'node:http'; import { WebSocketServer, type WebSocket } from 'ws'; import { logger } from './logger.js'; let wss: WebSocketServer | null = null; export function initLiveReload(server: http.Server): void { if (wss) return; const enabled = process.env.LIVE_RELOAD_WS_ENABLED === 'true'; if (!enabled) { logger.info({ event: 'live_reload.disabled' }, 'Live reload websocket disabled'); return; } const wsPath = process.env.LIVE_RELOAD_WS_PATH || '/__live_reload'; wss = new WebSocketServer({ server, path: wsPath }); wss.on('connection', (socket: WebSocket) => { logger.info({ event: 'live_reload.connected' }, 'Live reload client connected'); socket.on('close', () => { logger.info({ event: 'live_reload.disconnected' }, 'Live reload client disconnected'); }); }); logger.info({ event: 'live_reload.started', path: wsPath }, 'Live reload websocket started'); } export function broadcastReload(reason: string, data?: Record): void { if (!wss) return; const payload = JSON.stringify({ type: 'reload', ts: Date.now(), reason, ...data, }); for (const client of wss.clients) { if (client.readyState === client.OPEN) { client.send(payload); } } } export type UpdateStatusPhase = 'request_received' | 'update_started' | 'update_done'; export function broadcastUpdateStatus(phase: UpdateStatusPhase, data?: Record): void { if (!wss) return; const payload = JSON.stringify({ type: 'update_status', ts: Date.now(), phase, ...data, }); for (const client of wss.clients) { if (client.readyState === client.OPEN) { client.send(payload); } } }