diff --git a/web/src/websocket.ts b/web/src/websocket.ts new file mode 100644 index 0000000..0de551e --- /dev/null +++ b/web/src/websocket.ts @@ -0,0 +1,92 @@ +import { getToken } from "./storage"; +interface WebSocketConfig { + onMessage: (data: any) => void; + onOpen?: () => void; + onClose?: () => void; + onError?: (error: Event) => void; + enableReconnect?: boolean; + reconnectDelay?: number; +} +let activeWebSocket: WebSocket | null = null; +let reconnectTimeout: ReturnType | null = null; +function createWebSocket(config: WebSocketConfig): WebSocket | null { + const token = getToken(); + if (!token) { + console.warn( + "No authentication token found - skipping WebSocket connection", + ); + return null; + } + // Clean up existing connection + if (activeWebSocket) { + activeWebSocket.close(); + } + if (reconnectTimeout) { + clearTimeout(reconnectTimeout); + reconnectTimeout = null; + } + const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; + const wsUrl = `${protocol}//${window.location.host}/ws/sync?token=${token}`; + const ws = new WebSocket(wsUrl); + ws.onopen = () => { + console.log("WebSocket connected"); + if (config.onOpen) { + try { + config.onOpen(); + } catch (error) { + console.error("Error in onOpen callback:", error); + } + } + }; + ws.onmessage = (event: MessageEvent) => { + try { + const message = JSON.parse(event.data); + config.onMessage(message); + } catch (error) { + console.error("Error parsing WebSocket message:", error); + console.error("Raw message:", event.data); + } + }; + ws.onerror = (error: Event) => { + console.error("WebSocket error:", error); + if (config.onError) { + try { + config.onError(error); + } catch (err) { + console.error("Error in onError callback:", err); + } + } + }; + ws.onclose = () => { + console.log("WebSocket disconnected"); + + if (config.onClose) { + try { + config.onClose(); + } catch (error) { + console.error("Error in onClose callback:", error); + } + } + // Auto-reconnect if enabled + if (config.enableReconnect !== false) { + const delay = config.reconnectDelay || 5000; + console.log(`Reconnecting in ${delay / 1000}s...`); + reconnectTimeout = setTimeout(() => { + createWebSocket(config); + }, delay); + } + }; + activeWebSocket = ws; + return ws; +} +function disconnectWebSocket(): void { + if (reconnectTimeout) { + clearTimeout(reconnectTimeout); + reconnectTimeout = null; + } + if (activeWebSocket) { + activeWebSocket.close(); + activeWebSocket = null; + } +} +export { createWebSocket, disconnectWebSocket };