@xtr-dev/rondevu-client 0.13.0 → 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.
package/dist/rondevu.d.ts CHANGED
@@ -1,22 +1,47 @@
1
- import { RondevuAPI, Credentials, Keypair, Service, IceCandidate } from './api.js';
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[]>;
2
5
  export interface RondevuOptions {
3
6
  apiUrl: string;
4
- username: string;
7
+ username?: string;
5
8
  keypair?: Keypair;
6
- credentials?: Credentials;
9
+ cryptoAdapter?: CryptoAdapter;
10
+ batching?: BatcherOptions | false;
11
+ iceServers?: IceServerPreset | RTCIceServer[];
12
+ debug?: boolean;
7
13
  }
14
+ export interface OfferContext {
15
+ pc: RTCPeerConnection;
16
+ dc?: RTCDataChannel;
17
+ offer: RTCSessionDescriptionInit;
18
+ }
19
+ export type OfferFactory = (rtcConfig: RTCConfiguration) => Promise<OfferContext>;
8
20
  export interface PublishServiceOptions {
9
- serviceFqn: string;
10
- offers: Array<{
11
- sdp: string;
12
- }>;
21
+ service: string;
22
+ maxOffers: number;
23
+ offerFactory?: OfferFactory;
13
24
  ttl?: number;
14
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
+ }
15
40
  /**
16
41
  * Rondevu - Complete WebRTC signaling client
17
42
  *
18
43
  * Provides a unified API for:
19
- * - Username claiming with Ed25519 signatures
44
+ * - Implicit username claiming (auto-claimed on first authenticated request)
20
45
  * - Service publishing with automatic signature generation
21
46
  * - Service discovery (direct, random, paginated)
22
47
  * - WebRTC signaling (offer/answer exchange, ICE relay)
@@ -24,55 +49,173 @@ export interface PublishServiceOptions {
24
49
  *
25
50
  * @example
26
51
  * ```typescript
27
- * // Initialize (generates keypair automatically)
28
- * const rondevu = new Rondevu({
52
+ * // Create and initialize Rondevu instance with preset ICE servers
53
+ * const rondevu = await Rondevu.connect({
29
54
  * apiUrl: 'https://signal.example.com',
30
55
  * username: 'alice',
56
+ * iceServers: 'ipv4-turn' // Use preset: 'ipv4-turn', 'hostname-turns', 'google-stun', or 'relay-only'
31
57
  * })
32
58
  *
33
- * await rondevu.initialize()
34
- *
35
- * // Claim username (one time)
36
- * await rondevu.claimUsername()
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
+ * })
37
68
  *
38
- * // Publish a service
39
- * const publishedService = await rondevu.publishService({
40
- * serviceFqn: 'chat:1.0.0@alice',
41
- * offers: [{ sdp: offerSdp }],
42
- * ttl: 300000,
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
+ * }
43
80
  * })
44
81
  *
45
- * // Discover a service
46
- * const service = await rondevu.getService('chat:1.0.0@bob')
82
+ * // Start accepting connections (auto-fills offers and polls)
83
+ * await rondevu.startFilling()
47
84
  *
48
- * // Post answer
49
- * await rondevu.postOfferAnswer(service.serviceFqn, service.offerId, answerSdp)
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()
50
92
  * ```
51
93
  */
52
94
  export declare class Rondevu {
53
- private readonly api;
54
- private readonly username;
95
+ private static readonly DEFAULT_TTL_MS;
96
+ private static readonly POLLING_INTERVAL_MS;
97
+ private api;
98
+ private readonly apiUrl;
99
+ private username;
55
100
  private keypair;
56
101
  private usernameClaimed;
57
- constructor(options: RondevuOptions);
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;
58
119
  /**
59
- * Initialize the service - generates keypair if not provided
60
- * Call this before using other methods
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
+ * ```
61
129
  */
62
- initialize(): Promise<void>;
130
+ static connect(options: RondevuOptions): Promise<Rondevu>;
63
131
  /**
64
- * Claim the username with Ed25519 signature
65
- * Should be called once before publishing services
132
+ * Generate an anonymous username with timestamp and random component
66
133
  */
67
- claimUsername(): Promise<void>;
134
+ private static generateAnonymousUsername;
68
135
  /**
69
136
  * Check if username has been claimed (checks with server)
70
137
  */
71
138
  isUsernameClaimed(): Promise<boolean>;
72
139
  /**
73
- * Publish a service with automatic signature generation
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
+ * ```
74
217
  */
75
- publishService(options: PublishServiceOptions): Promise<Service>;
218
+ connectToService(options: ConnectToServiceOptions): Promise<ConnectionContext>;
76
219
  /**
77
220
  * Get service by FQN (with username) - Direct lookup
78
221
  * Example: chat:1.0.0@alice
@@ -133,6 +276,25 @@ export declare class Rondevu {
133
276
  answererId: string;
134
277
  answeredAt: number;
135
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
+ }>;
136
298
  /**
137
299
  * Add ICE candidates to specific offer
138
300
  */
@@ -150,7 +312,7 @@ export declare class Rondevu {
150
312
  /**
151
313
  * Get the current keypair (for backup/storage)
152
314
  */
153
- getKeypair(): Keypair | null;
315
+ getKeypair(): Keypair;
154
316
  /**
155
317
  * Get the username
156
318
  */
@@ -158,10 +320,10 @@ export declare class Rondevu {
158
320
  /**
159
321
  * Get the public key
160
322
  */
161
- getPublicKey(): string | null;
323
+ getPublicKey(): string;
162
324
  /**
163
325
  * Access to underlying API for advanced operations
164
326
  * @deprecated Use direct methods on Rondevu instance instead
165
327
  */
166
- getAPI(): RondevuAPI;
328
+ getAPIPublic(): RondevuAPI;
167
329
  }