UNPKG

resig.js

Version:

Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.

313 lines 25 kB
"use strict"; /** * WebRTC Streaming Signals * Real-time collaboration with automatic reconnection and peer discovery */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createWebRTCBroadcast = exports.createWebRTCStream = exports.BroadcastChannelSignaling = exports.WebRTCPeer = void 0; const coalgebra_1 = require("./coalgebra"); // WebRTC peer connection wrapper class WebRTCPeer { constructor(peerId, config, signaling) { this.peerId = peerId; this.config = config; this.signaling = signaling; this.dataChannel = null; this.reconnectAttempts = 0; this.heartbeatTimer = null; this.messageHandlers = new Set(); this.connection = new RTCPeerConnection({ iceServers: config.iceServers || [ { urls: 'stun:stun.l.google.com:19302' }, ], }); this.setupConnection(); } setupConnection() { // Handle ICE candidates this.connection.onicecandidate = (event) => { if (event.candidate) { this.signaling.iceCandidate(this.peerId, event.candidate.toJSON()); } }; // Handle connection state changes this.connection.onconnectionstatechange = () => { const state = this.connection.connectionState; if (state === 'failed' || state === 'disconnected') { this.handleReconnection(); } }; // Handle incoming data channels this.connection.ondatachannel = (event) => { this.setupDataChannel(event.channel); }; } setupDataChannel(channel) { this.dataChannel = channel; channel.onopen = () => { this.startHeartbeat(); }; channel.onclose = () => { this.stopHeartbeat(); }; channel.onmessage = (event) => { try { const data = JSON.parse(event.data); if (data.type === 'heartbeat') { // Respond to heartbeat this.send({ type: 'heartbeat-response', timestamp: Date.now() }); } else { this.messageHandlers.forEach((handler) => handler(data)); } } catch (error) { console.error('Failed to parse WebRTC message:', error); } }; channel.onerror = (error) => { console.error('WebRTC data channel error:', error); }; } startHeartbeat() { if (this.heartbeatTimer) return; const interval = this.config.heartbeatInterval || 30000; // 30 seconds this.heartbeatTimer = window.setInterval(() => { this.send({ type: 'heartbeat', timestamp: Date.now() }); }, interval); } stopHeartbeat() { if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; } } async handleReconnection() { const maxAttempts = this.config.reconnectAttempts || 5; const delay = this.config.reconnectDelay || 1000; if (this.reconnectAttempts >= maxAttempts) { console.error(`Failed to reconnect to peer ${this.peerId} after ${maxAttempts} attempts`); return; } this.reconnectAttempts++; console.log(`Attempting to reconnect to peer ${this.peerId} (attempt ${this.reconnectAttempts})`); await new Promise((resolve) => setTimeout(resolve, delay * this.reconnectAttempts)); try { await this.createOffer(); } catch (error) { console.error('Reconnection failed:', error); this.handleReconnection(); } } async createOffer() { // Create data channel for outgoing connections if (!this.dataChannel) { this.dataChannel = this.connection.createDataChannel('data', this.config.dataChannelOptions); this.setupDataChannel(this.dataChannel); } const offer = await this.connection.createOffer(); await this.connection.setLocalDescription(offer); await this.signaling.offer(this.peerId, offer); } async handleOffer(offer) { await this.connection.setRemoteDescription(offer); const answer = await this.connection.createAnswer(); await this.connection.setLocalDescription(answer); await this.signaling.answer(this.peerId, answer); } async handleAnswer(answer) { await this.connection.setRemoteDescription(answer); this.reconnectAttempts = 0; // Reset on successful connection } async handleIceCandidate(candidate) { await this.connection.addIceCandidate(new RTCIceCandidate(candidate)); } send(data) { if (this.dataChannel && this.dataChannel.readyState === 'open') { try { this.dataChannel.send(JSON.stringify(data)); return true; } catch (error) { console.error('Failed to send WebRTC message:', error); return false; } } return false; } onMessage(handler) { this.messageHandlers.add(handler); return () => this.messageHandlers.delete(handler); } getConnectionState() { return this.connection.connectionState; } close() { this.stopHeartbeat(); if (this.dataChannel) { this.dataChannel.close(); } this.connection.close(); } } exports.WebRTCPeer = WebRTCPeer; // Simple signaling implementation using BroadcastChannel class BroadcastChannelSignaling { constructor(channelName = 'webrtc-signaling') { this.offerHandlers = new Set(); this.answerHandlers = new Set(); this.iceCandidateHandlers = new Set(); this.channel = new BroadcastChannel(channelName); this.channel.onmessage = this.handleMessage.bind(this); } handleMessage(event) { const { type, peerId, data } = event.data; switch (type) { case 'offer': this.offerHandlers.forEach((handler) => handler(peerId, data)); break; case 'answer': this.answerHandlers.forEach((handler) => handler(peerId, data)); break; case 'ice-candidate': this.iceCandidateHandlers.forEach((handler) => handler(peerId, data)); break; } } async offer(peerId, offer) { this.channel.postMessage({ type: 'offer', peerId, data: offer }); } async answer(peerId, answer) { this.channel.postMessage({ type: 'answer', peerId, data: answer }); } async iceCandidate(peerId, candidate) { this.channel.postMessage({ type: 'ice-candidate', peerId, data: candidate, }); } onOffer(callback) { this.offerHandlers.add(callback); } onAnswer(callback) { this.answerHandlers.add(callback); } onIceCandidate(callback) { this.iceCandidateHandlers.add(callback); } close() { this.channel.close(); } } exports.BroadcastChannelSignaling = BroadcastChannelSignaling; // Create WebRTC streaming signal const createWebRTCStream = (peerId, config = {}, signaling) => { const stream = (0, coalgebra_1.createStreamingSignal)(null); const sig = signaling || new BroadcastChannelSignaling(); const peer = new WebRTCPeer(peerId, config, sig); // Handle incoming messages peer.onMessage((data) => { if (typeof data === 'object' && data !== null && 'type' in data && data.type === 'stream-data' && 'value' in data) { stream._set(data.value); } }); // Setup signaling handlers sig.onOffer(async (fromPeerId, offer) => { if (fromPeerId === peerId) { await peer.handleOffer(offer); } }); sig.onAnswer(async (fromPeerId, answer) => { if (fromPeerId === peerId) { await peer.handleAnswer(answer); } }); sig.onIceCandidate(async (fromPeerId, candidate) => { if (fromPeerId === peerId) { await peer.handleIceCandidate(candidate); } }); // Override _set to broadcast changes const originalSet = stream ._set; stream._set = (value) => { originalSet(value); peer.send({ type: 'stream-data', value, timestamp: Date.now() }); }; // Add peer management methods stream.peer = peer; stream.connect = () => peer.createOffer(); stream.disconnect = () => peer.close(); stream.getConnectionState = () => peer.getConnectionState(); return stream; }; exports.createWebRTCStream = createWebRTCStream; // Multi-peer WebRTC stream for broadcasting to multiple peers const createWebRTCBroadcast = (peerIds, config = {}, signaling) => { const stream = (0, coalgebra_1.createStreamingSignal)(null); const sig = signaling || new BroadcastChannelSignaling(); const peers = new Map(); // Create peers for each peer ID peerIds.forEach((peerId) => { const peer = new WebRTCPeer(peerId, config, sig); peers.set(peerId, peer); // Handle incoming messages from any peer peer.onMessage((data) => { if (typeof data === 'object' && data !== null && 'type' in data && data.type === 'stream-data' && 'value' in data) { stream._set(data.value); } }); }); // Setup signaling for all peers sig.onOffer(async (fromPeerId, offer) => { const peer = peers.get(fromPeerId); if (peer) { await peer.handleOffer(offer); } }); sig.onAnswer(async (fromPeerId, answer) => { const peer = peers.get(fromPeerId); if (peer) { await peer.handleAnswer(answer); } }); sig.onIceCandidate(async (fromPeerId, candidate) => { const peer = peers.get(fromPeerId); if (peer) { await peer.handleIceCandidate(candidate); } }); // Override _set to broadcast to all peers const originalSet = stream ._set; stream._set = (value) => { originalSet(value); const message = { type: 'stream-data', value, timestamp: Date.now() }; peers.forEach((peer) => peer.send(message)); }; // Add broadcast management methods stream.peers = peers; stream.connectAll = async () => { const peerArray = Array.from(peers.values()); for (const peer of peerArray) { await peer.createOffer(); } }; stream.disconnectAll = () => { peers.forEach((peer) => peer.close()); }; return stream; }; exports.createWebRTCBroadcast = createWebRTCBroadcast; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2VicnRjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N0cmVhbWluZy93ZWJydGMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7O0FBRUgsMkNBQXFFO0FBbUNyRSxpQ0FBaUM7QUFDakMsTUFBYSxVQUFVO0lBT3JCLFlBQ1MsTUFBYyxFQUNiLE1BQTBCLEVBQzFCLFNBQXdCO1FBRnpCLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDYixXQUFNLEdBQU4sTUFBTSxDQUFvQjtRQUMxQixjQUFTLEdBQVQsU0FBUyxDQUFlO1FBUjFCLGdCQUFXLEdBQTBCLElBQUksQ0FBQztRQUMxQyxzQkFBaUIsR0FBRyxDQUFDLENBQUM7UUFDdEIsbUJBQWMsR0FBa0IsSUFBSSxDQUFDO1FBQ3JDLG9CQUFlLEdBQUcsSUFBSSxHQUFHLEVBQTJCLENBQUM7UUFPM0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLGlCQUFpQixDQUFDO1lBQ3RDLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVSxJQUFJO2dCQUMvQixFQUFFLElBQUksRUFBRSw4QkFBOEIsRUFBRTthQUN6QztTQUNGLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRU8sZUFBZTtRQUNyQix3QkFBd0I7UUFDeEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUN6QyxJQUFJLEtBQUssQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDcEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDckUsQ0FBQztRQUNILENBQUMsQ0FBQztRQUVGLGtDQUFrQztRQUNsQyxJQUFJLENBQUMsVUFBVSxDQUFDLHVCQUF1QixHQUFHLEdBQUcsRUFBRTtZQUM3QyxNQUFNLEtB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