@xtr-dev/rondevu-client 0.9.2 → 0.10.0

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 (73) hide show
  1. package/dist/api.d.ts +147 -0
  2. package/dist/api.js +307 -0
  3. package/dist/bin.d.ts +35 -0
  4. package/dist/bin.js +35 -0
  5. package/dist/connection-manager.d.ts +104 -0
  6. package/dist/connection-manager.js +324 -0
  7. package/dist/connection.d.ts +112 -0
  8. package/dist/connection.js +194 -0
  9. package/dist/event-bus.d.ts +52 -0
  10. package/dist/event-bus.js +84 -0
  11. package/dist/index.d.ts +15 -11
  12. package/dist/index.js +9 -11
  13. package/dist/noop-signaler.d.ts +14 -0
  14. package/dist/noop-signaler.js +27 -0
  15. package/dist/rondevu-service.d.ts +81 -0
  16. package/dist/rondevu-service.js +131 -0
  17. package/dist/service-client.d.ts +92 -0
  18. package/dist/service-client.js +185 -0
  19. package/dist/service-host.d.ts +101 -0
  20. package/dist/service-host.js +185 -0
  21. package/dist/signaler.d.ts +25 -0
  22. package/dist/signaler.js +89 -0
  23. package/dist/types.d.ts +33 -0
  24. package/dist/types.js +2 -0
  25. package/dist/webrtc-context.d.ts +6 -0
  26. package/dist/webrtc-context.js +34 -0
  27. package/package.json +16 -2
  28. package/dist/auth.d.ts +0 -20
  29. package/dist/auth.js +0 -41
  30. package/dist/durable/channel.d.ts +0 -115
  31. package/dist/durable/channel.js +0 -301
  32. package/dist/durable/connection.d.ts +0 -125
  33. package/dist/durable/connection.js +0 -370
  34. package/dist/durable/reconnection.d.ts +0 -90
  35. package/dist/durable/reconnection.js +0 -127
  36. package/dist/durable/service.d.ts +0 -103
  37. package/dist/durable/service.js +0 -264
  38. package/dist/durable/types.d.ts +0 -149
  39. package/dist/durable/types.js +0 -28
  40. package/dist/event-emitter.d.ts +0 -54
  41. package/dist/event-emitter.js +0 -102
  42. package/dist/offer-pool.d.ts +0 -86
  43. package/dist/offer-pool.js +0 -145
  44. package/dist/offers.d.ts +0 -101
  45. package/dist/offers.js +0 -202
  46. package/dist/peer/answering-state.d.ts +0 -11
  47. package/dist/peer/answering-state.js +0 -39
  48. package/dist/peer/closed-state.d.ts +0 -8
  49. package/dist/peer/closed-state.js +0 -10
  50. package/dist/peer/connected-state.d.ts +0 -8
  51. package/dist/peer/connected-state.js +0 -11
  52. package/dist/peer/creating-offer-state.d.ts +0 -12
  53. package/dist/peer/creating-offer-state.js +0 -45
  54. package/dist/peer/exchanging-ice-state.d.ts +0 -17
  55. package/dist/peer/exchanging-ice-state.js +0 -64
  56. package/dist/peer/failed-state.d.ts +0 -10
  57. package/dist/peer/failed-state.js +0 -16
  58. package/dist/peer/idle-state.d.ts +0 -7
  59. package/dist/peer/idle-state.js +0 -14
  60. package/dist/peer/index.d.ts +0 -71
  61. package/dist/peer/index.js +0 -176
  62. package/dist/peer/state.d.ts +0 -23
  63. package/dist/peer/state.js +0 -63
  64. package/dist/peer/types.d.ts +0 -43
  65. package/dist/peer/types.js +0 -1
  66. package/dist/peer/waiting-for-answer-state.d.ts +0 -17
  67. package/dist/peer/waiting-for-answer-state.js +0 -60
  68. package/dist/rondevu.d.ts +0 -184
  69. package/dist/rondevu.js +0 -171
  70. package/dist/service-pool.d.ts +0 -123
  71. package/dist/service-pool.js +0 -488
  72. package/dist/usernames.d.ts +0 -79
  73. package/dist/usernames.js +0 -153
@@ -1,115 +0,0 @@
1
- /**
2
- * DurableChannel - Message queueing wrapper for RTCDataChannel
3
- *
4
- * Provides automatic message queuing during disconnections and transparent
5
- * flushing when the connection is re-established.
6
- */
7
- import { EventEmitter } from '../event-emitter.js';
8
- import { DurableChannelState } from './types.js';
9
- import type { DurableChannelConfig, DurableChannelEvents } from './types.js';
10
- /**
11
- * Durable channel that survives WebRTC peer connection drops
12
- *
13
- * The DurableChannel wraps an RTCDataChannel and provides:
14
- * - Automatic message queuing during disconnections
15
- * - Queue flushing on reconnection
16
- * - Configurable queue size and message age limits
17
- * - RTCDataChannel-compatible API
18
- *
19
- * @example
20
- * ```typescript
21
- * const channel = new DurableChannel('chat', connection, {
22
- * maxQueueSize: 500,
23
- * maxMessageAge: 30000
24
- * });
25
- *
26
- * channel.on('message', (data) => {
27
- * console.log('Received:', data);
28
- * });
29
- *
30
- * channel.on('open', () => {
31
- * channel.send('Hello!');
32
- * });
33
- *
34
- * // Messages sent during disconnection are automatically queued
35
- * channel.send('This will be queued if disconnected');
36
- * ```
37
- */
38
- export declare class DurableChannel extends EventEmitter<DurableChannelEvents> {
39
- readonly label: string;
40
- readonly config: DurableChannelConfig;
41
- private _state;
42
- private underlyingChannel?;
43
- private messageQueue;
44
- private queueProcessing;
45
- private _bufferedAmountLowThreshold;
46
- private openHandler?;
47
- private messageHandler?;
48
- private errorHandler?;
49
- private closeHandler?;
50
- private bufferedAmountLowHandler?;
51
- constructor(label: string, config?: DurableChannelConfig);
52
- /**
53
- * Current channel state
54
- */
55
- get readyState(): DurableChannelState;
56
- /**
57
- * Buffered amount from underlying channel (0 if no channel)
58
- */
59
- get bufferedAmount(): number;
60
- /**
61
- * Buffered amount low threshold
62
- */
63
- get bufferedAmountLowThreshold(): number;
64
- set bufferedAmountLowThreshold(value: number);
65
- /**
66
- * Send data through the channel
67
- *
68
- * If the channel is open, sends immediately. Otherwise, queues the message
69
- * for delivery when the channel reconnects.
70
- *
71
- * @param data - Data to send
72
- */
73
- send(data: string | Blob | ArrayBuffer | ArrayBufferView): void;
74
- /**
75
- * Close the channel
76
- */
77
- close(): void;
78
- /**
79
- * Attach to an underlying RTCDataChannel
80
- *
81
- * This is called when a WebRTC connection is established (or re-established).
82
- * The channel will flush any queued messages and forward events.
83
- *
84
- * @param channel - RTCDataChannel to attach to
85
- * @internal
86
- */
87
- attachToChannel(channel: RTCDataChannel): void;
88
- /**
89
- * Detach from the underlying RTCDataChannel
90
- *
91
- * This is called when a WebRTC connection drops. The channel remains alive
92
- * and continues queuing messages.
93
- *
94
- * @internal
95
- */
96
- detachFromChannel(): void;
97
- /**
98
- * Enqueue a message for later delivery
99
- */
100
- private enqueueMessage;
101
- /**
102
- * Flush all queued messages through the channel
103
- */
104
- private flushQueue;
105
- /**
106
- * Remove messages older than maxMessageAge from the queue
107
- */
108
- private pruneOldMessages;
109
- /**
110
- * Get the current queue size
111
- *
112
- * @internal
113
- */
114
- getQueueSize(): number;
115
- }
@@ -1,301 +0,0 @@
1
- /**
2
- * DurableChannel - Message queueing wrapper for RTCDataChannel
3
- *
4
- * Provides automatic message queuing during disconnections and transparent
5
- * flushing when the connection is re-established.
6
- */
7
- import { EventEmitter } from '../event-emitter.js';
8
- import { DurableChannelState } from './types.js';
9
- /**
10
- * Default configuration for durable channels
11
- */
12
- const DEFAULT_CONFIG = {
13
- maxQueueSize: 1000,
14
- maxMessageAge: 60000, // 1 minute
15
- ordered: true,
16
- maxRetransmits: undefined
17
- };
18
- /**
19
- * Durable channel that survives WebRTC peer connection drops
20
- *
21
- * The DurableChannel wraps an RTCDataChannel and provides:
22
- * - Automatic message queuing during disconnections
23
- * - Queue flushing on reconnection
24
- * - Configurable queue size and message age limits
25
- * - RTCDataChannel-compatible API
26
- *
27
- * @example
28
- * ```typescript
29
- * const channel = new DurableChannel('chat', connection, {
30
- * maxQueueSize: 500,
31
- * maxMessageAge: 30000
32
- * });
33
- *
34
- * channel.on('message', (data) => {
35
- * console.log('Received:', data);
36
- * });
37
- *
38
- * channel.on('open', () => {
39
- * channel.send('Hello!');
40
- * });
41
- *
42
- * // Messages sent during disconnection are automatically queued
43
- * channel.send('This will be queued if disconnected');
44
- * ```
45
- */
46
- export class DurableChannel extends EventEmitter {
47
- constructor(label, config) {
48
- super();
49
- this.messageQueue = [];
50
- this.queueProcessing = false;
51
- this._bufferedAmountLowThreshold = 0;
52
- this.label = label;
53
- this.config = { ...DEFAULT_CONFIG, ...config };
54
- this._state = DurableChannelState.CONNECTING;
55
- }
56
- /**
57
- * Current channel state
58
- */
59
- get readyState() {
60
- return this._state;
61
- }
62
- /**
63
- * Buffered amount from underlying channel (0 if no channel)
64
- */
65
- get bufferedAmount() {
66
- return this.underlyingChannel?.bufferedAmount ?? 0;
67
- }
68
- /**
69
- * Buffered amount low threshold
70
- */
71
- get bufferedAmountLowThreshold() {
72
- return this._bufferedAmountLowThreshold;
73
- }
74
- set bufferedAmountLowThreshold(value) {
75
- this._bufferedAmountLowThreshold = value;
76
- if (this.underlyingChannel) {
77
- this.underlyingChannel.bufferedAmountLowThreshold = value;
78
- }
79
- }
80
- /**
81
- * Send data through the channel
82
- *
83
- * If the channel is open, sends immediately. Otherwise, queues the message
84
- * for delivery when the channel reconnects.
85
- *
86
- * @param data - Data to send
87
- */
88
- send(data) {
89
- if (this._state === DurableChannelState.OPEN && this.underlyingChannel) {
90
- // Channel is open - send immediately
91
- try {
92
- this.underlyingChannel.send(data);
93
- }
94
- catch (error) {
95
- // Send failed - queue the message
96
- this.enqueueMessage(data);
97
- this.emit('error', error);
98
- }
99
- }
100
- else if (this._state !== DurableChannelState.CLOSED) {
101
- // Channel is not open but not closed - queue the message
102
- this.enqueueMessage(data);
103
- }
104
- else {
105
- // Channel is closed - throw error
106
- throw new Error('Cannot send on closed channel');
107
- }
108
- }
109
- /**
110
- * Close the channel
111
- */
112
- close() {
113
- if (this._state === DurableChannelState.CLOSED ||
114
- this._state === DurableChannelState.CLOSING) {
115
- return;
116
- }
117
- this._state = DurableChannelState.CLOSING;
118
- if (this.underlyingChannel) {
119
- this.underlyingChannel.close();
120
- }
121
- this._state = DurableChannelState.CLOSED;
122
- this.emit('close');
123
- }
124
- /**
125
- * Attach to an underlying RTCDataChannel
126
- *
127
- * This is called when a WebRTC connection is established (or re-established).
128
- * The channel will flush any queued messages and forward events.
129
- *
130
- * @param channel - RTCDataChannel to attach to
131
- * @internal
132
- */
133
- attachToChannel(channel) {
134
- // Detach from any existing channel first
135
- this.detachFromChannel();
136
- this.underlyingChannel = channel;
137
- // Set buffered amount low threshold
138
- channel.bufferedAmountLowThreshold = this._bufferedAmountLowThreshold;
139
- // Setup event handlers
140
- this.openHandler = () => {
141
- this._state = DurableChannelState.OPEN;
142
- this.emit('open');
143
- // Flush queued messages
144
- this.flushQueue().catch(error => {
145
- this.emit('error', error);
146
- });
147
- };
148
- this.messageHandler = (event) => {
149
- this.emit('message', event.data);
150
- };
151
- this.errorHandler = (event) => {
152
- this.emit('error', new Error(`Channel error: ${event.type}`));
153
- };
154
- this.closeHandler = () => {
155
- if (this._state !== DurableChannelState.CLOSING &&
156
- this._state !== DurableChannelState.CLOSED) {
157
- // Unexpected close - transition to connecting (will reconnect)
158
- this._state = DurableChannelState.CONNECTING;
159
- }
160
- };
161
- this.bufferedAmountLowHandler = () => {
162
- this.emit('bufferedAmountLow');
163
- };
164
- // Attach handlers
165
- channel.addEventListener('open', this.openHandler);
166
- channel.addEventListener('message', this.messageHandler);
167
- channel.addEventListener('error', this.errorHandler);
168
- channel.addEventListener('close', this.closeHandler);
169
- channel.addEventListener('bufferedamountlow', this.bufferedAmountLowHandler);
170
- // If channel is already open, trigger open event
171
- if (channel.readyState === 'open') {
172
- this.openHandler();
173
- }
174
- else if (channel.readyState === 'connecting') {
175
- this._state = DurableChannelState.CONNECTING;
176
- }
177
- }
178
- /**
179
- * Detach from the underlying RTCDataChannel
180
- *
181
- * This is called when a WebRTC connection drops. The channel remains alive
182
- * and continues queuing messages.
183
- *
184
- * @internal
185
- */
186
- detachFromChannel() {
187
- if (!this.underlyingChannel) {
188
- return;
189
- }
190
- // Remove event listeners
191
- if (this.openHandler) {
192
- this.underlyingChannel.removeEventListener('open', this.openHandler);
193
- }
194
- if (this.messageHandler) {
195
- this.underlyingChannel.removeEventListener('message', this.messageHandler);
196
- }
197
- if (this.errorHandler) {
198
- this.underlyingChannel.removeEventListener('error', this.errorHandler);
199
- }
200
- if (this.closeHandler) {
201
- this.underlyingChannel.removeEventListener('close', this.closeHandler);
202
- }
203
- if (this.bufferedAmountLowHandler) {
204
- this.underlyingChannel.removeEventListener('bufferedamountlow', this.bufferedAmountLowHandler);
205
- }
206
- this.underlyingChannel = undefined;
207
- this._state = DurableChannelState.CONNECTING;
208
- }
209
- /**
210
- * Enqueue a message for later delivery
211
- */
212
- enqueueMessage(data) {
213
- // Prune old messages first
214
- this.pruneOldMessages();
215
- const message = {
216
- data,
217
- enqueuedAt: Date.now(),
218
- id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
219
- };
220
- this.messageQueue.push(message);
221
- // Handle overflow
222
- const maxQueueSize = this.config.maxQueueSize ?? 1000;
223
- if (this.messageQueue.length > maxQueueSize) {
224
- const excess = this.messageQueue.length - maxQueueSize;
225
- this.messageQueue.splice(0, excess);
226
- this.emit('queueOverflow', excess);
227
- console.warn(`DurableChannel[${this.label}]: Dropped ${excess} messages due to queue overflow`);
228
- }
229
- }
230
- /**
231
- * Flush all queued messages through the channel
232
- */
233
- async flushQueue() {
234
- if (this.queueProcessing || !this.underlyingChannel ||
235
- this.underlyingChannel.readyState !== 'open') {
236
- return;
237
- }
238
- this.queueProcessing = true;
239
- try {
240
- // Prune old messages before flushing
241
- this.pruneOldMessages();
242
- // Send all queued messages
243
- while (this.messageQueue.length > 0) {
244
- const message = this.messageQueue.shift();
245
- if (!message)
246
- break;
247
- try {
248
- this.underlyingChannel.send(message.data);
249
- }
250
- catch (error) {
251
- // Send failed - re-queue message
252
- this.messageQueue.unshift(message);
253
- throw error;
254
- }
255
- // If buffer is getting full, wait for it to drain
256
- if (this.underlyingChannel.bufferedAmount > 16 * 1024 * 1024) { // 16MB
257
- await new Promise((resolve) => {
258
- const checkBuffer = () => {
259
- if (!this.underlyingChannel ||
260
- this.underlyingChannel.bufferedAmount < 8 * 1024 * 1024) {
261
- resolve();
262
- }
263
- else {
264
- setTimeout(checkBuffer, 100);
265
- }
266
- };
267
- checkBuffer();
268
- });
269
- }
270
- }
271
- }
272
- finally {
273
- this.queueProcessing = false;
274
- }
275
- }
276
- /**
277
- * Remove messages older than maxMessageAge from the queue
278
- */
279
- pruneOldMessages() {
280
- const maxMessageAge = this.config.maxMessageAge ?? 60000;
281
- if (maxMessageAge === Infinity || maxMessageAge <= 0) {
282
- return;
283
- }
284
- const now = Date.now();
285
- const cutoff = now - maxMessageAge;
286
- const originalLength = this.messageQueue.length;
287
- this.messageQueue = this.messageQueue.filter(msg => msg.enqueuedAt >= cutoff);
288
- const pruned = originalLength - this.messageQueue.length;
289
- if (pruned > 0) {
290
- console.warn(`DurableChannel[${this.label}]: Pruned ${pruned} old messages (older than ${maxMessageAge}ms)`);
291
- }
292
- }
293
- /**
294
- * Get the current queue size
295
- *
296
- * @internal
297
- */
298
- getQueueSize() {
299
- return this.messageQueue.length;
300
- }
301
- }
@@ -1,125 +0,0 @@
1
- /**
2
- * DurableConnection - WebRTC connection with automatic reconnection
3
- *
4
- * Manages the WebRTC peer lifecycle and automatically reconnects on
5
- * connection drops with exponential backoff.
6
- */
7
- import { EventEmitter } from '../event-emitter.js';
8
- import type { RondevuOffers } from '../offers.js';
9
- import { DurableChannel } from './channel.js';
10
- import { DurableConnectionState } from './types.js';
11
- import type { DurableConnectionConfig, DurableConnectionEvents, ConnectionInfo } from './types.js';
12
- /**
13
- * Durable WebRTC connection that automatically reconnects
14
- *
15
- * The DurableConnection manages the lifecycle of a WebRTC peer connection
16
- * and provides:
17
- * - Automatic reconnection with exponential backoff
18
- * - Multiple durable channels that survive reconnections
19
- * - Configurable retry limits and timeouts
20
- * - High-level connection state events
21
- *
22
- * @example
23
- * ```typescript
24
- * const connection = new DurableConnection(
25
- * offersApi,
26
- * { username: 'alice', serviceFqn: 'chat@1.0.0' },
27
- * { maxReconnectAttempts: 5 }
28
- * );
29
- *
30
- * connection.on('connected', () => {
31
- * console.log('Connected!');
32
- * });
33
- *
34
- * connection.on('reconnecting', (attempt, max, delay) => {
35
- * console.log(`Reconnecting... (${attempt}/${max}, retry in ${delay}ms)`);
36
- * });
37
- *
38
- * const channel = connection.createChannel('chat');
39
- * channel.on('message', (data) => {
40
- * console.log('Received:', data);
41
- * });
42
- *
43
- * await connection.connect();
44
- * ```
45
- */
46
- export declare class DurableConnection extends EventEmitter<DurableConnectionEvents> {
47
- private offersApi;
48
- readonly connectionId: string;
49
- readonly config: Required<DurableConnectionConfig>;
50
- readonly connectionInfo: ConnectionInfo;
51
- private _state;
52
- private currentPeer?;
53
- private channels;
54
- private reconnectionScheduler?;
55
- private peerConnectedHandler?;
56
- private peerDisconnectedHandler?;
57
- private peerFailedHandler?;
58
- private peerDataChannelHandler?;
59
- constructor(offersApi: RondevuOffers, connectionInfo: ConnectionInfo, config?: DurableConnectionConfig);
60
- /**
61
- * Current connection state
62
- */
63
- getState(): DurableConnectionState;
64
- /**
65
- * Check if connection is currently connected
66
- */
67
- isConnected(): boolean;
68
- /**
69
- * Create a durable channel on this connection
70
- *
71
- * The channel will be created on the current peer connection if available,
72
- * otherwise it will be created when the connection is established.
73
- *
74
- * @param label - Channel label
75
- * @param options - RTCDataChannel init options
76
- * @returns DurableChannel instance
77
- */
78
- createChannel(label: string, options?: RTCDataChannelInit): DurableChannel;
79
- /**
80
- * Get an existing channel by label
81
- */
82
- getChannel(label: string): DurableChannel | undefined;
83
- /**
84
- * Establish the initial connection
85
- *
86
- * @returns Promise that resolves when connected
87
- */
88
- connect(): Promise<void>;
89
- /**
90
- * Close the connection gracefully
91
- */
92
- close(): Promise<void>;
93
- /**
94
- * Establish a WebRTC connection
95
- */
96
- private establishConnection;
97
- /**
98
- * Connect to a service by UUID
99
- */
100
- private connectByUuid;
101
- /**
102
- * Connect to a service by username and service FQN
103
- */
104
- private connectByService;
105
- /**
106
- * Wait for peer connection to establish
107
- */
108
- private waitForConnection;
109
- /**
110
- * Setup event handlers for peer
111
- */
112
- private setupPeerHandlers;
113
- /**
114
- * Transition to connected state
115
- */
116
- private transitionToConnected;
117
- /**
118
- * Create underlying RTCDataChannel and attach to durable channel
119
- */
120
- private createAndAttachChannel;
121
- /**
122
- * Handle connection disconnection
123
- */
124
- private handleDisconnection;
125
- }