UNPKG

anon-identity

Version:

Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure

160 lines 5.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebSocketChannel = void 0; const message_protocol_1 = require("../message-protocol"); class WebSocketChannel { constructor(id, options = {}) { this.type = 'websocket'; this.isConnected = false; this.messageHandlers = new Set(); this.reconnectAttempts = 0; this.id = id; this.options = { url: options.url || 'ws://localhost:8080', reconnectInterval: options.reconnectInterval || 5000, maxReconnectAttempts: options.maxReconnectAttempts || 10, heartbeatInterval: options.heartbeatInterval || 30000, messageTimeout: options.messageTimeout || 10000 }; } async connect() { return new Promise((resolve, reject) => { try { // Note: WebSocket is not available in Node.js by default // This implementation assumes a browser environment or ws library if (typeof WebSocket === 'undefined') { throw new Error('WebSocket not available in this environment'); } this.ws = new WebSocket(this.options.url); this.ws.onopen = () => { this.isConnected = true; this.reconnectAttempts = 0; this.startHeartbeat(); resolve(); }; this.ws.onclose = () => { this.isConnected = false; this.stopHeartbeat(); this.attemptReconnect(); }; this.ws.onerror = (error) => { console.error('WebSocket error:', error); reject(new Error('WebSocket connection failed')); }; this.ws.onmessage = (event) => { this.handleIncomingMessage(event.data); }; } catch (error) { reject(error); } }); } async disconnect() { this.stopHeartbeat(); if (this.ws) { this.ws.close(); this.ws = undefined; } this.isConnected = false; } async send(envelope) { if (!this.isConnected || !this.ws) { throw new Error('WebSocket not connected'); } const serialized = message_protocol_1.MessageProtocol.serialize(envelope.message); return new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error('Message send timeout')); }, this.options.messageTimeout); try { this.ws.send(JSON.stringify({ envelope, serializedMessage: serialized })); clearTimeout(timeout); resolve(); } catch (error) { clearTimeout(timeout); reject(error); } }); } onMessage(handler) { this.messageHandlers.add(handler); } removeMessageHandler(handler) { this.messageHandlers.delete(handler); } handleIncomingMessage(data) { try { const parsed = JSON.parse(data); let envelope; if (parsed.envelope) { envelope = parsed.envelope; // Deserialize the message if it was serialized if (parsed.serializedMessage) { envelope.message = message_protocol_1.MessageProtocol.deserialize(parsed.serializedMessage); } } else { // Assume the data is the envelope itself envelope = parsed; } // Notify all handlers this.messageHandlers.forEach(handler => { try { handler(envelope); } catch (error) { console.error('Message handler error:', error); } }); } catch (error) { console.error('Failed to parse incoming message:', error); } } startHeartbeat() { this.heartbeatTimer = setInterval(() => { if (this.isConnected && this.ws) { try { this.ws.send(JSON.stringify({ type: 'ping' })); } catch (error) { console.error('Heartbeat failed:', error); this.disconnect(); } } }, this.options.heartbeatInterval); } stopHeartbeat() { if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = undefined; } } attemptReconnect() { if (this.reconnectAttempts >= this.options.maxReconnectAttempts) { console.error('Max reconnection attempts reached'); return; } this.reconnectAttempts++; setTimeout(() => { console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.options.maxReconnectAttempts})`); this.connect().catch(error => { console.error('Reconnection failed:', error); }); }, this.options.reconnectInterval); } getConnectionState() { return { connected: this.isConnected, reconnectAttempts: this.reconnectAttempts, url: this.options.url }; } } exports.WebSocketChannel = WebSocketChannel; //# sourceMappingURL=websocket-channel.js.map