@xtr-dev/rondevu-client 0.12.4 → 0.17.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 (46) hide show
  1. package/README.md +100 -381
  2. package/dist/api.d.ts +75 -96
  3. package/dist/api.js +202 -243
  4. package/dist/crypto-adapter.d.ts +37 -0
  5. package/dist/crypto-adapter.js +4 -0
  6. package/dist/index.d.ts +8 -15
  7. package/dist/index.js +5 -8
  8. package/dist/node-crypto-adapter.d.ts +35 -0
  9. package/dist/node-crypto-adapter.js +80 -0
  10. package/dist/rondevu-signaler.d.ts +14 -12
  11. package/dist/rondevu-signaler.js +111 -95
  12. package/dist/rondevu.d.ts +329 -0
  13. package/dist/rondevu.js +648 -0
  14. package/dist/rpc-batcher.d.ts +61 -0
  15. package/dist/rpc-batcher.js +111 -0
  16. package/dist/types.d.ts +8 -21
  17. package/dist/types.js +4 -6
  18. package/dist/web-crypto-adapter.d.ts +16 -0
  19. package/dist/web-crypto-adapter.js +52 -0
  20. package/package.json +1 -1
  21. package/dist/bin.d.ts +0 -35
  22. package/dist/bin.js +0 -35
  23. package/dist/connection-manager.d.ts +0 -104
  24. package/dist/connection-manager.js +0 -324
  25. package/dist/connection.d.ts +0 -112
  26. package/dist/connection.js +0 -194
  27. package/dist/durable-connection.d.ts +0 -120
  28. package/dist/durable-connection.js +0 -244
  29. package/dist/event-bus.d.ts +0 -52
  30. package/dist/event-bus.js +0 -84
  31. package/dist/noop-signaler.d.ts +0 -14
  32. package/dist/noop-signaler.js +0 -27
  33. package/dist/quick-start.d.ts +0 -29
  34. package/dist/quick-start.js +0 -44
  35. package/dist/rondevu-context.d.ts +0 -10
  36. package/dist/rondevu-context.js +0 -20
  37. package/dist/rondevu-service.d.ts +0 -87
  38. package/dist/rondevu-service.js +0 -170
  39. package/dist/service-client.d.ts +0 -77
  40. package/dist/service-client.js +0 -158
  41. package/dist/service-host.d.ts +0 -67
  42. package/dist/service-host.js +0 -120
  43. package/dist/signaler.d.ts +0 -25
  44. package/dist/signaler.js +0 -89
  45. package/dist/webrtc-context.d.ts +0 -5
  46. package/dist/webrtc-context.js +0 -35
@@ -0,0 +1,329 @@
1
+ import { RondevuAPI, Keypair, IceCandidate, BatcherOptions } from './api.js';
2
+ import { CryptoAdapter } from './crypto-adapter.js';
3
+ export type IceServerPreset = 'ipv4-turn' | 'hostname-turns' | 'google-stun' | 'relay-only';
4
+ export declare const ICE_SERVER_PRESETS: Record<IceServerPreset, RTCIceServer[]>;
5
+ export interface RondevuOptions {
6
+ apiUrl: string;
7
+ username?: string;
8
+ keypair?: Keypair;
9
+ cryptoAdapter?: CryptoAdapter;
10
+ batching?: BatcherOptions | false;
11
+ iceServers?: IceServerPreset | RTCIceServer[];
12
+ debug?: boolean;
13
+ }
14
+ export interface OfferContext {
15
+ pc: RTCPeerConnection;
16
+ dc?: RTCDataChannel;
17
+ offer: RTCSessionDescriptionInit;
18
+ }
19
+ export type OfferFactory = (rtcConfig: RTCConfiguration) => Promise<OfferContext>;
20
+ export interface PublishServiceOptions {
21
+ service: string;
22
+ maxOffers: number;
23
+ offerFactory?: OfferFactory;
24
+ ttl?: number;
25
+ }
26
+ export interface ConnectionContext {
27
+ pc: RTCPeerConnection;
28
+ dc: RTCDataChannel;
29
+ serviceFqn: string;
30
+ offerId: string;
31
+ peerUsername: string;
32
+ }
33
+ export interface ConnectToServiceOptions {
34
+ serviceFqn?: string;
35
+ service?: string;
36
+ username?: string;
37
+ onConnection?: (context: ConnectionContext) => void | Promise<void>;
38
+ rtcConfig?: RTCConfiguration;
39
+ }
40
+ /**
41
+ * Rondevu - Complete WebRTC signaling client
42
+ *
43
+ * Provides a unified API for:
44
+ * - Implicit username claiming (auto-claimed on first authenticated request)
45
+ * - Service publishing with automatic signature generation
46
+ * - Service discovery (direct, random, paginated)
47
+ * - WebRTC signaling (offer/answer exchange, ICE relay)
48
+ * - Keypair management
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * // Create and initialize Rondevu instance with preset ICE servers
53
+ * const rondevu = await Rondevu.connect({
54
+ * apiUrl: 'https://signal.example.com',
55
+ * username: 'alice',
56
+ * iceServers: 'ipv4-turn' // Use preset: 'ipv4-turn', 'hostname-turns', 'google-stun', or 'relay-only'
57
+ * })
58
+ *
59
+ * // Or use custom ICE servers
60
+ * const rondevu2 = await Rondevu.connect({
61
+ * apiUrl: 'https://signal.example.com',
62
+ * username: 'bob',
63
+ * iceServers: [
64
+ * { urls: 'stun:stun.l.google.com:19302' },
65
+ * { urls: 'turn:turn.example.com:3478', username: 'user', credential: 'pass' }
66
+ * ]
67
+ * })
68
+ *
69
+ * // Publish a service with automatic offer management
70
+ * await rondevu.publishService({
71
+ * service: 'chat:2.0.0',
72
+ * maxOffers: 5, // Maintain up to 5 concurrent offers
73
+ * offerFactory: async (rtcConfig) => {
74
+ * const pc = new RTCPeerConnection(rtcConfig)
75
+ * const dc = pc.createDataChannel('chat')
76
+ * const offer = await pc.createOffer()
77
+ * await pc.setLocalDescription(offer)
78
+ * return { pc, dc, offer }
79
+ * }
80
+ * })
81
+ *
82
+ * // Start accepting connections (auto-fills offers and polls)
83
+ * await rondevu.startFilling()
84
+ *
85
+ * // Access active connections
86
+ * for (const offer of rondevu.getActiveOffers()) {
87
+ * offer.dc?.addEventListener('message', (e) => console.log(e.data))
88
+ * }
89
+ *
90
+ * // Stop when done
91
+ * rondevu.stopFilling()
92
+ * ```
93
+ */
94
+ export declare class Rondevu {
95
+ private static readonly DEFAULT_TTL_MS;
96
+ private static readonly POLLING_INTERVAL_MS;
97
+ private api;
98
+ private readonly apiUrl;
99
+ private username;
100
+ private keypair;
101
+ private usernameClaimed;
102
+ private cryptoAdapter?;
103
+ private batchingOptions?;
104
+ private iceServers;
105
+ private debugEnabled;
106
+ private currentService;
107
+ private maxOffers;
108
+ private offerFactory;
109
+ private ttl;
110
+ private activeOffers;
111
+ private filling;
112
+ private pollingInterval;
113
+ private lastPollTimestamp;
114
+ private constructor();
115
+ /**
116
+ * Internal debug logging - only logs if debug mode is enabled
117
+ */
118
+ private debug;
119
+ /**
120
+ * Create and initialize a Rondevu client
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const rondevu = await Rondevu.connect({
125
+ * apiUrl: 'https://api.ronde.vu',
126
+ * username: 'alice'
127
+ * })
128
+ * ```
129
+ */
130
+ static connect(options: RondevuOptions): Promise<Rondevu>;
131
+ /**
132
+ * Generate an anonymous username with timestamp and random component
133
+ */
134
+ private static generateAnonymousUsername;
135
+ /**
136
+ * Check if username has been claimed (checks with server)
137
+ */
138
+ isUsernameClaimed(): Promise<boolean>;
139
+ /**
140
+ * Default offer factory - creates a simple data channel connection
141
+ */
142
+ private defaultOfferFactory;
143
+ /**
144
+ * Publish a service with automatic offer management
145
+ * Call startFilling() to begin accepting connections
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * await rondevu.publishService({
150
+ * service: 'chat:2.0.0',
151
+ * maxOffers: 5
152
+ * })
153
+ * await rondevu.startFilling()
154
+ * ```
155
+ */
156
+ publishService(options: PublishServiceOptions): Promise<void>;
157
+ /**
158
+ * Set up ICE candidate handler to send candidates to the server
159
+ */
160
+ private setupIceCandidateHandler;
161
+ /**
162
+ * Create a single offer and publish it to the server
163
+ */
164
+ private createOffer;
165
+ /**
166
+ * Fill offers to reach maxOffers count
167
+ */
168
+ private fillOffers;
169
+ /**
170
+ * Poll for answers and ICE candidates (internal use for automatic offer management)
171
+ */
172
+ private pollInternal;
173
+ /**
174
+ * Start filling offers and polling for answers/ICE
175
+ * Call this after publishService() to begin accepting connections
176
+ */
177
+ startFilling(): Promise<void>;
178
+ /**
179
+ * Stop filling offers and polling
180
+ * Closes all active peer connections
181
+ */
182
+ stopFilling(): void;
183
+ /**
184
+ * Resolve the full service FQN from various input options
185
+ * Supports direct FQN, service+username, or service discovery
186
+ */
187
+ private resolveServiceFqn;
188
+ /**
189
+ * Start polling for remote ICE candidates
190
+ * Returns the polling interval ID
191
+ */
192
+ private startIcePolling;
193
+ /**
194
+ * Automatically connect to a service (answerer side)
195
+ * Handles the entire connection flow: discovery, WebRTC setup, answer exchange, ICE candidates
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * // Connect to specific user
200
+ * const connection = await rondevu.connectToService({
201
+ * serviceFqn: 'chat:2.0.0@alice',
202
+ * onConnection: ({ dc, peerUsername }) => {
203
+ * console.log('Connected to', peerUsername)
204
+ * dc.addEventListener('message', (e) => console.log(e.data))
205
+ * dc.addEventListener('open', () => dc.send('Hello!'))
206
+ * }
207
+ * })
208
+ *
209
+ * // Discover random service
210
+ * const connection = await rondevu.connectToService({
211
+ * service: 'chat:2.0.0',
212
+ * onConnection: ({ dc, peerUsername }) => {
213
+ * console.log('Connected to', peerUsername)
214
+ * }
215
+ * })
216
+ * ```
217
+ */
218
+ connectToService(options: ConnectToServiceOptions): Promise<ConnectionContext>;
219
+ /**
220
+ * Get service by FQN (with username) - Direct lookup
221
+ * Example: chat:1.0.0@alice
222
+ */
223
+ getService(serviceFqn: string): Promise<{
224
+ serviceId: string;
225
+ username: string;
226
+ serviceFqn: string;
227
+ offerId: string;
228
+ sdp: string;
229
+ createdAt: number;
230
+ expiresAt: number;
231
+ }>;
232
+ /**
233
+ * Discover a random available service without knowing the username
234
+ * Example: chat:1.0.0 (without @username)
235
+ */
236
+ discoverService(serviceVersion: string): Promise<{
237
+ serviceId: string;
238
+ username: string;
239
+ serviceFqn: string;
240
+ offerId: string;
241
+ sdp: string;
242
+ createdAt: number;
243
+ expiresAt: number;
244
+ }>;
245
+ /**
246
+ * Discover multiple available services with pagination
247
+ * Example: chat:1.0.0 (without @username)
248
+ */
249
+ discoverServices(serviceVersion: string, limit?: number, offset?: number): Promise<{
250
+ services: Array<{
251
+ serviceId: string;
252
+ username: string;
253
+ serviceFqn: string;
254
+ offerId: string;
255
+ sdp: string;
256
+ createdAt: number;
257
+ expiresAt: number;
258
+ }>;
259
+ count: number;
260
+ limit: number;
261
+ offset: number;
262
+ }>;
263
+ /**
264
+ * Post answer SDP to specific offer
265
+ */
266
+ postOfferAnswer(serviceFqn: string, offerId: string, sdp: string): Promise<{
267
+ success: boolean;
268
+ offerId: string;
269
+ }>;
270
+ /**
271
+ * Get answer SDP (offerer polls this)
272
+ */
273
+ getOfferAnswer(serviceFqn: string, offerId: string): Promise<{
274
+ sdp: string;
275
+ offerId: string;
276
+ answererId: string;
277
+ answeredAt: number;
278
+ } | null>;
279
+ /**
280
+ * Combined polling for answers and ICE candidates
281
+ * Returns all answered offers and ICE candidates for all peer's offers since timestamp
282
+ */
283
+ poll(since?: number): Promise<{
284
+ answers: Array<{
285
+ offerId: string;
286
+ serviceId?: string;
287
+ answererId: string;
288
+ sdp: string;
289
+ answeredAt: number;
290
+ }>;
291
+ iceCandidates: Record<string, Array<{
292
+ candidate: RTCIceCandidateInit | null;
293
+ role: 'offerer' | 'answerer';
294
+ peerId: string;
295
+ createdAt: number;
296
+ }>>;
297
+ }>;
298
+ /**
299
+ * Add ICE candidates to specific offer
300
+ */
301
+ addOfferIceCandidates(serviceFqn: string, offerId: string, candidates: RTCIceCandidateInit[]): Promise<{
302
+ count: number;
303
+ offerId: string;
304
+ }>;
305
+ /**
306
+ * Get ICE candidates for specific offer (with polling support)
307
+ */
308
+ getOfferIceCandidates(serviceFqn: string, offerId: string, since?: number): Promise<{
309
+ candidates: IceCandidate[];
310
+ offerId: string;
311
+ }>;
312
+ /**
313
+ * Get the current keypair (for backup/storage)
314
+ */
315
+ getKeypair(): Keypair;
316
+ /**
317
+ * Get the username
318
+ */
319
+ getUsername(): string;
320
+ /**
321
+ * Get the public key
322
+ */
323
+ getPublicKey(): string;
324
+ /**
325
+ * Access to underlying API for advanced operations
326
+ * @deprecated Use direct methods on Rondevu instance instead
327
+ */
328
+ getAPIPublic(): RondevuAPI;
329
+ }