import type { NuxtError } from "#app"; export type WebSocketCallback = (message: string) => void; export type WebSocketErrorHandler = (error: NuxtError) => void; export class WebSocketHandler { private listeners: Array = []; private outQueue: Array = []; private inQueue: Array = []; private ws: WebSocket | undefined = undefined; private connected: boolean = false; private errorHandler: WebSocketErrorHandler | undefined = undefined; constructor(route: string) { if (import.meta.server) return; const isSecure = location.protocol === "https:"; const url = (isSecure ? "wss://" : "ws://") + location.host + route; this.ws = new WebSocket(url); this.ws.onopen = () => { this.connected = true; for (const message of this.outQueue) { this.ws?.send(message); } }; this.ws.onmessage = (e) => { const message = e.data; switch (message) { case "unauthenticated": { const error = createError({ statusCode: 403, statusMessage: "Unable to connect to websocket - unauthenticated", }); if (this.errorHandler) { return this.errorHandler(error); } else { throw error; } } } if (this.listeners.length == 0) { this.inQueue.push(message); return; } for (const listener of this.listeners) { listener(message); } }; } error(handler: WebSocketErrorHandler) { this.errorHandler = handler; } listen(callback: WebSocketCallback) { this.listeners.push(callback); } send(message: string) { if (!this.connected || !this.ws) { this.outQueue.push(message); return; } this.ws.send(message); } }