// Minimal WS client with auto-reconnect for Rust backend interoperability. // Point URL to your Rust server: ws://localhost:8080/ws (example) type Listener = (data: any) => void export class VNWebSocket { private url: string private ws: WebSocket | null = null private reconnectDelay = 1000 private maxReconnectDelay = 8000 private shouldReconnect = true private listeners: Record = {} constructor(url: string) { this.url = url } on(event: 'open' | 'close' | 'error' | 'message', cb: Listener) { if (!this.listeners[event]) this.listeners[event] = [] this.listeners[event].push(cb) } private emit(event: string, data?: any) { ;(this.listeners[event] || []).forEach(cb => cb(data)) } connect() { this.ws = new WebSocket(this.url) this.ws.addEventListener('open', () => { this.emit('open') this.reconnectDelay = 1000 }) this.ws.addEventListener('message', (evt) => { try { const parsed = JSON.parse(evt.data) this.emit('message', parsed) } catch { this.emit('message', evt.data) } }) this.ws.addEventListener('close', () => { this.emit('close') if (this.shouldReconnect) { setTimeout(() => this.connect(), this.reconnectDelay) this.reconnectDelay = Math.min(this.reconnectDelay * 2, this.maxReconnectDelay) } }) this.ws.addEventListener('error', (e) => { this.emit('error', e) this.ws?.close() }) } send(data: any) { const payload = typeof data === 'string' ? data : JSON.stringify(data) if (this.ws && this.ws.readyState === WebSocket.OPEN) { this.ws.send(payload) } } close() { this.shouldReconnect = false this.ws?.close() } }