UNPKG

@jsenv/core

Version:

Tool to develop, test and build js projects

95 lines (92 loc) 2.51 kB
export const createServerEventsDispatcher = () => { const clients = []; const MAX_CLIENTS = 100; const addClient = (client) => { clients.push(client); if (clients.length >= MAX_CLIENTS) { const firstClient = clients.shift(); firstClient.close(); } const removeClient = () => { const index = clients.indexOf(client); if (index > -1) { clients.splice(index, 1); } }; client.onclose = () => { removeClient(client); }; return () => { client.close(); }; }; return { addWebsocket: (websocket, request) => { const client = { request, getReadystate: () => { return websocket.readyState; }, sendEvent: (event) => { websocket.send(JSON.stringify(event)); }, close: (reason) => { const closePromise = new Promise((resolve, reject) => { websocket.onclose = () => { websocket.onclose = null; websocket.onerror = null; resolve(); }; websocket.onerror = (e) => { websocket.onclose = null; websocket.onerror = null; reject(e); }; }); websocket.close(reason); return closePromise; }, destroy: () => { websocket.terminate(); }, }; client.sendEvent({ type: "welcome" }); websocket.onclose = () => { client.onclose(); }; client.onclose = () => {}; return addClient(client); }, // we could add "addEventSource" and let clients connect using // new WebSocket or new EventSource // in practice the new EventSource won't be used // so "serverEventsDispatcher.addEventSource" is not implemented // addEventSource: (request) => {}, dispatch: (event) => { clients.forEach((client) => { if (client.getReadystate() === 1) { client.sendEvent(event); } }); }, dispatchToClientsMatching: (event, predicate) => { clients.forEach((client) => { if (client.getReadystate() === 1 && predicate(client)) { client.sendEvent(event); } }); }, close: async (reason) => { await Promise.all( clients.map(async (client) => { await client.close(reason); }), ); }, destroy: () => { clients.forEach((client) => { client.destroy(); }); }, }; };