@xtr-dev/rondevu-client 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +35 -615
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,640 +1,60 @@
1
- # @xtr-dev/rondevu-client
1
+ # Rondevu
2
2
 
3
- TypeScript/JavaScript client for WebRTC peer-to-peer connections with automatic signaling and connection management.
3
+ 🎯 Meet WebRTC peers by topic, by peer ID, or by connection ID.
4
4
 
5
- ## Features
5
+ ## @xtr-dev/rondevu-client
6
6
 
7
- - ✨ **Simple API** - Three methods to establish connections: `create()`, `connect()`, `join()`
8
- - 🔄 **Automatic Everything** - Handles signaling, ICE candidates, and connection lifecycle
9
- - 📡 **Event-Driven** - Clean event-based API for connection state and data
10
- - 🎯 **Type-Safe** - Full TypeScript support with comprehensive type definitions
11
- - 🌐 **Universal** - Works in browsers and Node.js
12
- - 🚀 **Zero Dependencies** - Lightweight with no runtime dependencies
7
+ [![npm version](https://img.shields.io/npm/v/@xtr-dev/rondevu-client)](https://www.npmjs.com/package/@xtr-dev/rondevu-client)
13
8
 
14
- ## Installation
9
+ TypeScript Rondevu HTTP and WebRTC client, for simple peer discovery and connection.
10
+
11
+ ### Install
15
12
 
16
13
  ```bash
17
14
  npm install @xtr-dev/rondevu-client
18
15
  ```
19
16
 
20
- ## Quick Start
17
+ ### Usage
21
18
 
22
19
  ```typescript
23
20
  import { Rondevu } from '@xtr-dev/rondevu-client';
24
21
 
25
- // Initialize once
26
- const rdv = new Rondevu({
27
- baseUrl: 'https://your-rondevu-server.com',
28
- rtcConfig: {
29
- iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
30
- }
31
- });
32
-
33
- // Peer A: Create a connection
34
- const connA = await rdv.create('meeting-123', 'meetings');
35
- connA.on('connect', () => {
36
- const channel = connA.dataChannel('chat');
37
- channel.send('Hello!');
38
- });
39
-
40
- // Peer B: Connect to the connection
41
- const connB = await rdv.connect('meeting-123');
42
- connB.on('datachannel', (channel) => {
43
- channel.onmessage = (e) => console.log('Received:', e.data);
44
- });
45
- ```
46
-
47
- ## API Documentation
48
-
49
- ### Rondevu Class
50
-
51
- The main class for WebRTC connection management with automatic signaling.
52
-
53
- #### Constructor
54
-
55
- ```typescript
56
- const rdv = new Rondevu(options: RondevuOptions);
57
- ```
58
-
59
- **Options:**
60
- ```typescript
61
- interface RondevuOptions {
62
- baseUrl: string; // Rondevu server URL (required)
63
- peerId?: string; // Custom peer ID (auto-generated if not provided)
64
- origin?: string; // Origin for session isolation
65
- fetch?: typeof fetch; // Custom fetch (for Node.js)
66
- rtcConfig?: RTCConfiguration; // WebRTC configuration (ICE servers, etc.)
67
- pollingInterval?: number; // Polling interval in ms (default: 1000)
68
- connectionTimeout?: number; // Connection timeout in ms (default: 30000)
69
- }
70
- ```
71
-
72
- #### Properties
73
-
74
- - `peerId: string` - The current peer identifier (read-only)
75
-
76
- #### Methods
77
-
78
- ##### `create(id: string, topic: string): Promise<RondevuConnection>`
79
-
80
- Creates a new connection (offerer role) and waits for a peer to join.
81
-
82
- ```typescript
83
- const connection = await rdv.create('my-connection-id', 'my-topic');
84
- ```
22
+ const rdv = new Rondevu({ baseUrl: 'https://server.com' });
85
23
 
86
- **Parameters:**
87
- - `id` - Connection identifier (can be any string)
88
- - `topic` - Topic name for grouping connections (max 1024 chars)
89
-
90
- **Returns:** `RondevuConnection` object
91
-
92
- **Use case:** When you want to create a new connection and share its ID with others.
93
-
94
- ---
95
-
96
- ##### `connect(id: string): Promise<RondevuConnection>`
97
-
98
- Connects to an existing connection by ID (answerer role).
99
-
100
- ```typescript
101
- const connection = await rdv.connect('my-connection-id');
102
- ```
24
+ // Connect by topic
25
+ const conn = await rdv.join('room');
103
26
 
104
- **Parameters:**
105
- - `id` - The connection ID to join
27
+ // Or connect by ID
28
+ const conn = await rdv.connect('meeting-123');
106
29
 
107
- **Returns:** `RondevuConnection` object
108
-
109
- **Use case:** When you have a specific connection ID (e.g., from a QR code, link, or shared message).
110
-
111
- ---
112
-
113
- ##### `join(topic: string, options?: JoinOptions): Promise<RondevuConnection>`
114
-
115
- Joins a topic and automatically connects to the first available peer (answerer role).
116
-
117
- ```typescript
118
- const connection = await rdv.join('my-topic');
119
- ```
120
-
121
- **Parameters:**
122
- - `topic` - Topic name to join
123
- - `options` - Optional join options
124
-
125
- ```typescript
126
- interface JoinOptions {
127
- filter?: (session: { code: string; peerId: string }) => boolean;
128
- select?: 'first' | 'newest' | 'oldest' | 'random';
129
- }
130
- ```
131
-
132
- **Returns:** `RondevuConnection` object
133
-
134
- **Use case:** When you want automatic peer discovery and connection.
135
-
136
- **Example with options:**
137
- ```typescript
138
- const connection = await rdv.join('game-room', {
139
- filter: (session) => session.peerId.startsWith('player-'),
140
- select: 'random'
141
- });
142
- ```
143
-
144
- ---
145
-
146
- ##### `updatePeerId(newPeerId: string): void`
147
-
148
- Updates the peer ID (useful when user identity changes).
149
-
150
- ```typescript
151
- rdv.updatePeerId('new-peer-id');
152
- ```
153
-
154
- ---
155
-
156
- ### RondevuConnection Class
157
-
158
- Represents a WebRTC connection with event-driven API.
159
-
160
- #### Properties
161
-
162
- - `id: string` - Connection identifier (read-only)
163
- - `topic: string` - Topic name (read-only)
164
- - `role: 'offerer' | 'answerer'` - Connection role (read-only)
165
- - `remotePeerId: string` - Remote peer's ID (read-only)
166
-
167
- #### Methods
168
-
169
- ##### `dataChannel(label: string, options?: RTCDataChannelInit): RTCDataChannel`
170
-
171
- Gets or creates a data channel.
172
-
173
- ```typescript
174
- const channel = connection.dataChannel('chat');
175
- channel.onopen = () => channel.send('Hello!');
176
- ```
177
-
178
- **Parameters:**
179
- - `label` - Data channel label/name
180
- - `options` - Optional RTCDataChannel configuration
181
-
182
- **Returns:** `RTCDataChannel` object
183
-
184
- ---
185
-
186
- ##### `addStream(stream: MediaStream): void`
187
-
188
- Adds a local media stream (audio/video) to the connection.
189
-
190
- ```typescript
191
- const stream = await navigator.mediaDevices.getUserMedia({
192
- video: true,
193
- audio: true
194
- });
195
- connection.addStream(stream);
196
- ```
197
-
198
- ---
199
-
200
- ##### `getPeerConnection(): RTCPeerConnection`
201
-
202
- Gets the underlying `RTCPeerConnection` for advanced use cases.
203
-
204
- ```typescript
205
- const pc = connection.getPeerConnection();
206
- const stats = await pc.getStats();
207
- ```
208
-
209
- **Use case:** Accessing WebRTC stats, adding custom tracks, or other advanced WebRTC features.
210
-
211
- ---
212
-
213
- ##### `close(): void`
214
-
215
- Closes the connection and cleans up resources.
216
-
217
- ```typescript
218
- connection.close();
219
- ```
220
-
221
- ---
222
-
223
- #### Events
224
-
225
- Listen to connection events using the `.on()` method:
226
-
227
- ##### `'connect'`
228
-
229
- Emitted when the WebRTC connection is established.
230
-
231
- ```typescript
232
- connection.on('connect', () => {
233
- console.log('Connected!');
234
- });
235
- ```
236
-
237
- ---
238
-
239
- ##### `'disconnect'`
240
-
241
- Emitted when the connection is closed or lost.
242
-
243
- ```typescript
244
- connection.on('disconnect', () => {
245
- console.log('Disconnected');
246
- });
247
- ```
248
-
249
- ---
250
-
251
- ##### `'error'`
252
-
253
- Emitted when an error occurs.
254
-
255
- ```typescript
256
- connection.on('error', (error: Error) => {
257
- console.error('Connection error:', error.message);
258
- });
259
- ```
260
-
261
- ---
262
-
263
- ##### `'datachannel'`
264
-
265
- Emitted when a remote peer creates a data channel.
266
-
267
- ```typescript
268
- connection.on('datachannel', (channel: RTCDataChannel) => {
269
- console.log('Received channel:', channel.label);
270
- channel.onmessage = (e) => console.log(e.data);
271
- });
272
- ```
273
-
274
- ---
275
-
276
- ##### `'stream'`
277
-
278
- Emitted when a remote media stream is received.
279
-
280
- ```typescript
281
- connection.on('stream', (stream: MediaStream) => {
282
- videoElement.srcObject = stream;
283
- });
284
- ```
285
-
286
- ---
287
-
288
- ## Usage Examples
289
-
290
- ### Example 1: Simple Chat Application
291
-
292
- ```typescript
293
- import { Rondevu } from '@xtr-dev/rondevu-client';
294
-
295
- const rdv = new Rondevu({
296
- baseUrl: 'https://your-server.com',
297
- rtcConfig: {
298
- iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
299
- }
300
- });
301
-
302
- // Peer A: Create connection
303
- const connectionA = await rdv.create('chat-room-123', 'chat-rooms');
304
-
305
- connectionA.on('connect', () => {
306
- const chat = connectionA.dataChannel('messages');
307
- chat.send(JSON.stringify({ user: 'Alice', text: 'Hello!' }));
308
- });
309
-
310
- connectionA.on('datachannel', (channel) => {
311
- if (channel.label === 'messages') {
312
- channel.onmessage = (e) => {
313
- const msg = JSON.parse(e.data);
314
- console.log(`${msg.user}: ${msg.text}`);
315
- };
316
- }
317
- });
318
-
319
- // Share 'chat-room-123' with Peer B
320
-
321
- // Peer B: Join connection
322
- const connectionB = await rdv.connect('chat-room-123');
323
-
324
- connectionB.on('connect', () => {
325
- const chat = connectionB.dataChannel('messages');
326
- chat.send(JSON.stringify({ user: 'Bob', text: 'Hi Alice!' }));
327
- });
328
- ```
329
-
330
- ---
331
-
332
- ### Example 2: Video Chat
333
-
334
- ```typescript
335
- import { Rondevu } from '@xtr-dev/rondevu-client';
336
-
337
- const rdv = new Rondevu({
338
- baseUrl: 'https://your-server.com',
339
- rtcConfig: {
340
- iceServers: [
341
- { urls: 'stun:stun.l.google.com:19302' },
342
- {
343
- urls: 'turn:your-turn-server.com:3478',
344
- username: 'user',
345
- credential: 'pass'
346
- }
347
- ]
348
- }
349
- });
350
-
351
- // Get local video stream
352
- const localStream = await navigator.mediaDevices.getUserMedia({
353
- video: true,
354
- audio: true
355
- });
356
- document.getElementById('local-video').srcObject = localStream;
357
-
358
- // Create connection and add stream
359
- const connection = await rdv.create('video-call-456', 'video-calls');
360
- connection.addStream(localStream);
361
-
362
- // Handle remote stream
363
- connection.on('stream', (remoteStream) => {
364
- document.getElementById('remote-video').srcObject = remoteStream;
365
- });
366
-
367
- connection.on('connect', () => {
368
- console.log('Video call connected!');
369
- });
370
-
371
- // Other peer joins
372
- // const connection = await rdv.connect('video-call-456');
373
- ```
374
-
375
- ---
376
-
377
- ### Example 3: Topic-Based Discovery
378
-
379
- ```typescript
380
- import { Rondevu } from '@xtr-dev/rondevu-client';
381
-
382
- const rdv = new Rondevu({
383
- baseUrl: 'https://your-server.com',
384
- peerId: 'player-123' // Custom peer ID
385
- });
386
-
387
- // Create a game session
388
- const host = await rdv.create('game-session-1', 'multiplayer-games');
389
-
390
- host.on('connect', () => {
391
- console.log('Player joined:', host.remotePeerId);
392
-
393
- const game = host.dataChannel('game-state');
394
- game.send(JSON.stringify({ type: 'start', level: 1 }));
395
- });
396
-
397
- // Another player discovers and joins
398
- const player = await rdv.join('multiplayer-games', {
399
- filter: (session) => session.peerId !== rdv.peerId, // Avoid self
400
- select: 'first' // Join first available game
401
- });
402
-
403
- player.on('connect', () => {
404
- console.log('Joined game with:', player.remotePeerId);
405
- });
406
-
407
- player.on('datachannel', (channel) => {
408
- channel.onmessage = (e) => {
409
- const data = JSON.parse(e.data);
410
- console.log('Game event:', data);
411
- };
412
- });
413
- ```
414
-
415
- ---
416
-
417
- ### Example 4: Connection Stats Monitoring
418
-
419
- ```typescript
420
- import { Rondevu } from '@xtr-dev/rondevu-client';
421
-
422
- const rdv = new Rondevu({ baseUrl: 'https://your-server.com' });
423
- const connection = await rdv.connect('meeting-123');
424
-
425
- connection.on('connect', () => {
426
- // Access underlying RTCPeerConnection for stats
427
- const pc = connection.getPeerConnection();
428
-
429
- setInterval(async () => {
430
- const stats = await pc.getStats();
431
-
432
- stats.forEach(report => {
433
- if (report.type === 'candidate-pair' && report.state === 'succeeded') {
434
- console.log('RTT:', report.currentRoundTripTime * 1000, 'ms');
435
- console.log('Bytes sent:', report.bytesSent);
436
- console.log('Bytes received:', report.bytesReceived);
437
- }
438
- });
439
- }, 2000);
440
- });
441
- ```
442
-
443
- ---
444
-
445
- ## Low-Level API (Advanced)
446
-
447
- For advanced use cases, you can use the low-level `RondevuClient` for manual signaling:
448
-
449
- ```typescript
450
- import { RondevuClient } from '@xtr-dev/rondevu-client';
451
-
452
- const client = new RondevuClient({
453
- baseUrl: 'https://your-server.com'
454
- });
455
-
456
- // List topics
457
- const { topics } = await client.listTopics();
458
-
459
- // List sessions in a topic
460
- const { sessions } = await client.listSessions('my-topic');
461
-
462
- // Create offer manually
463
- const { code } = await client.createOffer('my-topic', {
464
- peerId: 'my-peer-id',
465
- offer: sdpOffer,
466
- code: 'custom-session-id' // Optional
467
- });
468
-
469
- // Send answer
470
- await client.sendAnswer({
471
- code: sessionCode,
472
- answer: sdpAnswer,
473
- side: 'answerer'
474
- });
475
-
476
- // Poll for remote data
477
- const data = await client.poll(sessionCode, 'offerer');
478
- ```
479
-
480
- See the original README for full low-level API documentation.
481
-
482
- ---
483
-
484
- ## Configuration
485
-
486
- ### ICE Servers
487
-
488
- Configure STUN/TURN servers for NAT traversal:
489
-
490
- ```typescript
491
- const rdv = new Rondevu({
492
- baseUrl: 'https://your-server.com',
493
- rtcConfig: {
494
- iceServers: [
495
- // Public STUN servers
496
- { urls: 'stun:stun.l.google.com:19302' },
497
- { urls: 'stun:stun1.l.google.com:19302' },
498
-
499
- // Private TURN server (recommended for production)
500
- {
501
- urls: 'turn:your-turn-server.com:3478',
502
- username: 'username',
503
- credential: 'password'
504
- }
505
- ],
506
- iceTransportPolicy: 'all' // 'relay' to force TURN
507
- }
508
- });
509
- ```
510
-
511
- ### Polling and Timeouts
512
-
513
- Customize polling interval and connection timeout:
514
-
515
- ```typescript
516
- const rdv = new Rondevu({
517
- baseUrl: 'https://your-server.com',
518
- pollingInterval: 500, // Poll every 500ms (default: 1000)
519
- connectionTimeout: 60000 // 60 second timeout (default: 30000)
520
- });
521
- ```
522
-
523
- ### Custom Peer ID
524
-
525
- Provide a custom peer identifier:
526
-
527
- ```typescript
528
- const rdv = new Rondevu({
529
- baseUrl: 'https://your-server.com',
530
- peerId: 'user-alice-session-xyz'
531
- });
532
-
533
- console.log(rdv.peerId); // 'user-alice-session-xyz'
534
-
535
- // Update later if needed
536
- rdv.updatePeerId('user-alice-new-session');
537
- ```
538
-
539
- ---
540
-
541
- ## Error Handling
542
-
543
- Always handle connection errors:
544
-
545
- ```typescript
546
- const connection = await rdv.create('session-1', 'topic-1');
547
-
548
- connection.on('error', (error) => {
549
- console.error('Connection error:', error.message);
550
-
551
- if (error.message.includes('timeout')) {
552
- // Handle timeout
553
- } else if (error.message.includes('not found')) {
554
- // Handle session not found
555
- }
556
- });
557
-
558
- connection.on('disconnect', () => {
559
- console.log('Connection closed');
560
- // Cleanup UI, attempt reconnection, etc.
561
- });
562
- ```
563
-
564
- ---
565
-
566
- ## TypeScript Support
567
-
568
- The library is written in TypeScript and includes comprehensive type definitions:
569
-
570
- ```typescript
571
- import {
572
- Rondevu,
573
- RondevuConnection,
574
- RondevuOptions,
575
- JoinOptions,
576
- ConnectionRole
577
- } from '@xtr-dev/rondevu-client';
578
-
579
- const options: RondevuOptions = {
580
- baseUrl: 'https://your-server.com',
581
- rtcConfig: {
582
- iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
583
- }
584
- };
585
-
586
- const rdv: Rondevu = new Rondevu(options);
587
- const connection: RondevuConnection = await rdv.create('id', 'topic');
588
-
589
- console.log(connection.role); // Type: 'offerer' | 'answerer'
590
- ```
591
-
592
- ---
593
-
594
- ## Node.js Support
595
-
596
- The library works in Node.js with a WebRTC polyfill:
597
-
598
- ```bash
599
- npm install wrtc
600
- ```
601
-
602
- ```typescript
603
- import { Rondevu } from '@xtr-dev/rondevu-client';
604
- import wrtc from 'wrtc';
605
-
606
- // Polyfill WebRTC globals
607
- global.RTCPeerConnection = wrtc.RTCPeerConnection;
608
- global.RTCSessionDescription = wrtc.RTCSessionDescription;
609
- global.RTCIceCandidate = wrtc.RTCIceCandidate;
610
-
611
- const rdv = new Rondevu({
612
- baseUrl: 'https://your-server.com',
613
- fetch: fetch // Use node-fetch if needed
30
+ // Use the connection
31
+ conn.on('connect', () => {
32
+ const channel = conn.dataChannel('chat');
33
+ channel.send('Hello!');
614
34
  });
615
35
  ```
616
36
 
617
- ---
37
+ ### API
618
38
 
619
- ## Browser Compatibility
39
+ **Main Methods:**
40
+ - `rdv.join(topic)` - Auto-connect to first peer in topic
41
+ - `rdv.join(topic, {filter})` - Connect to specific peer by ID
42
+ - `rdv.create(id, topic)` - Create connection for others to join
43
+ - `rdv.connect(id)` - Join connection by ID
620
44
 
621
- - Chrome/Edge 56+
622
- - Firefox 44+
623
- - Safari 11+
624
- - Opera 43+
45
+ **Connection Events:**
46
+ - `connect` - Connection established
47
+ - `disconnect` - Connection closed
48
+ - `datachannel` - Remote peer created data channel
49
+ - `stream` - Remote media stream received
50
+ - `error` - Error occurred
625
51
 
626
- Requires WebRTC support (`RTCPeerConnection`, `RTCDataChannel`).
52
+ **Connection Methods:**
53
+ - `conn.dataChannel(label)` - Get or create data channel
54
+ - `conn.addStream(stream)` - Add media stream
55
+ - `conn.getPeerConnection()` - Get underlying RTCPeerConnection
56
+ - `conn.close()` - Close connection
627
57
 
628
- ---
629
-
630
- ## License
58
+ ### License
631
59
 
632
60
  MIT
633
-
634
- ---
635
-
636
- ## Links
637
-
638
- - [GitHub Repository](https://github.com/xtr-dev/rondevu)
639
- - [Server Documentation](https://github.com/xtr-dev/rondevu/tree/main/server)
640
- - [Demo Application](https://github.com/xtr-dev/rondevu/tree/main/demo)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtr-dev/rondevu-client",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "TypeScript client for Rondevu peer signaling and discovery server",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",