@xtr-dev/rondevu-client 0.18.10 → 0.20.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/README.md +324 -47
- package/dist/{api.d.ts → api/client.d.ts} +17 -8
- package/dist/{api.js → api/client.js} +114 -81
- package/dist/{answerer-connection.d.ts → connections/answerer.d.ts} +13 -5
- package/dist/{answerer-connection.js → connections/answerer.js} +17 -32
- package/dist/{connection.d.ts → connections/base.d.ts} +26 -5
- package/dist/{connection.js → connections/base.js} +45 -4
- package/dist/{offerer-connection.d.ts → connections/offerer.d.ts} +30 -5
- package/dist/{offerer-connection.js → connections/offerer.js} +93 -32
- package/dist/core/index.d.ts +22 -0
- package/dist/core/index.js +17 -0
- package/dist/core/offer-pool.d.ts +94 -0
- package/dist/core/offer-pool.js +267 -0
- package/dist/{rondevu.d.ts → core/rondevu.d.ts} +77 -85
- package/dist/core/rondevu.js +600 -0
- package/dist/{node-crypto-adapter.d.ts → crypto/node.d.ts} +1 -1
- package/dist/{web-crypto-adapter.d.ts → crypto/web.d.ts} +1 -1
- package/dist/utils/async-lock.d.ts +42 -0
- package/dist/utils/async-lock.js +75 -0
- package/dist/{message-buffer.d.ts → utils/message-buffer.d.ts} +1 -1
- package/package.json +4 -4
- package/dist/index.d.ts +0 -13
- package/dist/index.js +0 -10
- package/dist/rondevu-signaler.d.ts +0 -112
- package/dist/rondevu-signaler.js +0 -401
- package/dist/rondevu.js +0 -847
- /package/dist/{rpc-batcher.d.ts → api/batcher.d.ts} +0 -0
- /package/dist/{rpc-batcher.js → api/batcher.js} +0 -0
- /package/dist/{connection-config.d.ts → connections/config.d.ts} +0 -0
- /package/dist/{connection-config.js → connections/config.js} +0 -0
- /package/dist/{connection-events.d.ts → connections/events.d.ts} +0 -0
- /package/dist/{connection-events.js → connections/events.js} +0 -0
- /package/dist/{types.d.ts → core/types.d.ts} +0 -0
- /package/dist/{types.js → core/types.js} +0 -0
- /package/dist/{crypto-adapter.d.ts → crypto/adapter.d.ts} +0 -0
- /package/dist/{crypto-adapter.js → crypto/adapter.js} +0 -0
- /package/dist/{node-crypto-adapter.js → crypto/node.js} +0 -0
- /package/dist/{web-crypto-adapter.js → crypto/web.js} +0 -0
- /package/dist/{exponential-backoff.d.ts → utils/exponential-backoff.d.ts} +0 -0
- /package/dist/{exponential-backoff.js → utils/exponential-backoff.js} +0 -0
- /package/dist/{message-buffer.js → utils/message-buffer.js} +0 -0
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@xtr-dev/rondevu-client)
|
|
4
4
|
|
|
5
|
-
🌐 **
|
|
5
|
+
🌐 **WebRTC signaling client with durable connections**
|
|
6
6
|
|
|
7
|
-
TypeScript/JavaScript client for Rondevu, providing WebRTC signaling with username claiming, service publishing/discovery, and efficient batch polling.
|
|
7
|
+
TypeScript/JavaScript client for Rondevu, providing WebRTC signaling with **automatic reconnection**, **message buffering**, username claiming, service publishing/discovery, and efficient batch polling.
|
|
8
8
|
|
|
9
9
|
**Related repositories:**
|
|
10
10
|
- [@xtr-dev/rondevu-client](https://github.com/xtr-dev/rondevu-client) - TypeScript client library ([npm](https://www.npmjs.com/package/@xtr-dev/rondevu-client))
|
|
@@ -15,15 +15,24 @@ TypeScript/JavaScript client for Rondevu, providing WebRTC signaling with userna
|
|
|
15
15
|
|
|
16
16
|
## Features
|
|
17
17
|
|
|
18
|
+
### ✨ New in v0.20.0
|
|
19
|
+
- **🔄 Automatic Reconnection**: Built-in exponential backoff for failed connections
|
|
20
|
+
- **📦 Message Buffering**: Queues messages during disconnections, replays on reconnect
|
|
21
|
+
- **🔄 Connection Persistence**: OffererConnection objects persist across disconnections via offer rotation
|
|
22
|
+
- **📊 Connection State Machine**: Explicit lifecycle tracking with native RTC events
|
|
23
|
+
- **🎯 Rich Event System**: 20+ events for monitoring connection health including `connection:rotated`
|
|
24
|
+
- **⚡ Improved Reliability**: ICE polling lifecycle management, proper cleanup, rotation fallback
|
|
25
|
+
- **🏗️ Internal Refactoring**: Cleaner codebase with OfferPool extraction and consolidated ICE polling
|
|
26
|
+
|
|
27
|
+
### Core Features
|
|
18
28
|
- **Username Claiming**: Secure ownership with Ed25519 signatures
|
|
19
29
|
- **Anonymous Users**: Auto-generated anonymous usernames for quick testing
|
|
20
30
|
- **Service Publishing**: Publish services with multiple offers for connection pooling
|
|
21
31
|
- **Service Discovery**: Direct lookup, random discovery, or paginated search
|
|
22
|
-
- **Efficient Batch Polling**: Single endpoint for answers and ICE candidates
|
|
32
|
+
- **Efficient Batch Polling**: Single endpoint for answers and ICE candidates
|
|
23
33
|
- **Semantic Version Matching**: Compatible version resolution (chat:1.0.0 matches any 1.x.x)
|
|
24
34
|
- **TypeScript**: Full type safety and autocomplete
|
|
25
35
|
- **Keypair Management**: Generate or reuse Ed25519 keypairs
|
|
26
|
-
- **Automatic Signatures**: All authenticated requests signed automatically
|
|
27
36
|
|
|
28
37
|
## Installation
|
|
29
38
|
|
|
@@ -49,27 +58,35 @@ const rondevu = await Rondevu.connect({
|
|
|
49
58
|
await rondevu.publishService({
|
|
50
59
|
service: 'chat:1.0.0',
|
|
51
60
|
maxOffers: 5, // Maintain up to 5 concurrent offers
|
|
52
|
-
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
dc.addEventListener('open', () => {
|
|
57
|
-
console.log('Connection opened!')
|
|
58
|
-
dc.send('Hello from Alice!')
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
dc.addEventListener('message', (e) => {
|
|
62
|
-
console.log('Received:', e.data)
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
const offer = await pc.createOffer()
|
|
66
|
-
await pc.setLocalDescription(offer)
|
|
67
|
-
return { dc, offer }
|
|
61
|
+
connectionConfig: {
|
|
62
|
+
reconnectEnabled: true, // Auto-reconnect on failures
|
|
63
|
+
bufferEnabled: true, // Buffer messages during disconnections
|
|
64
|
+
connectionTimeout: 30000 // 30 second timeout
|
|
68
65
|
}
|
|
69
66
|
})
|
|
70
67
|
|
|
71
68
|
// 3. Start accepting connections
|
|
72
69
|
await rondevu.startFilling()
|
|
70
|
+
|
|
71
|
+
// 4. Handle incoming connections
|
|
72
|
+
rondevu.on('connection:opened', (offerId, connection) => {
|
|
73
|
+
console.log('New connection:', offerId)
|
|
74
|
+
|
|
75
|
+
// Listen for messages
|
|
76
|
+
connection.on('message', (data) => {
|
|
77
|
+
console.log('Received:', data)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// Monitor connection state
|
|
81
|
+
connection.on('connected', () => {
|
|
82
|
+
console.log('Fully connected!')
|
|
83
|
+
connection.send('Hello from Alice!')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
connection.on('disconnected', () => {
|
|
87
|
+
console.log('Connection lost, will auto-reconnect')
|
|
88
|
+
})
|
|
89
|
+
})
|
|
73
90
|
```
|
|
74
91
|
|
|
75
92
|
### Connecting to a Service (Answerer)
|
|
@@ -84,25 +101,38 @@ const rondevu = await Rondevu.connect({
|
|
|
84
101
|
iceServers: 'ipv4-turn'
|
|
85
102
|
})
|
|
86
103
|
|
|
87
|
-
// 2. Connect to service
|
|
104
|
+
// 2. Connect to service - returns AnswererConnection
|
|
88
105
|
const connection = await rondevu.connectToService({
|
|
89
106
|
serviceFqn: 'chat:1.0.0@alice',
|
|
90
|
-
|
|
91
|
-
|
|
107
|
+
connectionConfig: {
|
|
108
|
+
reconnectEnabled: true,
|
|
109
|
+
bufferEnabled: true,
|
|
110
|
+
maxReconnectAttempts: 5
|
|
111
|
+
}
|
|
112
|
+
})
|
|
92
113
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
// 3. Setup event handlers
|
|
115
|
+
connection.on('connected', () => {
|
|
116
|
+
console.log('Connected to alice!')
|
|
117
|
+
connection.send('Hello from Bob!')
|
|
118
|
+
})
|
|
96
119
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
120
|
+
connection.on('message', (data) => {
|
|
121
|
+
console.log('Received:', data)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
// 4. Monitor connection health
|
|
125
|
+
connection.on('reconnecting', (attempt) => {
|
|
126
|
+
console.log(`Reconnecting... attempt ${attempt}`)
|
|
101
127
|
})
|
|
102
128
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
129
|
+
connection.on('reconnect:success', () => {
|
|
130
|
+
console.log('Back online!')
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
connection.on('failed', (error) => {
|
|
134
|
+
console.error('Connection failed:', error)
|
|
135
|
+
})
|
|
106
136
|
```
|
|
107
137
|
|
|
108
138
|
## Core API
|
|
@@ -126,52 +156,299 @@ await rondevu.publishService({
|
|
|
126
156
|
service: string, // e.g., 'chat:1.0.0' (username auto-appended)
|
|
127
157
|
maxOffers: number, // Maximum concurrent offers to maintain
|
|
128
158
|
offerFactory?: OfferFactory, // Optional: custom offer creation
|
|
129
|
-
ttl?: number // Optional: offer lifetime in ms (default: 300000)
|
|
159
|
+
ttl?: number, // Optional: offer lifetime in ms (default: 300000)
|
|
160
|
+
connectionConfig?: Partial<ConnectionConfig> // Optional: durability settings
|
|
130
161
|
})
|
|
131
162
|
|
|
132
163
|
await rondevu.startFilling() // Start accepting connections
|
|
133
164
|
rondevu.stopFilling() // Stop and close all connections
|
|
134
165
|
```
|
|
135
166
|
|
|
167
|
+
### Connecting to Services
|
|
168
|
+
|
|
169
|
+
**⚠️ Breaking Change in v0.18.9+:** `connectToService()` now returns `AnswererConnection` instead of `ConnectionContext`.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// New API (v0.18.9/v0.18.11+)
|
|
173
|
+
const connection = await rondevu.connectToService({
|
|
174
|
+
serviceFqn?: string, // Full FQN like 'chat:1.0.0@alice'
|
|
175
|
+
service?: string, // Service without username (for discovery)
|
|
176
|
+
username?: string, // Target username (combined with service)
|
|
177
|
+
connectionConfig?: Partial<ConnectionConfig>, // Durability settings
|
|
178
|
+
rtcConfig?: RTCConfiguration // Optional: override ICE servers
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// Setup event handlers
|
|
182
|
+
connection.on('connected', () => {
|
|
183
|
+
connection.send('Hello!')
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
connection.on('message', (data) => {
|
|
187
|
+
console.log(data)
|
|
188
|
+
})
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Connection Configuration
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
interface ConnectionConfig {
|
|
195
|
+
// Timeouts
|
|
196
|
+
connectionTimeout: number // Default: 30000ms (30s)
|
|
197
|
+
iceGatheringTimeout: number // Default: 10000ms (10s)
|
|
198
|
+
|
|
199
|
+
// Reconnection
|
|
200
|
+
reconnectEnabled: boolean // Default: true
|
|
201
|
+
maxReconnectAttempts: number // Default: 5 (0 = infinite)
|
|
202
|
+
reconnectBackoffBase: number // Default: 1000ms
|
|
203
|
+
reconnectBackoffMax: number // Default: 30000ms (30s)
|
|
204
|
+
|
|
205
|
+
// Message buffering
|
|
206
|
+
bufferEnabled: boolean // Default: true
|
|
207
|
+
maxBufferSize: number // Default: 100 messages
|
|
208
|
+
maxBufferAge: number // Default: 60000ms (1 min)
|
|
209
|
+
|
|
210
|
+
// Debug
|
|
211
|
+
debug: boolean // Default: false
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Connection Events
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// Lifecycle events
|
|
219
|
+
connection.on('connecting', () => {})
|
|
220
|
+
connection.on('connected', () => {})
|
|
221
|
+
connection.on('disconnected', (reason) => {})
|
|
222
|
+
connection.on('failed', (error) => {})
|
|
223
|
+
connection.on('closed', (reason) => {})
|
|
224
|
+
|
|
225
|
+
// Reconnection events
|
|
226
|
+
connection.on('reconnecting', (attempt) => {})
|
|
227
|
+
connection.on('reconnect:success', () => {})
|
|
228
|
+
connection.on('reconnect:failed', (error) => {})
|
|
229
|
+
connection.on('reconnect:exhausted', (attempts) => {})
|
|
230
|
+
|
|
231
|
+
// Message events
|
|
232
|
+
connection.on('message', (data) => {})
|
|
233
|
+
connection.on('message:buffered', (data) => {})
|
|
234
|
+
connection.on('message:replayed', (message) => {})
|
|
235
|
+
|
|
236
|
+
// ICE events
|
|
237
|
+
connection.on('ice:connection:state', (state) => {})
|
|
238
|
+
connection.on('ice:polling:started', () => {})
|
|
239
|
+
connection.on('ice:polling:stopped', () => {})
|
|
240
|
+
```
|
|
241
|
+
|
|
136
242
|
### Service Discovery
|
|
137
243
|
|
|
138
244
|
```typescript
|
|
139
|
-
//
|
|
140
|
-
await rondevu.
|
|
245
|
+
// Unified discovery API
|
|
246
|
+
const service = await rondevu.findService(
|
|
247
|
+
'chat:1.0.0@alice', // Direct lookup (with username)
|
|
248
|
+
{ mode: 'direct' }
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
const service = await rondevu.findService(
|
|
252
|
+
'chat:1.0.0', // Random discovery (without username)
|
|
253
|
+
{ mode: 'random' }
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
const result = await rondevu.findService(
|
|
257
|
+
'chat:1.0.0',
|
|
258
|
+
{
|
|
259
|
+
mode: 'paginated',
|
|
260
|
+
limit: 20,
|
|
261
|
+
offset: 0
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Migration Guide
|
|
267
|
+
|
|
268
|
+
**Upgrading from v0.18.10 or earlier?** See [MIGRATION.md](./MIGRATION.md) for detailed upgrade instructions.
|
|
141
269
|
|
|
142
|
-
|
|
143
|
-
await rondevu.discoverService('chat:1.0.0')
|
|
270
|
+
### Quick Migration Summary
|
|
144
271
|
|
|
145
|
-
|
|
146
|
-
|
|
272
|
+
**Before (v0.18.7/v0.18.10):**
|
|
273
|
+
```typescript
|
|
274
|
+
const context = await rondevu.connectToService({
|
|
275
|
+
serviceFqn: 'chat:1.0.0@alice',
|
|
276
|
+
onConnection: ({ dc }) => {
|
|
277
|
+
dc.addEventListener('message', (e) => console.log(e.data))
|
|
278
|
+
dc.send('Hello')
|
|
279
|
+
}
|
|
280
|
+
})
|
|
147
281
|
```
|
|
148
282
|
|
|
149
|
-
|
|
283
|
+
**After (v0.18.9/v0.18.11):**
|
|
284
|
+
```typescript
|
|
285
|
+
const connection = await rondevu.connectToService({
|
|
286
|
+
serviceFqn: 'chat:1.0.0@alice'
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
connection.on('connected', () => {
|
|
290
|
+
connection.send('Hello') // Use connection.send()
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
connection.on('message', (data) => {
|
|
294
|
+
console.log(data) // data is already extracted
|
|
295
|
+
})
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Advanced Usage
|
|
299
|
+
|
|
300
|
+
### Custom Offer Factory
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
await rondevu.publishService({
|
|
304
|
+
service: 'file-transfer:1.0.0',
|
|
305
|
+
maxOffers: 3,
|
|
306
|
+
offerFactory: async (pc) => {
|
|
307
|
+
// Customize data channel settings
|
|
308
|
+
const dc = pc.createDataChannel('files', {
|
|
309
|
+
ordered: true,
|
|
310
|
+
maxRetransmits: 10
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
// Add custom listeners
|
|
314
|
+
dc.addEventListener('open', () => {
|
|
315
|
+
console.log('Transfer channel ready')
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
const offer = await pc.createOffer()
|
|
319
|
+
await pc.setLocalDescription(offer)
|
|
320
|
+
return { dc, offer }
|
|
321
|
+
}
|
|
322
|
+
})
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Accessing Raw RTCPeerConnection
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
const connection = await rondevu.connectToService({ ... })
|
|
329
|
+
|
|
330
|
+
// Get raw objects if needed
|
|
331
|
+
const pc = connection.getPeerConnection()
|
|
332
|
+
const dc = connection.getDataChannel()
|
|
333
|
+
|
|
334
|
+
// Note: Using raw DataChannel bypasses buffering/reconnection features
|
|
335
|
+
if (dc) {
|
|
336
|
+
dc.addEventListener('message', (e) => {
|
|
337
|
+
console.log('Raw message:', e.data)
|
|
338
|
+
})
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Disabling Durability Features
|
|
150
343
|
|
|
151
344
|
```typescript
|
|
152
345
|
const connection = await rondevu.connectToService({
|
|
153
|
-
serviceFqn
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
346
|
+
serviceFqn: 'chat:1.0.0@alice',
|
|
347
|
+
connectionConfig: {
|
|
348
|
+
reconnectEnabled: false, // Disable auto-reconnect
|
|
349
|
+
bufferEnabled: false, // Disable message buffering
|
|
350
|
+
}
|
|
158
351
|
})
|
|
159
352
|
```
|
|
160
353
|
|
|
161
354
|
## Documentation
|
|
162
355
|
|
|
356
|
+
📚 **[MIGRATION.md](./MIGRATION.md)** - Upgrade guide from v0.18.7 to v0.18.9
|
|
357
|
+
|
|
163
358
|
📚 **[ADVANCED.md](./ADVANCED.md)** - Comprehensive guide including:
|
|
164
359
|
- Detailed API reference for all methods
|
|
165
360
|
- Type definitions and interfaces
|
|
166
361
|
- Platform support (Browser & Node.js)
|
|
167
362
|
- Advanced usage patterns
|
|
168
363
|
- Username rules and service FQN format
|
|
169
|
-
|
|
364
|
+
|
|
365
|
+
## Connection Persistence (v0.20.0+)
|
|
366
|
+
|
|
367
|
+
Connection objects now persist across disconnections via **"offer rotation"**. When a connection fails, the same connection object is rebound to a new offer instead of being destroyed:
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
rondevu.on('connection:opened', (offerId, connection) => {
|
|
371
|
+
console.log(`Connection ${offerId} opened`)
|
|
372
|
+
|
|
373
|
+
// Listen for offer rotation
|
|
374
|
+
rondevu.on('connection:rotated', (oldOfferId, newOfferId, conn) => {
|
|
375
|
+
if (conn === connection) {
|
|
376
|
+
console.log(`Connection rotated: ${oldOfferId} → ${newOfferId}`)
|
|
377
|
+
// Same connection object! Event listeners still work
|
|
378
|
+
// Message buffer preserved
|
|
379
|
+
}
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
connection.on('message', (data) => {
|
|
383
|
+
console.log('Received:', data)
|
|
384
|
+
// This listener continues working even after rotation
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
connection.on('failed', () => {
|
|
388
|
+
console.log('Connection failed, will auto-rotate to new offer')
|
|
389
|
+
})
|
|
390
|
+
})
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Benefits:**
|
|
394
|
+
- ✅ Same connection object remains usable through disconnections
|
|
395
|
+
- ✅ Message buffer preserved during temporary disconnections
|
|
396
|
+
- ✅ Event listeners don't need to be re-registered
|
|
397
|
+
- ✅ Seamless reconnection experience for offerer side
|
|
170
398
|
|
|
171
399
|
## Examples
|
|
172
400
|
|
|
173
401
|
- [React Demo](https://github.com/xtr-dev/rondevu-demo) - Full browser UI ([live](https://ronde.vu))
|
|
174
402
|
|
|
403
|
+
## Changelog
|
|
404
|
+
|
|
405
|
+
### v0.20.0 (Latest)
|
|
406
|
+
- **Connection Persistence** - OffererConnection objects now persist across disconnections
|
|
407
|
+
- **Offer Rotation** - When connection fails, same object is rebound to new offer
|
|
408
|
+
- **Message Buffering** - Now works seamlessly on offerer side through rotations
|
|
409
|
+
- **New Event**: `connection:rotated` emitted when offer is rotated
|
|
410
|
+
- **Internal**: Added `OffererConnection.rebindToOffer()` method
|
|
411
|
+
- **Internal**: Modified OfferPool failure handler to rotate offers instead of destroying connections
|
|
412
|
+
- **Internal**: Added rotation lock to prevent concurrent rotations
|
|
413
|
+
- **Internal**: Added max rotation attempts limit (default: 5)
|
|
414
|
+
- 100% backward compatible - no breaking changes
|
|
415
|
+
|
|
416
|
+
### v0.19.0
|
|
417
|
+
- **Internal Refactoring** - Improved codebase maintainability (no API changes)
|
|
418
|
+
- Extract OfferPool class for offer lifecycle management
|
|
419
|
+
- Consolidate ICE polling logic (remove ~86 lines of duplicate code)
|
|
420
|
+
- Add AsyncLock utility for race-free concurrent operations
|
|
421
|
+
- Disable reconnection for offerer connections (offers are ephemeral)
|
|
422
|
+
- 100% backward compatible - upgrade without code changes
|
|
423
|
+
|
|
424
|
+
### v0.18.11
|
|
425
|
+
- Restore EventEmitter-based durable connections (same as v0.18.9)
|
|
426
|
+
- Durable WebRTC connections with state machine
|
|
427
|
+
- Automatic reconnection with exponential backoff
|
|
428
|
+
- Message buffering during disconnections
|
|
429
|
+
- ICE polling lifecycle management
|
|
430
|
+
- **Breaking:** `connectToService()` returns `AnswererConnection` instead of `ConnectionContext`
|
|
431
|
+
- See [MIGRATION.md](./MIGRATION.md) for upgrade guide
|
|
432
|
+
|
|
433
|
+
### v0.18.10
|
|
434
|
+
- Temporary revert to callback-based API (reverted in v0.18.11)
|
|
435
|
+
|
|
436
|
+
### v0.18.9
|
|
437
|
+
- Add durable WebRTC connections with state machine
|
|
438
|
+
- Implement automatic reconnection with exponential backoff
|
|
439
|
+
- Add message buffering during disconnections
|
|
440
|
+
- Fix ICE polling lifecycle (stops when connected)
|
|
441
|
+
- Add fillOffers() semaphore to prevent exceeding maxOffers
|
|
442
|
+
- **Breaking:** `connectToService()` returns `AnswererConnection` instead of `ConnectionContext`
|
|
443
|
+
- **Breaking:** `connection:opened` event signature changed
|
|
444
|
+
- See [MIGRATION.md](./MIGRATION.md) for upgrade guide
|
|
445
|
+
|
|
446
|
+
### v0.18.8
|
|
447
|
+
- Initial durable connections implementation
|
|
448
|
+
|
|
449
|
+
### v0.18.3
|
|
450
|
+
- Fix EventEmitter cross-platform compatibility
|
|
451
|
+
|
|
175
452
|
## License
|
|
176
453
|
|
|
177
454
|
MIT
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Rondevu API Client - RPC interface
|
|
3
3
|
*/
|
|
4
|
-
import { CryptoAdapter, Keypair } from '
|
|
5
|
-
import { BatcherOptions } from './
|
|
6
|
-
export type { Keypair } from '
|
|
7
|
-
export type { BatcherOptions } from './
|
|
4
|
+
import { CryptoAdapter, Keypair } from '../crypto/adapter.js';
|
|
5
|
+
import { BatcherOptions } from './batcher.js';
|
|
6
|
+
export type { Keypair } from '../crypto/adapter.js';
|
|
7
|
+
export type { BatcherOptions } from './batcher.js';
|
|
8
8
|
export interface OfferRequest {
|
|
9
9
|
sdp: string;
|
|
10
10
|
}
|
|
@@ -12,8 +12,6 @@ export interface ServiceRequest {
|
|
|
12
12
|
serviceFqn: string;
|
|
13
13
|
offers: OfferRequest[];
|
|
14
14
|
ttl?: number;
|
|
15
|
-
signature: string;
|
|
16
|
-
message: string;
|
|
17
15
|
}
|
|
18
16
|
export interface ServiceOffer {
|
|
19
17
|
offerId: string;
|
|
@@ -45,9 +43,19 @@ export declare class RondevuAPI {
|
|
|
45
43
|
private batcher;
|
|
46
44
|
constructor(baseUrl: string, username: string, keypair: Keypair, cryptoAdapter?: CryptoAdapter, batcherOptions?: BatcherOptions | false);
|
|
47
45
|
/**
|
|
48
|
-
*
|
|
46
|
+
* Create canonical JSON string with sorted keys for deterministic signing
|
|
49
47
|
*/
|
|
50
|
-
private
|
|
48
|
+
private canonicalJSON;
|
|
49
|
+
/**
|
|
50
|
+
* Generate authentication headers for RPC request
|
|
51
|
+
* Signs the payload (method + params + timestamp + username)
|
|
52
|
+
*/
|
|
53
|
+
private generateAuthHeaders;
|
|
54
|
+
/**
|
|
55
|
+
* Generate authentication fields embedded in request body (for batch requests)
|
|
56
|
+
* Signs the payload (method + params + timestamp + username)
|
|
57
|
+
*/
|
|
58
|
+
private generateAuthForRequest;
|
|
51
59
|
/**
|
|
52
60
|
* Execute RPC call with optional batching
|
|
53
61
|
*/
|
|
@@ -58,6 +66,7 @@ export declare class RondevuAPI {
|
|
|
58
66
|
private rpcDirect;
|
|
59
67
|
/**
|
|
60
68
|
* Execute batch RPC calls directly (bypasses batcher)
|
|
69
|
+
* Each request in the batch has its own embedded authentication (signature, timestamp, username, publicKey)
|
|
61
70
|
*/
|
|
62
71
|
private rpcBatchDirect;
|
|
63
72
|
/**
|