@xtr-dev/rondevu-client 0.13.0 → 0.17.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 +100 -381
- package/dist/api.d.ts +67 -116
- package/dist/api.js +201 -244
- package/dist/crypto-adapter.d.ts +37 -0
- package/dist/crypto-adapter.js +4 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +4 -1
- package/dist/node-crypto-adapter.d.ts +35 -0
- package/dist/node-crypto-adapter.js +80 -0
- package/dist/rondevu-signaler.d.ts +10 -7
- package/dist/rondevu-signaler.js +96 -64
- package/dist/rondevu.d.ts +199 -37
- package/dist/rondevu.js +519 -103
- package/dist/rpc-batcher.d.ts +61 -0
- package/dist/rpc-batcher.js +111 -0
- package/dist/web-crypto-adapter.d.ts +16 -0
- package/dist/web-crypto-adapter.js +52 -0
- package/package.json +1 -1
package/dist/rondevu.d.ts
CHANGED
|
@@ -1,22 +1,47 @@
|
|
|
1
|
-
import { RondevuAPI,
|
|
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
|
|
7
|
+
username?: string;
|
|
5
8
|
keypair?: Keypair;
|
|
6
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
* -
|
|
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
|
-
* //
|
|
28
|
-
* const 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
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
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
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
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
|
-
* //
|
|
46
|
-
*
|
|
82
|
+
* // Start accepting connections (auto-fills offers and polls)
|
|
83
|
+
* await rondevu.startFilling()
|
|
47
84
|
*
|
|
48
|
-
* //
|
|
49
|
-
*
|
|
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
|
|
54
|
-
private readonly
|
|
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
|
-
|
|
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
|
-
*
|
|
60
|
-
*
|
|
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
|
-
|
|
130
|
+
static connect(options: RondevuOptions): Promise<Rondevu>;
|
|
63
131
|
/**
|
|
64
|
-
*
|
|
65
|
-
* Should be called once before publishing services
|
|
132
|
+
* Generate an anonymous username with timestamp and random component
|
|
66
133
|
*/
|
|
67
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
328
|
+
getAPIPublic(): RondevuAPI;
|
|
167
329
|
}
|