import type { Server } from 'http'; import type { WebSocketServer as wsServer } from 'ws'; import { WebSocketServer as WebSocket } from 'ws'; import type { Socket } from 'net'; export interface WebSocketServer { on: wsServer['on']; off: wsServer['off']; send(payload: any): void; close(): Promise; } export const createWebSocketServer = ( server: Server, httpsOptions?: {}, ): WebSocketServer => { let wss: WebSocket; let httpsServer: Server | undefined = undefined; const wsServer = server; wss = new WebSocket({ noServer: true }); wsServer.on('upgrade', (req, socket, head) => { wss.handleUpgrade(req, socket as Socket, head, (ws) => { wss.emit('connection', ws, req); }); }); wss.on('connection', (socket) => { socket.send(JSON.stringify({ type: 'connected' })); }); wss.on('error', (e: Error & { code: string }) => { if (e.code !== 'EADDRINUSE') { } }); return { on: wss.on.bind(wss), off: wss.off.bind(wss), send(payload: any) { if (payload.type === 'error' && !wss.clients.size) { console.log('err'); return; } const stringified = JSON.stringify(payload); wss.clients.forEach((client) => { // readyState 1 means the connection is open if (client.readyState === 1) { client.send(stringified); } }); }, close() { return new Promise((resolve, reject) => { wss.clients.forEach((client) => { client.terminate(); }); wss.close((err) => { if (err) { reject(err); } else { if (httpsServer) { httpsServer.close((err) => { if (err) { reject(err); } else { resolve(); } }); } else { resolve(); } } }); }); }, }; };