@xtr-dev/rondevu-client 0.20.1 → 0.21.3

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 (43) hide show
  1. package/README.md +83 -385
  2. package/dist/api/batcher.d.ts +60 -38
  3. package/dist/api/batcher.js +121 -77
  4. package/dist/api/client.d.ts +104 -61
  5. package/dist/api/client.js +273 -185
  6. package/dist/connections/answerer.d.ts +15 -6
  7. package/dist/connections/answerer.js +56 -19
  8. package/dist/connections/base.d.ts +6 -4
  9. package/dist/connections/base.js +26 -16
  10. package/dist/connections/config.d.ts +30 -0
  11. package/dist/connections/config.js +20 -0
  12. package/dist/connections/events.d.ts +6 -6
  13. package/dist/connections/offerer.d.ts +37 -8
  14. package/dist/connections/offerer.js +92 -24
  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 +18 -18
  18. package/dist/core/index.js +18 -13
  19. package/dist/core/offer-pool.d.ts +30 -11
  20. package/dist/core/offer-pool.js +90 -76
  21. package/dist/core/peer.d.ts +158 -0
  22. package/dist/core/peer.js +254 -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 +106 -209
  30. package/dist/core/rondevu.js +222 -349
  31. package/dist/crypto/adapter.d.ts +25 -9
  32. package/dist/crypto/node.d.ts +27 -5
  33. package/dist/crypto/node.js +96 -25
  34. package/dist/crypto/web.d.ts +26 -4
  35. package/dist/crypto/web.js +102 -25
  36. package/dist/utils/message-buffer.js +4 -4
  37. package/dist/webrtc/adapter.d.ts +22 -0
  38. package/dist/webrtc/adapter.js +5 -0
  39. package/dist/webrtc/browser.d.ts +12 -0
  40. package/dist/webrtc/browser.js +15 -0
  41. package/dist/webrtc/node.d.ts +32 -0
  42. package/dist/webrtc/node.js +32 -0
  43. package/package.json +17 -6
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Crypto adapter interface for platform-independent cryptographic operations
3
3
  */
4
- export interface Keypair {
5
- publicKey: string;
6
- privateKey: string;
4
+ export interface Credential {
5
+ name: string;
6
+ secret: string;
7
7
  }
8
8
  /**
9
9
  * Platform-independent crypto adapter interface
@@ -11,17 +11,33 @@ export interface Keypair {
11
11
  */
12
12
  export interface CryptoAdapter {
13
13
  /**
14
- * Generate an Ed25519 keypair
14
+ * Generate HMAC-SHA256 signature for message authentication
15
+ * @param secret - The credential secret (hex string)
16
+ * @param message - The message to sign
17
+ * @returns Base64-encoded signature
15
18
  */
16
- generateKeypair(): Promise<Keypair>;
19
+ generateSignature(secret: string, message: string): Promise<string>;
17
20
  /**
18
- * Sign a message with an Ed25519 private key
21
+ * Verify HMAC-SHA256 signature
22
+ * @param secret - The credential secret (hex string)
23
+ * @param message - The message that was signed
24
+ * @param signature - The signature to verify (base64)
25
+ * @returns True if signature is valid
19
26
  */
20
- signMessage(message: string, privateKeyBase64: string): Promise<string>;
27
+ verifySignature(secret: string, message: string, signature: string): Promise<boolean>;
21
28
  /**
22
- * Verify an Ed25519 signature
29
+ * Generate a random secret (256-bit hex string)
30
+ * @returns 64-character hex string
23
31
  */
24
- verifySignature(message: string, signatureBase64: string, publicKeyBase64: string): Promise<boolean>;
32
+ generateSecret(): string;
33
+ /**
34
+ * Convert hex string to bytes
35
+ */
36
+ hexToBytes(hex: string): Uint8Array;
37
+ /**
38
+ * Convert bytes to hex string
39
+ */
40
+ bytesToHex(bytes: Uint8Array): string;
25
41
  /**
26
42
  * Convert Uint8Array to base64 string
27
43
  */
@@ -2,7 +2,7 @@
2
2
  * Node.js Crypto adapter for Node.js environments
3
3
  * Requires Node.js 19+ or Node.js 18 with --experimental-global-webcrypto flag
4
4
  */
5
- import { CryptoAdapter, Keypair } from './adapter.js';
5
+ import { CryptoAdapter } from './adapter.js';
6
6
  /**
7
7
  * Node.js Crypto implementation using Node.js built-in APIs
8
8
  * Uses Buffer for base64 encoding and crypto.randomBytes for random generation
@@ -19,16 +19,38 @@ import { CryptoAdapter, Keypair } from './adapter.js';
19
19
  * const api = new RondevuAPI(
20
20
  * 'https://signal.example.com',
21
21
  * 'alice',
22
- * keypair,
22
+ * { name: 'alice', secret: '...' },
23
23
  * new NodeCryptoAdapter()
24
24
  * )
25
25
  * ```
26
26
  */
27
27
  export declare class NodeCryptoAdapter implements CryptoAdapter {
28
28
  constructor();
29
- generateKeypair(): Promise<Keypair>;
30
- signMessage(message: string, privateKeyBase64: string): Promise<string>;
31
- verifySignature(message: string, signatureBase64: string, publicKeyBase64: string): Promise<boolean>;
29
+ /**
30
+ * Generate HMAC-SHA256 signature
31
+ */
32
+ generateSignature(secret: string, message: string): Promise<string>;
33
+ /**
34
+ * Verify HMAC-SHA256 signature
35
+ * Uses constant-time comparison via Web Crypto API to prevent timing attacks
36
+ *
37
+ * @returns false for invalid signatures, throws for malformed input
38
+ * @throws Error if secret/signature format is invalid (not a verification failure)
39
+ */
40
+ verifySignature(secret: string, message: string, signature: string): Promise<boolean>;
41
+ /**
42
+ * Generate a random secret (256-bit hex string)
43
+ */
44
+ generateSecret(): string;
45
+ /**
46
+ * Convert hex string to bytes
47
+ * @throws Error if hex string is invalid
48
+ */
49
+ hexToBytes(hex: string): Uint8Array;
50
+ /**
51
+ * Convert bytes to hex string
52
+ */
53
+ bytesToHex(bytes: Uint8Array): string;
32
54
  bytesToBase64(bytes: Uint8Array): string;
33
55
  base64ToBytes(base64: string): Uint8Array;
34
56
  randomBytes(length: number): Uint8Array;
@@ -2,7 +2,6 @@
2
2
  * Node.js Crypto adapter for Node.js environments
3
3
  * Requires Node.js 19+ or Node.js 18 with --experimental-global-webcrypto flag
4
4
  */
5
- import * as ed25519 from '@noble/ed25519';
6
5
  /**
7
6
  * Node.js Crypto implementation using Node.js built-in APIs
8
7
  * Uses Buffer for base64 encoding and crypto.randomBytes for random generation
@@ -19,55 +18,127 @@ import * as ed25519 from '@noble/ed25519';
19
18
  * const api = new RondevuAPI(
20
19
  * 'https://signal.example.com',
21
20
  * 'alice',
22
- * keypair,
21
+ * { name: 'alice', secret: '...' },
23
22
  * new NodeCryptoAdapter()
24
23
  * )
25
24
  * ```
26
25
  */
27
26
  export class NodeCryptoAdapter {
28
27
  constructor() {
29
- // Set SHA-512 hash function for ed25519 using Node's crypto.subtle
30
28
  if (typeof crypto === 'undefined' || !crypto.subtle) {
31
29
  throw new Error('crypto.subtle is not available. ' +
32
30
  'Node.js 19+ is required, or Node.js 18 with --experimental-global-webcrypto flag');
33
31
  }
34
- ed25519.hashes.sha512Async = async (message) => {
35
- const hash = await crypto.subtle.digest('SHA-512', message);
36
- return new Uint8Array(hash);
37
- };
38
32
  }
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);
33
+ /**
34
+ * Generate HMAC-SHA256 signature
35
+ */
36
+ async generateSignature(secret, message) {
37
+ if (!secret || typeof secret !== 'string') {
38
+ throw new Error('Invalid secret: must be a non-empty string');
39
+ }
40
+ if (typeof message !== 'string') {
41
+ throw new Error('Invalid message: must be a string');
42
+ }
43
+ const secretBytes = this.hexToBytes(secret);
44
+ // Import secret as HMAC key
45
+ const key = await crypto.subtle.importKey('raw', secretBytes, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
46
+ // Convert message to bytes
49
47
  const encoder = new TextEncoder();
50
48
  const messageBytes = encoder.encode(message);
51
- const signature = await ed25519.signAsync(messageBytes, privateKey);
52
- return this.bytesToBase64(signature);
49
+ // Generate HMAC signature
50
+ const signatureBytes = await crypto.subtle.sign('HMAC', key, messageBytes);
51
+ // Convert to base64
52
+ return this.bytesToBase64(new Uint8Array(signatureBytes));
53
53
  }
54
- async verifySignature(message, signatureBase64, publicKeyBase64) {
54
+ /**
55
+ * Verify HMAC-SHA256 signature
56
+ * Uses constant-time comparison via Web Crypto API to prevent timing attacks
57
+ *
58
+ * @returns false for invalid signatures, throws for malformed input
59
+ * @throws Error if secret/signature format is invalid (not a verification failure)
60
+ */
61
+ async verifySignature(secret, message, signature) {
62
+ // Validate inputs first
63
+ // Use generic error messages to prevent timing attacks and information leakage
64
+ let secretBytes;
65
+ let signatureBytes;
66
+ try {
67
+ secretBytes = this.hexToBytes(secret);
68
+ }
69
+ catch (error) {
70
+ // Generic error message - don't leak format details
71
+ throw new Error('Invalid credential format');
72
+ }
73
+ try {
74
+ signatureBytes = this.base64ToBytes(signature);
75
+ }
76
+ catch (error) {
77
+ // Generic error message - don't leak format details
78
+ throw new Error('Invalid signature format');
79
+ }
80
+ // Perform HMAC verification
55
81
  try {
56
- const signature = this.base64ToBytes(signatureBase64);
57
- const publicKey = this.base64ToBytes(publicKeyBase64);
82
+ // Import secret as HMAC key for verification
83
+ const key = await crypto.subtle.importKey('raw', secretBytes, { name: 'HMAC', hash: 'SHA-256' }, false, ['verify']);
84
+ // Convert message to bytes
58
85
  const encoder = new TextEncoder();
59
86
  const messageBytes = encoder.encode(message);
60
- return await ed25519.verifyAsync(signature, messageBytes, publicKey);
87
+ // Use Web Crypto API's verify() for constant-time comparison
88
+ // Returns false for signature mismatch (auth failure)
89
+ return await crypto.subtle.verify('HMAC', key, signatureBytes, messageBytes);
61
90
  }
62
- catch {
63
- return false;
91
+ catch (error) {
92
+ // System/crypto errors - unexpected failures
93
+ throw new Error(`Signature verification error: ${error instanceof Error ? error.message : String(error)}`);
64
94
  }
65
95
  }
96
+ /**
97
+ * Generate a random secret (256-bit hex string)
98
+ */
99
+ generateSecret() {
100
+ const bytes = this.randomBytes(32); // 32 bytes = 256 bits
101
+ return this.bytesToHex(bytes);
102
+ }
103
+ /**
104
+ * Convert hex string to bytes
105
+ * @throws Error if hex string is invalid
106
+ */
107
+ hexToBytes(hex) {
108
+ if (hex.length % 2 !== 0) {
109
+ throw new Error('Hex string must have even length');
110
+ }
111
+ // Validate all characters are valid hex (0-9, a-f, A-F)
112
+ if (!/^[0-9a-fA-F]*$/.test(hex)) {
113
+ throw new Error('Invalid hex string: contains non-hex characters');
114
+ }
115
+ const bytes = new Uint8Array(hex.length / 2);
116
+ for (let i = 0; i < hex.length; i += 2) {
117
+ bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
118
+ }
119
+ return bytes;
120
+ }
121
+ /**
122
+ * Convert bytes to hex string
123
+ */
124
+ bytesToHex(bytes) {
125
+ return Array.from(bytes)
126
+ .map(b => b.toString(16).padStart(2, '0'))
127
+ .join('');
128
+ }
66
129
  bytesToBase64(bytes) {
67
130
  // Node.js Buffer provides native base64 encoding
68
131
  return Buffer.from(bytes).toString('base64');
69
132
  }
70
133
  base64ToBytes(base64) {
134
+ // Validate base64 string format
135
+ if (typeof base64 !== 'string' || base64.length === 0) {
136
+ throw new Error('Invalid base64 string');
137
+ }
138
+ // Base64 length must be divisible by 4 (with padding), + requires at least one char
139
+ if (base64.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(base64)) {
140
+ throw new Error('Invalid base64 string');
141
+ }
71
142
  // Node.js Buffer provides native base64 decoding
72
143
  return new Uint8Array(Buffer.from(base64, 'base64'));
73
144
  }
@@ -1,15 +1,37 @@
1
1
  /**
2
2
  * Web Crypto adapter for browser environments
3
3
  */
4
- import { CryptoAdapter, Keypair } from './adapter.js';
4
+ import { CryptoAdapter } from './adapter.js';
5
5
  /**
6
6
  * Web Crypto implementation using browser APIs
7
7
  * Uses btoa/atob for base64 encoding and crypto.getRandomValues for random bytes
8
8
  */
9
9
  export declare class WebCryptoAdapter implements CryptoAdapter {
10
- generateKeypair(): Promise<Keypair>;
11
- signMessage(message: string, privateKeyBase64: string): Promise<string>;
12
- verifySignature(message: string, signatureBase64: string, publicKeyBase64: string): Promise<boolean>;
10
+ /**
11
+ * Generate HMAC-SHA256 signature
12
+ */
13
+ generateSignature(secret: string, message: string): Promise<string>;
14
+ /**
15
+ * Verify HMAC-SHA256 signature
16
+ * Uses constant-time comparison via Web Crypto API to prevent timing attacks
17
+ *
18
+ * @returns false for invalid signatures, throws for malformed input
19
+ * @throws Error if secret/signature format is invalid (not a verification failure)
20
+ */
21
+ verifySignature(secret: string, message: string, signature: string): Promise<boolean>;
22
+ /**
23
+ * Generate a random secret (256-bit hex string)
24
+ */
25
+ generateSecret(): string;
26
+ /**
27
+ * Convert hex string to bytes
28
+ * @throws Error if hex string is invalid
29
+ */
30
+ hexToBytes(hex: string): Uint8Array;
31
+ /**
32
+ * Convert bytes to hex string
33
+ */
34
+ bytesToHex(bytes: Uint8Array): string;
13
35
  bytesToBase64(bytes: Uint8Array): string;
14
36
  base64ToBytes(base64: string): Uint8Array;
15
37
  randomBytes(length: number): Uint8Array;
@@ -1,50 +1,127 @@
1
1
  /**
2
2
  * Web Crypto adapter for browser environments
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
- };
9
4
  /**
10
5
  * Web Crypto implementation using browser APIs
11
6
  * Uses btoa/atob for base64 encoding and crypto.getRandomValues for random bytes
12
7
  */
13
8
  export class WebCryptoAdapter {
14
- async generateKeypair() {
15
- const privateKey = ed25519.utils.randomSecretKey();
16
- const publicKey = await ed25519.getPublicKeyAsync(privateKey);
17
- return {
18
- publicKey: this.bytesToBase64(publicKey),
19
- privateKey: this.bytesToBase64(privateKey),
20
- };
21
- }
22
- async signMessage(message, privateKeyBase64) {
23
- const privateKey = this.base64ToBytes(privateKeyBase64);
9
+ /**
10
+ * Generate HMAC-SHA256 signature
11
+ */
12
+ async generateSignature(secret, message) {
13
+ if (!secret || typeof secret !== 'string') {
14
+ throw new Error('Invalid secret: must be a non-empty string');
15
+ }
16
+ if (typeof message !== 'string') {
17
+ throw new Error('Invalid message: must be a string');
18
+ }
19
+ const secretBytes = this.hexToBytes(secret);
20
+ // Import secret as HMAC key
21
+ const key = await crypto.subtle.importKey('raw', secretBytes, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
22
+ // Convert message to bytes
24
23
  const encoder = new TextEncoder();
25
24
  const messageBytes = encoder.encode(message);
26
- const signature = await ed25519.signAsync(messageBytes, privateKey);
27
- return this.bytesToBase64(signature);
25
+ // Generate HMAC signature
26
+ const signatureBytes = await crypto.subtle.sign('HMAC', key, messageBytes);
27
+ // Convert to base64
28
+ return this.bytesToBase64(new Uint8Array(signatureBytes));
28
29
  }
29
- async verifySignature(message, signatureBase64, publicKeyBase64) {
30
+ /**
31
+ * Verify HMAC-SHA256 signature
32
+ * Uses constant-time comparison via Web Crypto API to prevent timing attacks
33
+ *
34
+ * @returns false for invalid signatures, throws for malformed input
35
+ * @throws Error if secret/signature format is invalid (not a verification failure)
36
+ */
37
+ async verifySignature(secret, message, signature) {
38
+ // Validate inputs first
39
+ // Use generic error messages to prevent timing attacks and information leakage
40
+ let secretBytes;
41
+ let signatureBytes;
42
+ try {
43
+ secretBytes = this.hexToBytes(secret);
44
+ }
45
+ catch (error) {
46
+ // Generic error message - don't leak format details
47
+ throw new Error('Invalid credential format');
48
+ }
30
49
  try {
31
- const signature = this.base64ToBytes(signatureBase64);
32
- const publicKey = this.base64ToBytes(publicKeyBase64);
50
+ signatureBytes = this.base64ToBytes(signature);
51
+ }
52
+ catch (error) {
53
+ // Generic error message - don't leak format details
54
+ throw new Error('Invalid signature format');
55
+ }
56
+ // Perform HMAC verification
57
+ try {
58
+ // Import secret as HMAC key for verification
59
+ const key = await crypto.subtle.importKey('raw', secretBytes, { name: 'HMAC', hash: 'SHA-256' }, false, ['verify']);
60
+ // Convert message to bytes
33
61
  const encoder = new TextEncoder();
34
62
  const messageBytes = encoder.encode(message);
35
- return await ed25519.verifyAsync(signature, messageBytes, publicKey);
63
+ // Use Web Crypto API's verify() for constant-time comparison
64
+ // Returns false for signature mismatch (auth failure)
65
+ return await crypto.subtle.verify('HMAC', key, signatureBytes, messageBytes);
36
66
  }
37
- catch {
38
- return false;
67
+ catch (error) {
68
+ // System/crypto errors - unexpected failures
69
+ throw new Error(`Signature verification error: ${error instanceof Error ? error.message : String(error)}`);
39
70
  }
40
71
  }
72
+ /**
73
+ * Generate a random secret (256-bit hex string)
74
+ */
75
+ generateSecret() {
76
+ const bytes = this.randomBytes(32); // 32 bytes = 256 bits
77
+ return this.bytesToHex(bytes);
78
+ }
79
+ /**
80
+ * Convert hex string to bytes
81
+ * @throws Error if hex string is invalid
82
+ */
83
+ hexToBytes(hex) {
84
+ if (hex.length % 2 !== 0) {
85
+ throw new Error('Hex string must have even length');
86
+ }
87
+ // Validate all characters are valid hex (0-9, a-f, A-F)
88
+ if (!/^[0-9a-fA-F]*$/.test(hex)) {
89
+ throw new Error('Invalid hex string: contains non-hex characters');
90
+ }
91
+ const bytes = new Uint8Array(hex.length / 2);
92
+ for (let i = 0; i < hex.length; i += 2) {
93
+ bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
94
+ }
95
+ return bytes;
96
+ }
97
+ /**
98
+ * Convert bytes to hex string
99
+ */
100
+ bytesToHex(bytes) {
101
+ return Array.from(bytes)
102
+ .map(b => b.toString(16).padStart(2, '0'))
103
+ .join('');
104
+ }
41
105
  bytesToBase64(bytes) {
42
106
  const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join('');
43
107
  return btoa(binString);
44
108
  }
45
109
  base64ToBytes(base64) {
46
- const binString = atob(base64);
47
- return Uint8Array.from(binString, char => char.codePointAt(0));
110
+ // Validate base64 string format
111
+ if (typeof base64 !== 'string' || base64.length === 0) {
112
+ throw new Error('Invalid base64 string');
113
+ }
114
+ // Base64 length must be divisible by 4 (with padding), + requires at least one char
115
+ if (base64.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(base64)) {
116
+ throw new Error('Invalid base64 string');
117
+ }
118
+ try {
119
+ const binString = atob(base64);
120
+ return Uint8Array.from(binString, char => char.codePointAt(0));
121
+ }
122
+ catch {
123
+ throw new Error('Invalid base64 string');
124
+ }
48
125
  }
49
126
  randomBytes(length) {
50
127
  return crypto.getRandomValues(new Uint8Array(length));
@@ -40,7 +40,7 @@ export class MessageBuffer {
40
40
  */
41
41
  getValid() {
42
42
  const now = Date.now();
43
- return this.buffer.filter((msg) => now - msg.timestamp < this.config.maxAge);
43
+ return this.buffer.filter(msg => now - msg.timestamp < this.config.maxAge);
44
44
  }
45
45
  /**
46
46
  * Get and remove expired messages
@@ -48,7 +48,7 @@ export class MessageBuffer {
48
48
  getExpired() {
49
49
  const now = Date.now();
50
50
  const expired = [];
51
- this.buffer = this.buffer.filter((msg) => {
51
+ this.buffer = this.buffer.filter(msg => {
52
52
  if (now - msg.timestamp >= this.config.maxAge) {
53
53
  expired.push(msg);
54
54
  return false;
@@ -61,7 +61,7 @@ export class MessageBuffer {
61
61
  * Remove a specific message by ID
62
62
  */
63
63
  remove(messageId) {
64
- const index = this.buffer.findIndex((msg) => msg.id === messageId);
64
+ const index = this.buffer.findIndex(msg => msg.id === messageId);
65
65
  if (index === -1)
66
66
  return null;
67
67
  const [removed] = this.buffer.splice(index, 1);
@@ -79,7 +79,7 @@ export class MessageBuffer {
79
79
  * Increment attempt count for a message
80
80
  */
81
81
  incrementAttempt(messageId) {
82
- const message = this.buffer.find((msg) => msg.id === messageId);
82
+ const message = this.buffer.find(msg => msg.id === messageId);
83
83
  if (!message)
84
84
  return false;
85
85
  message.attempts++;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * WebRTC adapter interface for platform-independent WebRTC operations
3
+ * Allows using native browser APIs or polyfills like `wrtc` for Node.js
4
+ */
5
+ /**
6
+ * Platform-independent WebRTC adapter interface
7
+ * Implementations provide platform-specific WebRTC constructors
8
+ */
9
+ export interface WebRTCAdapter {
10
+ /**
11
+ * Create a new RTCPeerConnection
12
+ * @param config - RTCConfiguration for the peer connection
13
+ * @returns A new RTCPeerConnection instance
14
+ */
15
+ createPeerConnection(config?: RTCConfiguration): RTCPeerConnection;
16
+ /**
17
+ * Create a new RTCIceCandidate
18
+ * @param candidateInit - RTCIceCandidateInit to create the candidate from
19
+ * @returns A new RTCIceCandidate instance
20
+ */
21
+ createIceCandidate(candidateInit: RTCIceCandidateInit): RTCIceCandidate;
22
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * WebRTC adapter interface for platform-independent WebRTC operations
3
+ * Allows using native browser APIs or polyfills like `wrtc` for Node.js
4
+ */
5
+ export {};
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Browser WebRTC adapter using native browser APIs
3
+ */
4
+ import { WebRTCAdapter } from './adapter.js';
5
+ /**
6
+ * Browser WebRTC implementation using native browser APIs
7
+ * This is the default adapter for browser environments
8
+ */
9
+ export declare class BrowserWebRTCAdapter implements WebRTCAdapter {
10
+ createPeerConnection(config?: RTCConfiguration): RTCPeerConnection;
11
+ createIceCandidate(candidateInit: RTCIceCandidateInit): RTCIceCandidate;
12
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Browser WebRTC adapter using native browser APIs
3
+ */
4
+ /**
5
+ * Browser WebRTC implementation using native browser APIs
6
+ * This is the default adapter for browser environments
7
+ */
8
+ export class BrowserWebRTCAdapter {
9
+ createPeerConnection(config) {
10
+ return new RTCPeerConnection(config);
11
+ }
12
+ createIceCandidate(candidateInit) {
13
+ return new RTCIceCandidate(candidateInit);
14
+ }
15
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Node.js WebRTC adapter using polyfills like `wrtc`
3
+ */
4
+ import { WebRTCAdapter } from './adapter.js';
5
+ export interface NodeWebRTCPolyfills {
6
+ RTCPeerConnection: typeof RTCPeerConnection;
7
+ RTCIceCandidate: typeof RTCIceCandidate;
8
+ }
9
+ /**
10
+ * Node.js WebRTC implementation using polyfills
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import wrtc from 'wrtc'
15
+ *
16
+ * const adapter = new NodeWebRTCAdapter({
17
+ * RTCPeerConnection: wrtc.RTCPeerConnection,
18
+ * RTCIceCandidate: wrtc.RTCIceCandidate,
19
+ * })
20
+ *
21
+ * const rondevu = await Rondevu.connect({
22
+ * apiUrl: 'https://api.ronde.vu',
23
+ * webrtcAdapter: adapter,
24
+ * })
25
+ * ```
26
+ */
27
+ export declare class NodeWebRTCAdapter implements WebRTCAdapter {
28
+ private readonly polyfills;
29
+ constructor(polyfills: NodeWebRTCPolyfills);
30
+ createPeerConnection(config?: RTCConfiguration): RTCPeerConnection;
31
+ createIceCandidate(candidateInit: RTCIceCandidateInit): RTCIceCandidate;
32
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Node.js WebRTC adapter using polyfills like `wrtc`
3
+ */
4
+ /**
5
+ * Node.js WebRTC implementation using polyfills
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import wrtc from 'wrtc'
10
+ *
11
+ * const adapter = new NodeWebRTCAdapter({
12
+ * RTCPeerConnection: wrtc.RTCPeerConnection,
13
+ * RTCIceCandidate: wrtc.RTCIceCandidate,
14
+ * })
15
+ *
16
+ * const rondevu = await Rondevu.connect({
17
+ * apiUrl: 'https://api.ronde.vu',
18
+ * webrtcAdapter: adapter,
19
+ * })
20
+ * ```
21
+ */
22
+ export class NodeWebRTCAdapter {
23
+ constructor(polyfills) {
24
+ this.polyfills = polyfills;
25
+ }
26
+ createPeerConnection(config) {
27
+ return new this.polyfills.RTCPeerConnection(config);
28
+ }
29
+ createIceCandidate(candidateInit) {
30
+ return new this.polyfills.RTCIceCandidate(candidateInit);
31
+ }
32
+ }