diff --git a/src/lib/ws.ts b/src/lib/ws.ts index 746260b..47f5a9d 100644 --- a/src/lib/ws.ts +++ b/src/lib/ws.ts @@ -9,6 +9,8 @@ class WSClient { private ws: WebSocket | null = null; private handlers: Map> = new Map(); private reconnectTimer: ReturnType | null = null; + private pendingQueue: any[] = []; + private authenticated = false; private _lobbyId: string | null = null; private _projects: Array<{ id: string; slug: string; name: string }> = []; private _online: string[] = []; @@ -27,6 +29,8 @@ class WSClient { console.error("NEXT_PUBLIC_WS_URL is not set!"); return; } + + this.authenticated = false; this.ws = new WebSocket(`${wsBase}/ws?token=${token}`); this.ws.onmessage = (event) => { @@ -34,11 +38,17 @@ class WSClient { const msg = JSON.parse(event.data); const type = msg.type; - // Handle auth.ok + // Handle auth.ok — flush pending queue if (type === "auth.ok") { this._lobbyId = msg.data?.lobby_chat_id || null; this._projects = msg.data?.projects || []; this._online = msg.data?.online || []; + this.authenticated = true; + // Flush queued messages + for (const queued of this.pendingQueue) { + this.ws!.send(JSON.stringify(queued)); + } + this.pendingQueue = []; } // Dispatch to handlers @@ -54,6 +64,7 @@ class WSClient { }; this.ws.onclose = () => { + this.authenticated = false; this.reconnectTimer = setTimeout(() => this.connect(), 3000); }; @@ -64,6 +75,8 @@ class WSClient { if (this.reconnectTimer) clearTimeout(this.reconnectTimer); this.ws?.close(); this.ws = null; + this.authenticated = false; + this.pendingQueue = []; } on(type: string, handler: MessageHandler) { @@ -73,8 +86,11 @@ class WSClient { } send(data: any) { - if (this.ws?.readyState === WebSocket.OPEN) { + if (this.ws?.readyState === WebSocket.OPEN && this.authenticated) { this.ws.send(JSON.stringify(data)); + } else { + // Queue until connected + authenticated + this.pendingQueue.push(data); } }