import type { Server as HttpServer } from 'node:http'; import { WebSocketServer, type VerifyClientCallbackSync } from 'ws'; import { handleChatConnection } from '@/modules/websocket/services/chat-websocket.service.js'; import { verifyWebSocketClient } from '@/modules/websocket/services/websocket-auth.service.js'; import { handlePluginWsProxy } from '@/modules/websocket/services/plugin-websocket-proxy.service.js'; import { handleShellConnection } from '@/modules/websocket/services/shell-websocket.service.js'; import type { AuthenticatedWebSocketRequest } from '@/shared/types.js'; type WebSocketServerDependencies = { verifyClient: Parameters[1]; chat: Parameters[2]; shell: Parameters[1]; getPluginPort: Parameters[2]; }; /** * Creates and wires the server-wide websocket gateway used for chat, shell, and * plugin proxy routes. */ export function createWebSocketServer( server: HttpServer, dependencies: WebSocketServerDependencies ): WebSocketServer { const wss = new WebSocketServer({ server, verifyClient: (( info: Parameters>[0] ) => verifyWebSocketClient(info, dependencies.verifyClient)), }); wss.on('connection', (ws, request) => { const incomingRequest = request as AuthenticatedWebSocketRequest; const url = incomingRequest.url ?? '/'; const pathname = new URL(url, 'http://localhost').pathname; if (pathname === '/shell') { handleShellConnection(ws, dependencies.shell); return; } if (pathname === '/ws') { handleChatConnection(ws, incomingRequest, dependencies.chat); return; } if (pathname.startsWith('/plugin-ws/')) { handlePluginWsProxy(ws, pathname, dependencies.getPluginPort); return; } console.log('[WARN] Unknown WebSocket path:', pathname); ws.close(); }); return wss; }