@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
package/dist/api.js CHANGED
@@ -1,320 +1,279 @@
1
1
  /**
2
- * Rondevu API Client - Single class for all API endpoints
2
+ * Rondevu API Client - RPC interface
3
3
  */
4
- import * as ed25519 from '@noble/ed25519';
5
- // Set SHA-512 hash function for ed25519 (required in @noble/ed25519 v3+)
6
- ed25519.hashes.sha512Async = async (message) => {
7
- return new Uint8Array(await crypto.subtle.digest('SHA-512', message));
8
- };
4
+ import { WebCryptoAdapter } from './web-crypto-adapter.js';
5
+ import { RpcBatcher } from './rpc-batcher.js';
9
6
  /**
10
- * Helper: Convert Uint8Array to base64 string
11
- */
12
- function bytesToBase64(bytes) {
13
- const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join('');
14
- return btoa(binString);
15
- }
16
- /**
17
- * Helper: Convert base64 string to Uint8Array
18
- */
19
- function base64ToBytes(base64) {
20
- const binString = atob(base64);
21
- return Uint8Array.from(binString, char => char.codePointAt(0));
22
- }
23
- /**
24
- * RondevuAPI - Complete API client for Rondevu signaling server
7
+ * RondevuAPI - RPC-based API client for Rondevu signaling server
25
8
  */
26
9
  export class RondevuAPI {
27
- constructor(baseUrl, credentials) {
10
+ constructor(baseUrl, username, keypair, cryptoAdapter, batcherOptions) {
28
11
  this.baseUrl = baseUrl;
29
- this.credentials = credentials;
30
- }
31
- /**
32
- * Set credentials for authentication
33
- */
34
- setCredentials(credentials) {
35
- this.credentials = credentials;
36
- }
37
- /**
38
- * Authentication header
39
- */
40
- getAuthHeader() {
41
- if (!this.credentials) {
42
- return {};
12
+ this.username = username;
13
+ this.keypair = keypair;
14
+ this.batcher = null;
15
+ // Use WebCryptoAdapter by default (browser environment)
16
+ this.crypto = cryptoAdapter || new WebCryptoAdapter();
17
+ // Create batcher if not explicitly disabled
18
+ if (batcherOptions !== false) {
19
+ this.batcher = new RpcBatcher((requests) => this.rpcBatchDirect(requests), batcherOptions);
43
20
  }
44
- return {
45
- Authorization: `Bearer ${this.credentials.peerId}:${this.credentials.secret}`,
46
- };
47
21
  }
48
- // ============================================
49
- // Ed25519 Cryptography Helpers
50
- // ============================================
51
22
  /**
52
- * Generate an Ed25519 keypair for username claiming and service publishing
23
+ * Generate authentication parameters for RPC calls
53
24
  */
54
- static async generateKeypair() {
55
- const privateKey = ed25519.utils.randomSecretKey();
56
- const publicKey = await ed25519.getPublicKeyAsync(privateKey);
57
- return {
58
- publicKey: bytesToBase64(publicKey),
59
- privateKey: bytesToBase64(privateKey),
60
- };
25
+ async generateAuth(method, params = '') {
26
+ const timestamp = Date.now();
27
+ const message = params
28
+ ? `${method}:${this.username}:${params}:${timestamp}`
29
+ : `${method}:${this.username}:${timestamp}`;
30
+ const signature = await this.crypto.signMessage(message, this.keypair.privateKey);
31
+ return { message, signature };
61
32
  }
62
33
  /**
63
- * Sign a message with an Ed25519 private key
34
+ * Execute RPC call with optional batching
64
35
  */
65
- static async signMessage(message, privateKeyBase64) {
66
- const privateKey = base64ToBytes(privateKeyBase64);
67
- const encoder = new TextEncoder();
68
- const messageBytes = encoder.encode(message);
69
- const signature = await ed25519.signAsync(messageBytes, privateKey);
70
- return bytesToBase64(signature);
36
+ async rpc(request) {
37
+ // Use batcher if enabled
38
+ if (this.batcher) {
39
+ return await this.batcher.add(request);
40
+ }
41
+ // Direct call without batching
42
+ return await this.rpcDirect(request);
71
43
  }
72
44
  /**
73
- * Verify a signature
45
+ * Execute single RPC call directly (bypasses batcher)
74
46
  */
75
- static async verifySignature(message, signatureBase64, publicKeyBase64) {
76
- const publicKey = base64ToBytes(publicKeyBase64);
77
- const signature = base64ToBytes(signatureBase64);
78
- const encoder = new TextEncoder();
79
- const messageBytes = encoder.encode(message);
80
- return await ed25519.verifyAsync(signature, messageBytes, publicKey);
81
- }
82
- // ============================================
83
- // Authentication
84
- // ============================================
85
- /**
86
- * Register a new peer and get credentials
87
- */
88
- async register() {
89
- const response = await fetch(`${this.baseUrl}/register`, {
47
+ async rpcDirect(request) {
48
+ const response = await fetch(`${this.baseUrl}/rpc`, {
90
49
  method: 'POST',
91
50
  headers: { 'Content-Type': 'application/json' },
51
+ body: JSON.stringify(request),
92
52
  });
93
53
  if (!response.ok) {
94
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
95
- throw new Error(`Registration failed: ${error.error || response.statusText}`);
54
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
55
+ }
56
+ const result = await response.json();
57
+ if (!result.success) {
58
+ throw new Error(result.error || 'RPC call failed');
96
59
  }
97
- return await response.json();
60
+ return result.result;
98
61
  }
99
- // ============================================
100
- // Offers
101
- // ============================================
102
62
  /**
103
- * Create one or more offers
63
+ * Execute batch RPC calls directly (bypasses batcher)
104
64
  */
105
- async createOffers(offers) {
106
- const response = await fetch(`${this.baseUrl}/offers`, {
65
+ async rpcBatchDirect(requests) {
66
+ const response = await fetch(`${this.baseUrl}/rpc`, {
107
67
  method: 'POST',
108
- headers: {
109
- 'Content-Type': 'application/json',
110
- ...this.getAuthHeader(),
111
- },
112
- body: JSON.stringify({ offers }),
68
+ headers: { 'Content-Type': 'application/json' },
69
+ body: JSON.stringify(requests),
113
70
  });
114
71
  if (!response.ok) {
115
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
116
- throw new Error(`Failed to create offers: ${error.error || response.statusText}`);
72
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
117
73
  }
118
- return await response.json();
119
- }
120
- /**
121
- * Get offer by ID
122
- */
123
- async getOffer(offerId) {
124
- const response = await fetch(`${this.baseUrl}/offers/${offerId}`, {
125
- headers: this.getAuthHeader(),
126
- });
127
- if (!response.ok) {
128
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
129
- throw new Error(`Failed to get offer: ${error.error || response.statusText}`);
74
+ const results = await response.json();
75
+ // Validate response is an array
76
+ if (!Array.isArray(results)) {
77
+ console.error('Invalid RPC batch response:', results);
78
+ throw new Error('Server returned invalid batch response (not an array)');
79
+ }
80
+ // Check response length matches request length
81
+ if (results.length !== requests.length) {
82
+ console.error(`Response length mismatch: expected ${requests.length}, got ${results.length}`);
130
83
  }
131
- return await response.json();
84
+ return results.map((result, i) => {
85
+ if (!result || typeof result !== 'object') {
86
+ throw new Error(`Invalid response at index ${i}`);
87
+ }
88
+ if (!result.success) {
89
+ throw new Error(result.error || `RPC call ${i} failed`);
90
+ }
91
+ return result.result;
92
+ });
132
93
  }
94
+ // ============================================
95
+ // Ed25519 Cryptography Helpers
96
+ // ============================================
133
97
  /**
134
- * Answer a service
98
+ * Generate an Ed25519 keypair for username claiming and service publishing
99
+ * @param cryptoAdapter - Optional crypto adapter (defaults to WebCryptoAdapter)
135
100
  */
136
- async answerService(serviceUuid, sdp) {
137
- const response = await fetch(`${this.baseUrl}/services/${serviceUuid}/answer`, {
138
- method: 'POST',
139
- headers: {
140
- 'Content-Type': 'application/json',
141
- ...this.getAuthHeader(),
142
- },
143
- body: JSON.stringify({ sdp }),
144
- });
145
- if (!response.ok) {
146
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
147
- throw new Error(`Failed to answer service: ${error.error || response.statusText}`);
148
- }
149
- return await response.json();
101
+ static async generateKeypair(cryptoAdapter) {
102
+ const adapter = cryptoAdapter || new WebCryptoAdapter();
103
+ return await adapter.generateKeypair();
150
104
  }
151
105
  /**
152
- * Get answer for a service (offerer polls this)
106
+ * Sign a message with an Ed25519 private key
107
+ * @param cryptoAdapter - Optional crypto adapter (defaults to WebCryptoAdapter)
153
108
  */
154
- async getServiceAnswer(serviceUuid) {
155
- const response = await fetch(`${this.baseUrl}/services/${serviceUuid}/answer`, {
156
- headers: this.getAuthHeader(),
157
- });
158
- if (!response.ok) {
159
- // 404 means not yet answered
160
- if (response.status === 404) {
161
- return null;
162
- }
163
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
164
- throw new Error(`Failed to get answer: ${error.error || response.statusText}`);
165
- }
166
- const data = await response.json();
167
- return { sdp: data.sdp, offerId: data.offerId };
109
+ static async signMessage(message, privateKeyBase64, cryptoAdapter) {
110
+ const adapter = cryptoAdapter || new WebCryptoAdapter();
111
+ return await adapter.signMessage(message, privateKeyBase64);
168
112
  }
169
113
  /**
170
- * Search offers by topic
114
+ * Verify an Ed25519 signature
115
+ * @param cryptoAdapter - Optional crypto adapter (defaults to WebCryptoAdapter)
171
116
  */
172
- async searchOffers(topic) {
173
- const response = await fetch(`${this.baseUrl}/offers?topic=${encodeURIComponent(topic)}`, {
174
- headers: this.getAuthHeader(),
175
- });
176
- if (!response.ok) {
177
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
178
- throw new Error(`Failed to search offers: ${error.error || response.statusText}`);
179
- }
180
- return await response.json();
117
+ static async verifySignature(message, signatureBase64, publicKeyBase64, cryptoAdapter) {
118
+ const adapter = cryptoAdapter || new WebCryptoAdapter();
119
+ return await adapter.verifySignature(message, signatureBase64, publicKeyBase64);
181
120
  }
182
121
  // ============================================
183
- // ICE Candidates
122
+ // Username Management
184
123
  // ============================================
185
124
  /**
186
- * Add ICE candidates to a service
125
+ * Check if a username is available
187
126
  */
188
- async addServiceIceCandidates(serviceUuid, candidates, offerId) {
189
- const response = await fetch(`${this.baseUrl}/services/${serviceUuid}/ice-candidates`, {
190
- method: 'POST',
191
- headers: {
192
- 'Content-Type': 'application/json',
193
- ...this.getAuthHeader(),
194
- },
195
- body: JSON.stringify({ candidates, offerId }),
127
+ async isUsernameAvailable(username) {
128
+ const auth = await this.generateAuth('getUser', username);
129
+ const result = await this.rpc({
130
+ method: 'getUser',
131
+ message: auth.message,
132
+ signature: auth.signature,
133
+ params: { username },
196
134
  });
197
- if (!response.ok) {
198
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
199
- throw new Error(`Failed to add ICE candidates: ${error.error || response.statusText}`);
200
- }
201
- return await response.json();
135
+ return result.available;
202
136
  }
203
137
  /**
204
- * Get ICE candidates for a service (with polling support)
138
+ * Check if current username is claimed
205
139
  */
206
- async getServiceIceCandidates(serviceUuid, since = 0, offerId) {
207
- const url = new URL(`${this.baseUrl}/services/${serviceUuid}/ice-candidates`);
208
- url.searchParams.set('since', since.toString());
209
- if (offerId) {
210
- url.searchParams.set('offerId', offerId);
211
- }
212
- const response = await fetch(url.toString(), { headers: this.getAuthHeader() });
213
- if (!response.ok) {
214
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
215
- throw new Error(`Failed to get ICE candidates: ${error.error || response.statusText}`);
216
- }
217
- const data = await response.json();
218
- return {
219
- candidates: data.candidates || [],
220
- offerId: data.offerId
221
- };
140
+ async isUsernameClaimed() {
141
+ const auth = await this.generateAuth('getUser', this.username);
142
+ const result = await this.rpc({
143
+ method: 'getUser',
144
+ message: auth.message,
145
+ signature: auth.signature,
146
+ params: { username: this.username },
147
+ });
148
+ return !result.available;
222
149
  }
223
150
  // ============================================
224
- // Services
151
+ // Service Management
225
152
  // ============================================
226
153
  /**
227
154
  * Publish a service
228
155
  */
229
156
  async publishService(service) {
230
- const response = await fetch(`${this.baseUrl}/users/${encodeURIComponent(service.username)}/services`, {
231
- method: 'POST',
232
- headers: {
233
- 'Content-Type': 'application/json',
234
- ...this.getAuthHeader(),
157
+ const auth = await this.generateAuth('publishService', service.serviceFqn);
158
+ return await this.rpc({
159
+ method: 'publishService',
160
+ message: auth.message,
161
+ signature: auth.signature,
162
+ publicKey: this.keypair.publicKey,
163
+ params: {
164
+ serviceFqn: service.serviceFqn,
165
+ offers: service.offers,
166
+ ttl: service.ttl,
235
167
  },
236
- body: JSON.stringify(service),
237
168
  });
238
- if (!response.ok) {
239
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
240
- throw new Error(`Failed to publish service: ${error.error || response.statusText}`);
241
- }
242
- return await response.json();
243
169
  }
244
170
  /**
245
- * Get service by UUID
171
+ * Get service by FQN (direct lookup, random, or paginated)
246
172
  */
247
- async getService(uuid) {
248
- const response = await fetch(`${this.baseUrl}/services/${uuid}`, {
249
- headers: this.getAuthHeader(),
173
+ async getService(serviceFqn, options) {
174
+ const auth = await this.generateAuth('getService', serviceFqn);
175
+ return await this.rpc({
176
+ method: 'getService',
177
+ message: auth.message,
178
+ signature: auth.signature,
179
+ publicKey: this.keypair.publicKey,
180
+ params: {
181
+ serviceFqn,
182
+ ...options,
183
+ },
250
184
  });
251
- if (!response.ok) {
252
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
253
- throw new Error(`Failed to get service: ${error.error || response.statusText}`);
254
- }
255
- return await response.json();
256
185
  }
257
186
  /**
258
- * Search services by username - lists all services for a username
187
+ * Delete a service
259
188
  */
260
- async searchServicesByUsername(username) {
261
- const response = await fetch(`${this.baseUrl}/users/${encodeURIComponent(username)}/services`, { headers: this.getAuthHeader() });
262
- if (!response.ok) {
263
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
264
- throw new Error(`Failed to search services: ${error.error || response.statusText}`);
265
- }
266
- const data = await response.json();
267
- return data.services || [];
189
+ async deleteService(serviceFqn) {
190
+ const auth = await this.generateAuth('deleteService', serviceFqn);
191
+ await this.rpc({
192
+ method: 'deleteService',
193
+ message: auth.message,
194
+ signature: auth.signature,
195
+ publicKey: this.keypair.publicKey,
196
+ params: { serviceFqn },
197
+ });
268
198
  }
199
+ // ============================================
200
+ // WebRTC Signaling
201
+ // ============================================
269
202
  /**
270
- * Search services by username AND FQN - returns full service details
203
+ * Answer an offer
271
204
  */
272
- async searchServices(username, serviceFqn) {
273
- const response = await fetch(`${this.baseUrl}/users/${encodeURIComponent(username)}/services/${encodeURIComponent(serviceFqn)}`, { headers: this.getAuthHeader() });
274
- if (!response.ok) {
275
- if (response.status === 404) {
276
- return [];
205
+ async answerOffer(serviceFqn, offerId, sdp) {
206
+ const auth = await this.generateAuth('answerOffer', offerId);
207
+ await this.rpc({
208
+ method: 'answerOffer',
209
+ message: auth.message,
210
+ signature: auth.signature,
211
+ publicKey: this.keypair.publicKey,
212
+ params: { serviceFqn, offerId, sdp },
213
+ });
214
+ }
215
+ /**
216
+ * Get answer for a specific offer (offerer polls this)
217
+ */
218
+ async getOfferAnswer(serviceFqn, offerId) {
219
+ try {
220
+ const auth = await this.generateAuth('getOfferAnswer', offerId);
221
+ return await this.rpc({
222
+ method: 'getOfferAnswer',
223
+ message: auth.message,
224
+ signature: auth.signature,
225
+ publicKey: this.keypair.publicKey,
226
+ params: { serviceFqn, offerId },
227
+ });
228
+ }
229
+ catch (err) {
230
+ if (err.message.includes('not yet answered')) {
231
+ return null;
277
232
  }
278
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
279
- throw new Error(`Failed to search services: ${error.error || response.statusText}`);
233
+ throw err;
280
234
  }
281
- const service = await response.json();
282
- return [service];
283
235
  }
284
- // ============================================
285
- // Usernames
286
- // ============================================
287
236
  /**
288
- * Check if username is available
237
+ * Combined polling for answers and ICE candidates
289
238
  */
290
- async checkUsername(username) {
291
- const response = await fetch(`${this.baseUrl}/users/${encodeURIComponent(username)}`);
292
- if (!response.ok) {
293
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
294
- throw new Error(`Failed to check username: ${error.error || response.statusText}`);
295
- }
296
- return await response.json();
239
+ async poll(since) {
240
+ const auth = await this.generateAuth('poll');
241
+ return await this.rpc({
242
+ method: 'poll',
243
+ message: auth.message,
244
+ signature: auth.signature,
245
+ publicKey: this.keypair.publicKey,
246
+ params: { since },
247
+ });
297
248
  }
298
249
  /**
299
- * Claim a username (requires Ed25519 signature)
250
+ * Add ICE candidates to a specific offer
300
251
  */
301
- async claimUsername(username, publicKey, signature, message) {
302
- const response = await fetch(`${this.baseUrl}/users/${encodeURIComponent(username)}`, {
303
- method: 'POST',
304
- headers: {
305
- 'Content-Type': 'application/json',
306
- ...this.getAuthHeader(),
307
- },
308
- body: JSON.stringify({
309
- publicKey,
310
- signature,
311
- message,
312
- }),
252
+ async addOfferIceCandidates(serviceFqn, offerId, candidates) {
253
+ const auth = await this.generateAuth('addIceCandidates', offerId);
254
+ return await this.rpc({
255
+ method: 'addIceCandidates',
256
+ message: auth.message,
257
+ signature: auth.signature,
258
+ publicKey: this.keypair.publicKey,
259
+ params: { serviceFqn, offerId, candidates },
313
260
  });
314
- if (!response.ok) {
315
- const error = await response.json().catch(() => ({ error: 'Unknown error' }));
316
- throw new Error(`Failed to claim username: ${error.error || response.statusText}`);
317
- }
318
- return await response.json();
261
+ }
262
+ /**
263
+ * Get ICE candidates for a specific offer
264
+ */
265
+ async getOfferIceCandidates(serviceFqn, offerId, since = 0) {
266
+ const auth = await this.generateAuth('getIceCandidates', `${offerId}:${since}`);
267
+ const result = await this.rpc({
268
+ method: 'getIceCandidates',
269
+ message: auth.message,
270
+ signature: auth.signature,
271
+ publicKey: this.keypair.publicKey,
272
+ params: { serviceFqn, offerId, since },
273
+ });
274
+ return {
275
+ candidates: result.candidates || [],
276
+ offerId: result.offerId,
277
+ };
319
278
  }
320
279
  }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Crypto adapter interface for platform-independent cryptographic operations
3
+ */
4
+ export interface Keypair {
5
+ publicKey: string;
6
+ privateKey: string;
7
+ }
8
+ /**
9
+ * Platform-independent crypto adapter interface
10
+ * Implementations provide platform-specific crypto operations
11
+ */
12
+ export interface CryptoAdapter {
13
+ /**
14
+ * Generate an Ed25519 keypair
15
+ */
16
+ generateKeypair(): Promise<Keypair>;
17
+ /**
18
+ * Sign a message with an Ed25519 private key
19
+ */
20
+ signMessage(message: string, privateKeyBase64: string): Promise<string>;
21
+ /**
22
+ * Verify an Ed25519 signature
23
+ */
24
+ verifySignature(message: string, signatureBase64: string, publicKeyBase64: string): Promise<boolean>;
25
+ /**
26
+ * Convert Uint8Array to base64 string
27
+ */
28
+ bytesToBase64(bytes: Uint8Array): string;
29
+ /**
30
+ * Convert base64 string to Uint8Array
31
+ */
32
+ base64ToBytes(base64: string): Uint8Array;
33
+ /**
34
+ * Generate random bytes
35
+ */
36
+ randomBytes(length: number): Uint8Array;
37
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Crypto adapter interface for platform-independent cryptographic operations
3
+ */
4
+ export {};
package/dist/index.d.ts CHANGED
@@ -2,19 +2,12 @@
2
2
  * @xtr-dev/rondevu-client
3
3
  * WebRTC peer signaling client
4
4
  */
5
- export { EventBus } from './event-bus.js';
5
+ export { Rondevu } from './rondevu.js';
6
6
  export { RondevuAPI } from './api.js';
7
- export { RondevuService } from './rondevu-service.js';
8
- export { RondevuSignaler } from './rondevu-signaler.js';
9
- export { WebRTCContext } from './webrtc-context.js';
10
- export { RTCDurableConnection } from './durable-connection';
11
- export { ServiceHost } from './service-host.js';
12
- export { ServiceClient } from './service-client.js';
13
- export { createBin } from './bin.js';
14
- export type { ConnectionInterface, QueueMessageOptions, Message, ConnectionEvents, Signaler, } from './types.js';
15
- export type { Credentials, Keypair, OfferRequest, Offer, ServiceRequest, Service, IceCandidate, } from './api.js';
16
- export type { Binnable } from './bin.js';
17
- export type { RondevuServiceOptions, PublishServiceOptions } from './rondevu-service.js';
18
- export type { ServiceHostOptions, ServiceHostEvents } from './service-host.js';
19
- export type { ServiceClientOptions, ServiceClientEvents } from './service-client.js';
20
- export type { PollingConfig } from './rondevu-signaler.js';
7
+ export { RpcBatcher } from './rpc-batcher.js';
8
+ export { WebCryptoAdapter } from './web-crypto-adapter.js';
9
+ export { NodeCryptoAdapter } from './node-crypto-adapter.js';
10
+ export type { Signaler, Binnable, } from './types.js';
11
+ export type { Keypair, OfferRequest, ServiceRequest, Service, ServiceOffer, IceCandidate, } from './api.js';
12
+ export type { RondevuOptions, PublishServiceOptions, ConnectToServiceOptions, ConnectionContext, OfferContext, OfferFactory } from './rondevu.js';
13
+ export type { CryptoAdapter } from './crypto-adapter.js';
package/dist/index.js CHANGED
@@ -2,12 +2,9 @@
2
2
  * @xtr-dev/rondevu-client
3
3
  * WebRTC peer signaling client
4
4
  */
5
- export { EventBus } from './event-bus.js';
5
+ export { Rondevu } from './rondevu.js';
6
6
  export { RondevuAPI } from './api.js';
7
- export { RondevuService } from './rondevu-service.js';
8
- export { RondevuSignaler } from './rondevu-signaler.js';
9
- export { WebRTCContext } from './webrtc-context.js';
10
- export { RTCDurableConnection } from './durable-connection';
11
- export { ServiceHost } from './service-host.js';
12
- export { ServiceClient } from './service-client.js';
13
- export { createBin } from './bin.js';
7
+ export { RpcBatcher } from './rpc-batcher.js';
8
+ // Export crypto adapters
9
+ export { WebCryptoAdapter } from './web-crypto-adapter.js';
10
+ export { NodeCryptoAdapter } from './node-crypto-adapter.js';
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Node.js Crypto adapter for Node.js environments
3
+ * Requires Node.js 19+ or Node.js 18 with --experimental-global-webcrypto flag
4
+ */
5
+ import { CryptoAdapter, Keypair } from './crypto-adapter.js';
6
+ /**
7
+ * Node.js Crypto implementation using Node.js built-in APIs
8
+ * Uses Buffer for base64 encoding and crypto.randomBytes for random generation
9
+ *
10
+ * Requirements:
11
+ * - Node.js 19+ (crypto.subtle available globally)
12
+ * - OR Node.js 18 with --experimental-global-webcrypto flag
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { RondevuAPI } from '@xtr-dev/rondevu-client'
17
+ * import { NodeCryptoAdapter } from '@xtr-dev/rondevu-client/node'
18
+ *
19
+ * const api = new RondevuAPI(
20
+ * 'https://signal.example.com',
21
+ * 'alice',
22
+ * keypair,
23
+ * new NodeCryptoAdapter()
24
+ * )
25
+ * ```
26
+ */
27
+ export declare class NodeCryptoAdapter implements CryptoAdapter {
28
+ constructor();
29
+ generateKeypair(): Promise<Keypair>;
30
+ signMessage(message: string, privateKeyBase64: string): Promise<string>;
31
+ verifySignature(message: string, signatureBase64: string, publicKeyBase64: string): Promise<boolean>;
32
+ bytesToBase64(bytes: Uint8Array): string;
33
+ base64ToBytes(base64: string): Uint8Array;
34
+ randomBytes(length: number): Uint8Array;
35
+ }