import { writable } from 'svelte/store'; import { playSound } from '$utils/helpers.js'; function createWebSocketStore() { const { subscribe, set, update } = writable({ connected: false, ws: null }); let ws = null; let reconnectTimer = null; let listeners = {}; function connect(token) { if (ws && ws.readyState === WebSocket.OPEN) return; const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws'; const host = window.location.host; const url = `${protocol}://${host}/ws?token=${token}`; ws = new WebSocket(url); ws.onopen = () => { console.log('[WS] Connected'); update((s) => ({ ...s, connected: true, ws })); clearTimeout(reconnectTimer); }; ws.onmessage = (event) => { try { const msg = JSON.parse(event.data); const { channel, event: evt, data } = msg; // Dispatch to registered listeners const key = `${channel}:${evt}`; if (listeners[key]) { listeners[key].forEach((fn) => fn(data)); } // Wildcard channel listeners if (listeners[`*:${evt}`]) { listeners[`*:${evt}`].forEach((fn) => fn(data, channel)); } // Play sound for new orders/KOTs if (evt === 'new_order' || evt === 'new_kot') { playSound('order'); } } catch { // Ignore parse errors } }; ws.onclose = () => { console.log('[WS] Disconnected, reconnecting in 3s...'); update((s) => ({ ...s, connected: false, ws: null })); reconnectTimer = setTimeout(() => connect(token), 3000); }; ws.onerror = () => { ws.close(); }; } function disconnect() { clearTimeout(reconnectTimer); if (ws) { ws.close(); ws = null; } set({ connected: false, ws: null }); listeners = {}; } function on(channel, event, callback) { const key = `${channel}:${event}`; if (!listeners[key]) listeners[key] = []; listeners[key].push(callback); // Return unsubscribe function return () => { listeners[key] = listeners[key].filter((fn) => fn !== callback); }; } function send(channel, event, data) { if (ws && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ channel, event, data })); } } return { subscribe, connect, disconnect, on, send }; } export const wsStore = createWebSocketStore();