mirror of
https://github.com/xtr-dev/rondevu-client.git
synced 2025-12-10 02:43:25 +00:00
Add Node.js support via WebRTC polyfill injection
- Added WebRTCPolyfill interface for injecting WebRTC implementations - Added wrtc option to RondevuOptions and RondevuConnectionParams - Updated Rondevu and RondevuConnection to use injected APIs - Added helpful error message when RTCPeerConnection is not available - Updated README with Node.js usage examples - Version bumped to 0.3.0 Fixes: RTCPeerConnection not defined error in Node.js 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
40
README.md
40
README.md
@@ -24,6 +24,8 @@ npm install @xtr-dev/rondevu-client
|
||||
|
||||
### Usage
|
||||
|
||||
#### Browser
|
||||
|
||||
```typescript
|
||||
import { Rondevu } from '@xtr-dev/rondevu-client';
|
||||
|
||||
@@ -56,6 +58,44 @@ conn.on('connect', () => {
|
||||
});
|
||||
```
|
||||
|
||||
#### Node.js
|
||||
|
||||
In Node.js, you need to provide a WebRTC polyfill since WebRTC APIs are not natively available:
|
||||
|
||||
```bash
|
||||
npm install @roamhq/wrtc
|
||||
# or
|
||||
npm install wrtc
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { Rondevu } from '@xtr-dev/rondevu-client';
|
||||
import wrtc from '@roamhq/wrtc';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
const rdv = new Rondevu({
|
||||
baseUrl: 'https://server.com',
|
||||
fetch: fetch as any,
|
||||
wrtc: {
|
||||
RTCPeerConnection: wrtc.RTCPeerConnection,
|
||||
RTCSessionDescription: wrtc.RTCSessionDescription,
|
||||
RTCIceCandidate: wrtc.RTCIceCandidate,
|
||||
},
|
||||
rtcConfig: {
|
||||
iceServers: [
|
||||
{ urls: 'stun:stun.l.google.com:19302' }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
// Rest is the same as browser usage
|
||||
const conn = await rdv.join('room');
|
||||
conn.on('connect', () => {
|
||||
const channel = conn.dataChannel('chat');
|
||||
channel.send('Hello from Node.js!');
|
||||
});
|
||||
```
|
||||
|
||||
### API
|
||||
|
||||
**Main Methods:**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xtr-dev/rondevu-client",
|
||||
"version": "0.2.2",
|
||||
"version": "0.3.0",
|
||||
"description": "TypeScript client for Rondevu peer signaling and discovery server",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from './event-emitter.js';
|
||||
import { RondevuAPI } from './client.js';
|
||||
import { RondevuConnectionParams } from './types.js';
|
||||
import { RondevuConnectionParams, WebRTCPolyfill } from './types.js';
|
||||
|
||||
/**
|
||||
* Represents a WebRTC connection with automatic signaling and ICE exchange
|
||||
@@ -21,6 +21,8 @@ export class RondevuConnection extends EventEmitter {
|
||||
private connectionTimer?: ReturnType<typeof setTimeout>;
|
||||
private isPolling: boolean = false;
|
||||
private isClosed: boolean = false;
|
||||
private wrtc?: WebRTCPolyfill;
|
||||
private RTCIceCandidate: typeof RTCIceCandidate;
|
||||
|
||||
constructor(params: RondevuConnectionParams, client: RondevuAPI) {
|
||||
super();
|
||||
@@ -34,6 +36,10 @@ export class RondevuConnection extends EventEmitter {
|
||||
this.dataChannels = new Map();
|
||||
this.pollingIntervalMs = params.pollingInterval;
|
||||
this.connectionTimeoutMs = params.connectionTimeout;
|
||||
this.wrtc = params.wrtc;
|
||||
|
||||
// Use injected WebRTC polyfill or fall back to global
|
||||
this.RTCIceCandidate = params.wrtc?.RTCIceCandidate || globalThis.RTCIceCandidate;
|
||||
|
||||
this.setupEventHandlers();
|
||||
this.startConnectionTimeout();
|
||||
@@ -187,7 +193,7 @@ export class RondevuConnection extends EventEmitter {
|
||||
for (const candidateStr of offererResponse.answerCandidates) {
|
||||
try {
|
||||
const candidate = JSON.parse(candidateStr);
|
||||
await this.pc.addIceCandidate(new RTCIceCandidate(candidate));
|
||||
await this.pc.addIceCandidate(new this.RTCIceCandidate(candidate));
|
||||
} catch (err) {
|
||||
console.warn('Failed to add ICE candidate:', err);
|
||||
}
|
||||
@@ -202,7 +208,7 @@ export class RondevuConnection extends EventEmitter {
|
||||
for (const candidateStr of answererResponse.offerCandidates) {
|
||||
try {
|
||||
const candidate = JSON.parse(candidateStr);
|
||||
await this.pc.addIceCandidate(new RTCIceCandidate(candidate));
|
||||
await this.pc.addIceCandidate(new this.RTCIceCandidate(candidate));
|
||||
} catch (err) {
|
||||
console.warn('Failed to add ICE candidate:', err);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ export type {
|
||||
ConnectionRole,
|
||||
RondevuConnectionParams,
|
||||
RondevuConnectionEvents,
|
||||
WebRTCPolyfill,
|
||||
// Signaling types
|
||||
Side,
|
||||
Session,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RondevuAPI } from './client.js';
|
||||
import { RondevuConnection } from './connection.js';
|
||||
import { RondevuOptions, JoinOptions, RondevuConnectionParams } from './types.js';
|
||||
import { RondevuOptions, JoinOptions, RondevuConnectionParams, WebRTCPolyfill } from './types.js';
|
||||
|
||||
/**
|
||||
* Main Rondevu WebRTC client with automatic connection management
|
||||
@@ -14,6 +14,9 @@ export class Rondevu {
|
||||
private rtcConfig?: RTCConfiguration;
|
||||
private pollingInterval: number;
|
||||
private connectionTimeout: number;
|
||||
private wrtc?: WebRTCPolyfill;
|
||||
private RTCPeerConnection: typeof RTCPeerConnection;
|
||||
private RTCIceCandidate: typeof RTCIceCandidate;
|
||||
|
||||
/**
|
||||
* Creates a new Rondevu client instance
|
||||
@@ -22,6 +25,7 @@ export class Rondevu {
|
||||
constructor(options: RondevuOptions = {}) {
|
||||
this.baseUrl = options.baseUrl || 'https://rondevu.xtrdev.workers.dev';
|
||||
this.fetchImpl = options.fetch;
|
||||
this.wrtc = options.wrtc;
|
||||
|
||||
this.api = new RondevuAPI({
|
||||
baseUrl: this.baseUrl,
|
||||
@@ -33,6 +37,18 @@ export class Rondevu {
|
||||
this.rtcConfig = options.rtcConfig;
|
||||
this.pollingInterval = options.pollingInterval || 1000;
|
||||
this.connectionTimeout = options.connectionTimeout || 30000;
|
||||
|
||||
// Use injected WebRTC polyfill or fall back to global
|
||||
this.RTCPeerConnection = options.wrtc?.RTCPeerConnection || globalThis.RTCPeerConnection;
|
||||
this.RTCIceCandidate = options.wrtc?.RTCIceCandidate || globalThis.RTCIceCandidate;
|
||||
|
||||
if (!this.RTCPeerConnection) {
|
||||
throw new Error(
|
||||
'RTCPeerConnection not available. ' +
|
||||
'In Node.js, provide a WebRTC polyfill via the wrtc option. ' +
|
||||
'Install: npm install @roamhq/wrtc or npm install wrtc'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +73,7 @@ export class Rondevu {
|
||||
*/
|
||||
async create(id: string, topic: string): Promise<RondevuConnection> {
|
||||
// Create peer connection
|
||||
const pc = new RTCPeerConnection(this.rtcConfig);
|
||||
const pc = new this.RTCPeerConnection(this.rtcConfig);
|
||||
|
||||
// Create initial data channel for negotiation (required for offer creation)
|
||||
pc.createDataChannel('_negotiation');
|
||||
@@ -86,6 +102,7 @@ export class Rondevu {
|
||||
remotePeerId: '', // Will be populated when answer is received
|
||||
pollingInterval: this.pollingInterval,
|
||||
connectionTimeout: this.connectionTimeout,
|
||||
wrtc: this.wrtc,
|
||||
};
|
||||
|
||||
const connection = new RondevuConnection(connectionParams, this.api);
|
||||
@@ -110,7 +127,7 @@ export class Rondevu {
|
||||
}
|
||||
|
||||
// Create peer connection
|
||||
const pc = new RTCPeerConnection(this.rtcConfig);
|
||||
const pc = new this.RTCPeerConnection(this.rtcConfig);
|
||||
|
||||
// Set remote offer
|
||||
await pc.setRemoteDescription({
|
||||
@@ -142,6 +159,7 @@ export class Rondevu {
|
||||
remotePeerId: sessionData.peerId,
|
||||
pollingInterval: this.pollingInterval,
|
||||
connectionTimeout: this.connectionTimeout,
|
||||
wrtc: this.wrtc,
|
||||
};
|
||||
|
||||
const connection = new RondevuConnection(connectionParams, this.api);
|
||||
|
||||
12
src/types.ts
12
src/types.ts
@@ -177,6 +177,15 @@ export interface RondevuClientOptions {
|
||||
// WebRTC Types
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* WebRTC polyfill for Node.js and other non-browser platforms
|
||||
*/
|
||||
export interface WebRTCPolyfill {
|
||||
RTCPeerConnection: typeof RTCPeerConnection;
|
||||
RTCSessionDescription: typeof RTCSessionDescription;
|
||||
RTCIceCandidate: typeof RTCIceCandidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration options for Rondevu WebRTC client
|
||||
*/
|
||||
@@ -193,6 +202,8 @@ export interface RondevuOptions {
|
||||
pollingInterval?: number;
|
||||
/** Connection timeout in milliseconds (default: 30000) */
|
||||
connectionTimeout?: number;
|
||||
/** WebRTC polyfill for Node.js (e.g., wrtc or @roamhq/wrtc) */
|
||||
wrtc?: WebRTCPolyfill;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,6 +233,7 @@ export interface RondevuConnectionParams {
|
||||
remotePeerId: string;
|
||||
pollingInterval: number;
|
||||
connectionTimeout: number;
|
||||
wrtc?: WebRTCPolyfill;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user