| 11 | const DEFAULT_RETRY_IN_MS = 5000; |
| 12 | |
| 13 | export default class WebSocketClient { |
| 14 | private url: string; |
| 15 | |
| 16 | private socket: WebSocket | null = null; |
| 17 | |
| 18 | private queue: { topic: string; event: string; payload: Record<string, any> }[] = []; |
| 19 | |
| 20 | private callbacks: Record<string, Array<(event: string, payload: Record<string, any>) => void>> = |
| 21 | {}; |
| 22 | |
| 23 | private currentRetry = 0; |
| 24 | |
| 25 | constructor(url: string) { |
| 26 | this.url = url; |
| 27 | this.connect(); |
| 28 | } |
| 29 | |
| 30 | get open() { |
| 31 | return this.socket !== null && this.socket.readyState === WebSocket.OPEN; |
| 32 | } |
| 33 | |
| 34 | on(topic: string, callback: (event: string, payload: Record<string, any>) => void) { |
| 35 | this.callbacks[topic] = this.callbacks[topic] || []; |
| 36 | this.callbacks[topic]?.push(callback); |
| 37 | } |
| 38 | |
| 39 | off(topic: string, callback: (event: string, payload: Record<string, any>) => void) { |
| 40 | const callbacks = (this.callbacks[topic] || []).filter((cb) => cb !== callback); |
| 41 | |
| 42 | if (callbacks.length === 0) { |
| 43 | delete this.callbacks[topic]; |
| 44 | } else { |
| 45 | this.callbacks[topic] = callbacks; |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | push(topic: string, event: string, payload: Record<string, any>) { |
| 50 | if (this.open) { |
| 51 | this.send(topic, event, payload); |
| 52 | } else { |
| 53 | this.queue.push({ topic, event, payload }); |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | private flush() { |
| 58 | while (this.queue.length > 0) { |
| 59 | const message = this.queue.shift()!; |
| 60 | this.send(message.topic, message.event, message.payload); |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | private send(topic: string, event: string, payload: Record<string, any>) { |
| 65 | const message = JSON.stringify([topic, event, payload]); |
| 66 | |
| 67 | if (this.socket && this.open) { |
| 68 | this.socket.send(message); |
| 69 | } else { |
| 70 | console.error( |
nothing calls this directly
no test coverage detected