@xtr-dev/rondevu-client 0.17.1 → 0.18.1

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.
package/dist/rondevu.d.ts CHANGED
@@ -10,6 +10,8 @@ export interface RondevuOptions {
10
10
  batching?: BatcherOptions | false;
11
11
  iceServers?: IceServerPreset | RTCIceServer[];
12
12
  debug?: boolean;
13
+ rtcPeerConnection?: typeof RTCPeerConnection;
14
+ rtcIceCandidate?: typeof RTCIceCandidate;
13
15
  }
14
16
  export interface OfferContext {
15
17
  pc: RTCPeerConnection;
@@ -103,6 +105,8 @@ export declare class Rondevu {
103
105
  private batchingOptions?;
104
106
  private iceServers;
105
107
  private debugEnabled;
108
+ private rtcPeerConnection?;
109
+ private rtcIceCandidate?;
106
110
  private currentService;
107
111
  private maxOffers;
108
112
  private offerFactory;
package/dist/rondevu.js CHANGED
@@ -98,7 +98,7 @@ export const ICE_SERVER_PRESETS = {
98
98
  * ```
99
99
  */
100
100
  export class Rondevu {
101
- constructor(apiUrl, username, keypair, api, iceServers, cryptoAdapter, batchingOptions, debugEnabled = false) {
101
+ constructor(apiUrl, username, keypair, api, iceServers, cryptoAdapter, batchingOptions, debugEnabled = false, rtcPeerConnection, rtcIceCandidate) {
102
102
  this.usernameClaimed = false;
103
103
  // Service management
104
104
  this.currentService = null;
@@ -118,6 +118,8 @@ export class Rondevu {
118
118
  this.cryptoAdapter = cryptoAdapter;
119
119
  this.batchingOptions = batchingOptions;
120
120
  this.debugEnabled = debugEnabled;
121
+ this.rtcPeerConnection = rtcPeerConnection;
122
+ this.rtcIceCandidate = rtcIceCandidate;
121
123
  this.debug('Instance created:', {
122
124
  username: this.username,
123
125
  publicKey: this.keypair.publicKey,
@@ -146,6 +148,13 @@ export class Rondevu {
146
148
  */
147
149
  static async connect(options) {
148
150
  const username = options.username || Rondevu.generateAnonymousUsername();
151
+ // Apply WebRTC polyfills to global scope if provided (Node.js environments)
152
+ if (options.rtcPeerConnection) {
153
+ globalThis.RTCPeerConnection = options.rtcPeerConnection;
154
+ }
155
+ if (options.rtcIceCandidate) {
156
+ globalThis.RTCIceCandidate = options.rtcIceCandidate;
157
+ }
149
158
  // Handle preset string or custom array
150
159
  let iceServers;
151
160
  if (typeof options.iceServers === 'string') {
@@ -181,7 +190,7 @@ export class Rondevu {
181
190
  const api = new RondevuAPI(options.apiUrl, username, keypair, options.cryptoAdapter, options.batching);
182
191
  if (options.debug)
183
192
  console.log('[Rondevu] Created API instance');
184
- return new Rondevu(options.apiUrl, username, keypair, api, iceServers, options.cryptoAdapter, options.batching, options.debug || false);
193
+ return new Rondevu(options.apiUrl, username, keypair, api, iceServers, options.cryptoAdapter, options.batching, options.debug || false, options.rtcPeerConnection, options.rtcIceCandidate);
185
194
  }
186
195
  /**
187
196
  * Generate an anonymous username with timestamp and random component
@@ -278,9 +287,39 @@ export class Rondevu {
278
287
  };
279
288
  this.debug('Creating new offer...');
280
289
  // Create the offer using the factory
290
+ // Note: The factory may call setLocalDescription() which triggers ICE gathering
281
291
  const { pc, dc, offer } = await this.offerFactory(rtcConfig);
282
292
  // Auto-append username to service
283
293
  const serviceFqn = `${this.currentService}@${this.username}`;
294
+ // Queue to buffer ICE candidates generated before we have the offerId
295
+ // This fixes the race condition where ICE candidates are lost because
296
+ // they're generated before we can set up the handler with the offerId
297
+ const earlyIceCandidates = [];
298
+ let offerId = null;
299
+ // Set up a queuing ICE candidate handler immediately after getting the pc
300
+ // This captures any candidates that fire before we have the offerId
301
+ pc.onicecandidate = async (event) => {
302
+ if (event.candidate) {
303
+ // Handle both browser and Node.js (wrtc) environments
304
+ const candidateData = typeof event.candidate.toJSON === 'function'
305
+ ? event.candidate.toJSON()
306
+ : event.candidate;
307
+ if (offerId) {
308
+ // We have the offerId, send directly
309
+ try {
310
+ await this.api.addOfferIceCandidates(serviceFqn, offerId, [candidateData]);
311
+ }
312
+ catch (err) {
313
+ console.error('[Rondevu] Failed to send ICE candidate:', err);
314
+ }
315
+ }
316
+ else {
317
+ // Queue for later - we don't have the offerId yet
318
+ this.debug('Queuing early ICE candidate');
319
+ earlyIceCandidates.push(candidateData);
320
+ }
321
+ }
322
+ };
284
323
  // Publish to server
285
324
  const result = await this.api.publishService({
286
325
  serviceFqn,
@@ -289,7 +328,7 @@ export class Rondevu {
289
328
  signature: '',
290
329
  message: '',
291
330
  });
292
- const offerId = result.offers[0].offerId;
331
+ offerId = result.offers[0].offerId;
293
332
  // Store active offer
294
333
  this.activeOffers.set(offerId, {
295
334
  offerId,
@@ -300,8 +339,16 @@ export class Rondevu {
300
339
  createdAt: Date.now()
301
340
  });
302
341
  this.debug(`Offer created: ${offerId}`);
303
- // Set up ICE candidate handler
304
- this.setupIceCandidateHandler(pc, serviceFqn, offerId);
342
+ // Send any queued early ICE candidates
343
+ if (earlyIceCandidates.length > 0) {
344
+ this.debug(`Sending ${earlyIceCandidates.length} early ICE candidates`);
345
+ try {
346
+ await this.api.addOfferIceCandidates(serviceFqn, offerId, earlyIceCandidates);
347
+ }
348
+ catch (err) {
349
+ console.error('[Rondevu] Failed to send early ICE candidates:', err);
350
+ }
351
+ }
305
352
  // Monitor connection state
306
353
  pc.onconnectionstatechange = () => {
307
354
  this.debug(`Offer ${offerId} connection state: ${pc.connectionState}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtr-dev/rondevu-client",
3
- "version": "0.17.1",
3
+ "version": "0.18.1",
4
4
  "description": "TypeScript client for Rondevu with durable WebRTC connections, automatic reconnection, and message queuing",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",