@xtr-dev/rondevu-client 0.18.10 → 0.21.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.
Files changed (70) hide show
  1. package/README.md +92 -117
  2. package/dist/api/batcher.d.ts +83 -0
  3. package/dist/api/batcher.js +155 -0
  4. package/dist/api/client.d.ts +198 -0
  5. package/dist/api/client.js +400 -0
  6. package/dist/{answerer-connection.d.ts → connections/answerer.d.ts} +25 -8
  7. package/dist/{answerer-connection.js → connections/answerer.js} +70 -48
  8. package/dist/{connection.d.ts → connections/base.d.ts} +30 -7
  9. package/dist/{connection.js → connections/base.js} +65 -14
  10. package/dist/connections/config.d.ts +51 -0
  11. package/dist/{connection-config.js → connections/config.js} +20 -0
  12. package/dist/{connection-events.d.ts → connections/events.d.ts} +6 -6
  13. package/dist/connections/offerer.d.ts +108 -0
  14. package/dist/connections/offerer.js +306 -0
  15. package/dist/core/ice-config.d.ts +35 -0
  16. package/dist/core/ice-config.js +111 -0
  17. package/dist/core/index.d.ts +22 -0
  18. package/dist/core/index.js +22 -0
  19. package/dist/core/offer-pool.d.ts +113 -0
  20. package/dist/core/offer-pool.js +281 -0
  21. package/dist/core/peer.d.ts +155 -0
  22. package/dist/core/peer.js +252 -0
  23. package/dist/core/polling-manager.d.ts +71 -0
  24. package/dist/core/polling-manager.js +122 -0
  25. package/dist/core/rondevu-errors.d.ts +59 -0
  26. package/dist/core/rondevu-errors.js +75 -0
  27. package/dist/core/rondevu-types.d.ts +125 -0
  28. package/dist/core/rondevu-types.js +6 -0
  29. package/dist/core/rondevu.d.ts +296 -0
  30. package/dist/core/rondevu.js +472 -0
  31. package/dist/crypto/adapter.d.ts +53 -0
  32. package/dist/crypto/node.d.ts +57 -0
  33. package/dist/crypto/node.js +149 -0
  34. package/dist/crypto/web.d.ts +38 -0
  35. package/dist/crypto/web.js +129 -0
  36. package/dist/utils/async-lock.d.ts +42 -0
  37. package/dist/utils/async-lock.js +75 -0
  38. package/dist/{message-buffer.d.ts → utils/message-buffer.d.ts} +1 -1
  39. package/dist/{message-buffer.js → utils/message-buffer.js} +4 -4
  40. package/dist/webrtc/adapter.d.ts +22 -0
  41. package/dist/webrtc/adapter.js +5 -0
  42. package/dist/webrtc/browser.d.ts +12 -0
  43. package/dist/webrtc/browser.js +15 -0
  44. package/dist/webrtc/node.d.ts +32 -0
  45. package/dist/webrtc/node.js +32 -0
  46. package/package.json +20 -9
  47. package/dist/api.d.ts +0 -146
  48. package/dist/api.js +0 -279
  49. package/dist/connection-config.d.ts +0 -21
  50. package/dist/crypto-adapter.d.ts +0 -37
  51. package/dist/index.d.ts +0 -13
  52. package/dist/index.js +0 -10
  53. package/dist/node-crypto-adapter.d.ts +0 -35
  54. package/dist/node-crypto-adapter.js +0 -78
  55. package/dist/offerer-connection.d.ts +0 -54
  56. package/dist/offerer-connection.js +0 -177
  57. package/dist/rondevu-signaler.d.ts +0 -112
  58. package/dist/rondevu-signaler.js +0 -401
  59. package/dist/rondevu.d.ts +0 -407
  60. package/dist/rondevu.js +0 -847
  61. package/dist/rpc-batcher.d.ts +0 -61
  62. package/dist/rpc-batcher.js +0 -111
  63. package/dist/web-crypto-adapter.d.ts +0 -16
  64. package/dist/web-crypto-adapter.js +0 -52
  65. /package/dist/{connection-events.js → connections/events.js} +0 -0
  66. /package/dist/{types.d.ts → core/types.d.ts} +0 -0
  67. /package/dist/{types.js → core/types.js} +0 -0
  68. /package/dist/{crypto-adapter.js → crypto/adapter.js} +0 -0
  69. /package/dist/{exponential-backoff.d.ts → utils/exponential-backoff.d.ts} +0 -0
  70. /package/dist/{exponential-backoff.js → utils/exponential-backoff.js} +0 -0
package/dist/api.d.ts DELETED
@@ -1,146 +0,0 @@
1
- /**
2
- * Rondevu API Client - RPC interface
3
- */
4
- import { CryptoAdapter, Keypair } from './crypto-adapter.js';
5
- import { BatcherOptions } from './rpc-batcher.js';
6
- export type { Keypair } from './crypto-adapter.js';
7
- export type { BatcherOptions } from './rpc-batcher.js';
8
- export interface OfferRequest {
9
- sdp: string;
10
- }
11
- export interface ServiceRequest {
12
- serviceFqn: string;
13
- offers: OfferRequest[];
14
- ttl?: number;
15
- signature: string;
16
- message: string;
17
- }
18
- export interface ServiceOffer {
19
- offerId: string;
20
- sdp: string;
21
- createdAt: number;
22
- expiresAt: number;
23
- }
24
- export interface Service {
25
- serviceId: string;
26
- offers: ServiceOffer[];
27
- username: string;
28
- serviceFqn: string;
29
- createdAt: number;
30
- expiresAt: number;
31
- }
32
- export interface IceCandidate {
33
- candidate: RTCIceCandidateInit | null;
34
- role: 'offerer' | 'answerer';
35
- createdAt: number;
36
- }
37
- /**
38
- * RondevuAPI - RPC-based API client for Rondevu signaling server
39
- */
40
- export declare class RondevuAPI {
41
- private baseUrl;
42
- private username;
43
- private keypair;
44
- private crypto;
45
- private batcher;
46
- constructor(baseUrl: string, username: string, keypair: Keypair, cryptoAdapter?: CryptoAdapter, batcherOptions?: BatcherOptions | false);
47
- /**
48
- * Generate authentication parameters for RPC calls
49
- */
50
- private generateAuth;
51
- /**
52
- * Execute RPC call with optional batching
53
- */
54
- private rpc;
55
- /**
56
- * Execute single RPC call directly (bypasses batcher)
57
- */
58
- private rpcDirect;
59
- /**
60
- * Execute batch RPC calls directly (bypasses batcher)
61
- */
62
- private rpcBatchDirect;
63
- /**
64
- * Generate an Ed25519 keypair for username claiming and service publishing
65
- * @param cryptoAdapter - Optional crypto adapter (defaults to WebCryptoAdapter)
66
- */
67
- static generateKeypair(cryptoAdapter?: CryptoAdapter): Promise<Keypair>;
68
- /**
69
- * Sign a message with an Ed25519 private key
70
- * @param cryptoAdapter - Optional crypto adapter (defaults to WebCryptoAdapter)
71
- */
72
- static signMessage(message: string, privateKeyBase64: string, cryptoAdapter?: CryptoAdapter): Promise<string>;
73
- /**
74
- * Verify an Ed25519 signature
75
- * @param cryptoAdapter - Optional crypto adapter (defaults to WebCryptoAdapter)
76
- */
77
- static verifySignature(message: string, signatureBase64: string, publicKeyBase64: string, cryptoAdapter?: CryptoAdapter): Promise<boolean>;
78
- /**
79
- * Check if a username is available
80
- */
81
- isUsernameAvailable(username: string): Promise<boolean>;
82
- /**
83
- * Check if current username is claimed
84
- */
85
- isUsernameClaimed(): Promise<boolean>;
86
- /**
87
- * Publish a service
88
- */
89
- publishService(service: ServiceRequest): Promise<Service>;
90
- /**
91
- * Get service by FQN (direct lookup, random, or paginated)
92
- */
93
- getService(serviceFqn: string, options?: {
94
- limit?: number;
95
- offset?: number;
96
- }): Promise<any>;
97
- /**
98
- * Delete a service
99
- */
100
- deleteService(serviceFqn: string): Promise<void>;
101
- /**
102
- * Answer an offer
103
- */
104
- answerOffer(serviceFqn: string, offerId: string, sdp: string): Promise<void>;
105
- /**
106
- * Get answer for a specific offer (offerer polls this)
107
- */
108
- getOfferAnswer(serviceFqn: string, offerId: string): Promise<{
109
- sdp: string;
110
- offerId: string;
111
- answererId: string;
112
- answeredAt: number;
113
- } | null>;
114
- /**
115
- * Combined polling for answers and ICE candidates
116
- */
117
- poll(since?: number): Promise<{
118
- answers: Array<{
119
- offerId: string;
120
- serviceId?: string;
121
- answererId: string;
122
- sdp: string;
123
- answeredAt: number;
124
- }>;
125
- iceCandidates: Record<string, Array<{
126
- candidate: RTCIceCandidateInit | null;
127
- role: 'offerer' | 'answerer';
128
- peerId: string;
129
- createdAt: number;
130
- }>>;
131
- }>;
132
- /**
133
- * Add ICE candidates to a specific offer
134
- */
135
- addOfferIceCandidates(serviceFqn: string, offerId: string, candidates: RTCIceCandidateInit[]): Promise<{
136
- count: number;
137
- offerId: string;
138
- }>;
139
- /**
140
- * Get ICE candidates for a specific offer
141
- */
142
- getOfferIceCandidates(serviceFqn: string, offerId: string, since?: number): Promise<{
143
- candidates: IceCandidate[];
144
- offerId: string;
145
- }>;
146
- }
package/dist/api.js DELETED
@@ -1,279 +0,0 @@
1
- /**
2
- * Rondevu API Client - RPC interface
3
- */
4
- import { WebCryptoAdapter } from './web-crypto-adapter.js';
5
- import { RpcBatcher } from './rpc-batcher.js';
6
- /**
7
- * RondevuAPI - RPC-based API client for Rondevu signaling server
8
- */
9
- export class RondevuAPI {
10
- constructor(baseUrl, username, keypair, cryptoAdapter, batcherOptions) {
11
- this.baseUrl = baseUrl;
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);
20
- }
21
- }
22
- /**
23
- * Generate authentication parameters for RPC calls
24
- */
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 };
32
- }
33
- /**
34
- * Execute RPC call with optional batching
35
- */
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);
43
- }
44
- /**
45
- * Execute single RPC call directly (bypasses batcher)
46
- */
47
- async rpcDirect(request) {
48
- const response = await fetch(`${this.baseUrl}/rpc`, {
49
- method: 'POST',
50
- headers: { 'Content-Type': 'application/json' },
51
- body: JSON.stringify(request),
52
- });
53
- if (!response.ok) {
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');
59
- }
60
- return result.result;
61
- }
62
- /**
63
- * Execute batch RPC calls directly (bypasses batcher)
64
- */
65
- async rpcBatchDirect(requests) {
66
- const response = await fetch(`${this.baseUrl}/rpc`, {
67
- method: 'POST',
68
- headers: { 'Content-Type': 'application/json' },
69
- body: JSON.stringify(requests),
70
- });
71
- if (!response.ok) {
72
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
73
- }
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}`);
83
- }
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
- });
93
- }
94
- // ============================================
95
- // Ed25519 Cryptography Helpers
96
- // ============================================
97
- /**
98
- * Generate an Ed25519 keypair for username claiming and service publishing
99
- * @param cryptoAdapter - Optional crypto adapter (defaults to WebCryptoAdapter)
100
- */
101
- static async generateKeypair(cryptoAdapter) {
102
- const adapter = cryptoAdapter || new WebCryptoAdapter();
103
- return await adapter.generateKeypair();
104
- }
105
- /**
106
- * Sign a message with an Ed25519 private key
107
- * @param cryptoAdapter - Optional crypto adapter (defaults to WebCryptoAdapter)
108
- */
109
- static async signMessage(message, privateKeyBase64, cryptoAdapter) {
110
- const adapter = cryptoAdapter || new WebCryptoAdapter();
111
- return await adapter.signMessage(message, privateKeyBase64);
112
- }
113
- /**
114
- * Verify an Ed25519 signature
115
- * @param cryptoAdapter - Optional crypto adapter (defaults to WebCryptoAdapter)
116
- */
117
- static async verifySignature(message, signatureBase64, publicKeyBase64, cryptoAdapter) {
118
- const adapter = cryptoAdapter || new WebCryptoAdapter();
119
- return await adapter.verifySignature(message, signatureBase64, publicKeyBase64);
120
- }
121
- // ============================================
122
- // Username Management
123
- // ============================================
124
- /**
125
- * Check if a username is available
126
- */
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 },
134
- });
135
- return result.available;
136
- }
137
- /**
138
- * Check if current username is claimed
139
- */
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;
149
- }
150
- // ============================================
151
- // Service Management
152
- // ============================================
153
- /**
154
- * Publish a service
155
- */
156
- async publishService(service) {
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,
167
- },
168
- });
169
- }
170
- /**
171
- * Get service by FQN (direct lookup, random, or paginated)
172
- */
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
- },
184
- });
185
- }
186
- /**
187
- * Delete a service
188
- */
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
- });
198
- }
199
- // ============================================
200
- // WebRTC Signaling
201
- // ============================================
202
- /**
203
- * Answer an offer
204
- */
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;
232
- }
233
- throw err;
234
- }
235
- }
236
- /**
237
- * Combined polling for answers and ICE candidates
238
- */
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
- });
248
- }
249
- /**
250
- * Add ICE candidates to a specific offer
251
- */
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 },
260
- });
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
- };
278
- }
279
- }
@@ -1,21 +0,0 @@
1
- /**
2
- * Connection configuration interfaces and defaults
3
- */
4
- export interface ConnectionConfig {
5
- connectionTimeout: number;
6
- iceGatheringTimeout: number;
7
- reconnectEnabled: boolean;
8
- maxReconnectAttempts: number;
9
- reconnectBackoffBase: number;
10
- reconnectBackoffMax: number;
11
- reconnectJitter: number;
12
- bufferEnabled: boolean;
13
- maxBufferSize: number;
14
- maxBufferAge: number;
15
- preserveBufferOnClose: boolean;
16
- icePollingInterval: number;
17
- icePollingTimeout: number;
18
- debug: boolean;
19
- }
20
- export declare const DEFAULT_CONNECTION_CONFIG: ConnectionConfig;
21
- export declare function mergeConnectionConfig(userConfig?: Partial<ConnectionConfig>): ConnectionConfig;
@@ -1,37 +0,0 @@
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
- }
package/dist/index.d.ts DELETED
@@ -1,13 +0,0 @@
1
- /**
2
- * @xtr-dev/rondevu-client
3
- * WebRTC peer signaling client
4
- */
5
- export { Rondevu, RondevuError, NetworkError, ValidationError, ConnectionError } from './rondevu.js';
6
- export { RondevuAPI } from './api.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, ActiveOffer, FindServiceOptions, ServiceResult, PaginatedServiceResult } from './rondevu.js';
13
- export type { CryptoAdapter } from './crypto-adapter.js';
package/dist/index.js DELETED
@@ -1,10 +0,0 @@
1
- /**
2
- * @xtr-dev/rondevu-client
3
- * WebRTC peer signaling client
4
- */
5
- export { Rondevu, RondevuError, NetworkError, ValidationError, ConnectionError } from './rondevu.js';
6
- export { RondevuAPI } from './api.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';
@@ -1,35 +0,0 @@
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
- }
@@ -1,78 +0,0 @@
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 * as ed25519 from '@noble/ed25519';
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 class NodeCryptoAdapter {
28
- constructor() {
29
- // Set SHA-512 hash function for ed25519 using Node's crypto.subtle
30
- if (typeof crypto === 'undefined' || !crypto.subtle) {
31
- throw new Error('crypto.subtle is not available. ' +
32
- 'Node.js 19+ is required, or Node.js 18 with --experimental-global-webcrypto flag');
33
- }
34
- ed25519.hashes.sha512Async = async (message) => {
35
- const hash = await crypto.subtle.digest('SHA-512', message);
36
- return new Uint8Array(hash);
37
- };
38
- }
39
- async generateKeypair() {
40
- const privateKey = ed25519.utils.randomSecretKey();
41
- const publicKey = await ed25519.getPublicKeyAsync(privateKey);
42
- return {
43
- publicKey: this.bytesToBase64(publicKey),
44
- privateKey: this.bytesToBase64(privateKey),
45
- };
46
- }
47
- async signMessage(message, privateKeyBase64) {
48
- const privateKey = this.base64ToBytes(privateKeyBase64);
49
- const encoder = new TextEncoder();
50
- const messageBytes = encoder.encode(message);
51
- const signature = await ed25519.signAsync(messageBytes, privateKey);
52
- return this.bytesToBase64(signature);
53
- }
54
- async verifySignature(message, signatureBase64, publicKeyBase64) {
55
- try {
56
- const signature = this.base64ToBytes(signatureBase64);
57
- const publicKey = this.base64ToBytes(publicKeyBase64);
58
- const encoder = new TextEncoder();
59
- const messageBytes = encoder.encode(message);
60
- return await ed25519.verifyAsync(signature, messageBytes, publicKey);
61
- }
62
- catch {
63
- return false;
64
- }
65
- }
66
- bytesToBase64(bytes) {
67
- // Node.js Buffer provides native base64 encoding
68
- return Buffer.from(bytes).toString('base64');
69
- }
70
- base64ToBytes(base64) {
71
- // Node.js Buffer provides native base64 decoding
72
- return new Uint8Array(Buffer.from(base64, 'base64'));
73
- }
74
- randomBytes(length) {
75
- // Use Web Crypto API's getRandomValues (available in Node 19+)
76
- return crypto.getRandomValues(new Uint8Array(length));
77
- }
78
- }
@@ -1,54 +0,0 @@
1
- /**
2
- * Offerer-side WebRTC connection with offer creation and answer processing
3
- */
4
- import { RondevuConnection } from './connection.js';
5
- import { RondevuAPI } from './api.js';
6
- import { ConnectionConfig } from './connection-config.js';
7
- export interface OffererOptions {
8
- api: RondevuAPI;
9
- serviceFqn: string;
10
- offerId: string;
11
- pc: RTCPeerConnection;
12
- dc?: RTCDataChannel;
13
- config?: Partial<ConnectionConfig>;
14
- }
15
- /**
16
- * Offerer connection - manages already-created offers and waits for answers
17
- */
18
- export declare class OffererConnection extends RondevuConnection {
19
- private api;
20
- private serviceFqn;
21
- private offerId;
22
- constructor(options: OffererOptions);
23
- /**
24
- * Initialize the connection - setup handlers for already-created offer
25
- */
26
- initialize(): Promise<void>;
27
- /**
28
- * Process an answer from the answerer
29
- */
30
- processAnswer(sdp: string, answererId: string): Promise<void>;
31
- /**
32
- * Generate a hash fingerprint of SDP for deduplication
33
- */
34
- private hashSdp;
35
- /**
36
- * Handle local ICE candidate generation
37
- */
38
- protected onLocalIceCandidate(candidate: RTCIceCandidate): void;
39
- /**
40
- * Poll for remote ICE candidates
41
- */
42
- protected pollIceCandidates(): void;
43
- /**
44
- * Attempt to reconnect
45
- *
46
- * Note: For offerer connections, reconnection is handled by the Rondevu instance
47
- * creating a new offer via fillOffers(). This method is a no-op.
48
- */
49
- protected attemptReconnect(): void;
50
- /**
51
- * Get the offer ID
52
- */
53
- getOfferId(): string;
54
- }