@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.
- package/README.md +92 -117
- package/dist/api/batcher.d.ts +83 -0
- package/dist/api/batcher.js +155 -0
- package/dist/api/client.d.ts +198 -0
- package/dist/api/client.js +400 -0
- package/dist/{answerer-connection.d.ts → connections/answerer.d.ts} +25 -8
- package/dist/{answerer-connection.js → connections/answerer.js} +70 -48
- package/dist/{connection.d.ts → connections/base.d.ts} +30 -7
- package/dist/{connection.js → connections/base.js} +65 -14
- package/dist/connections/config.d.ts +51 -0
- package/dist/{connection-config.js → connections/config.js} +20 -0
- package/dist/{connection-events.d.ts → connections/events.d.ts} +6 -6
- package/dist/connections/offerer.d.ts +108 -0
- package/dist/connections/offerer.js +306 -0
- package/dist/core/ice-config.d.ts +35 -0
- package/dist/core/ice-config.js +111 -0
- package/dist/core/index.d.ts +22 -0
- package/dist/core/index.js +22 -0
- package/dist/core/offer-pool.d.ts +113 -0
- package/dist/core/offer-pool.js +281 -0
- package/dist/core/peer.d.ts +155 -0
- package/dist/core/peer.js +252 -0
- package/dist/core/polling-manager.d.ts +71 -0
- package/dist/core/polling-manager.js +122 -0
- package/dist/core/rondevu-errors.d.ts +59 -0
- package/dist/core/rondevu-errors.js +75 -0
- package/dist/core/rondevu-types.d.ts +125 -0
- package/dist/core/rondevu-types.js +6 -0
- package/dist/core/rondevu.d.ts +296 -0
- package/dist/core/rondevu.js +472 -0
- package/dist/crypto/adapter.d.ts +53 -0
- package/dist/crypto/node.d.ts +57 -0
- package/dist/crypto/node.js +149 -0
- package/dist/crypto/web.d.ts +38 -0
- package/dist/crypto/web.js +129 -0
- package/dist/utils/async-lock.d.ts +42 -0
- package/dist/utils/async-lock.js +75 -0
- package/dist/{message-buffer.d.ts → utils/message-buffer.d.ts} +1 -1
- package/dist/{message-buffer.js → utils/message-buffer.js} +4 -4
- package/dist/webrtc/adapter.d.ts +22 -0
- package/dist/webrtc/adapter.js +5 -0
- package/dist/webrtc/browser.d.ts +12 -0
- package/dist/webrtc/browser.js +15 -0
- package/dist/webrtc/node.d.ts +32 -0
- package/dist/webrtc/node.js +32 -0
- package/package.json +20 -9
- package/dist/api.d.ts +0 -146
- package/dist/api.js +0 -279
- package/dist/connection-config.d.ts +0 -21
- package/dist/crypto-adapter.d.ts +0 -37
- package/dist/index.d.ts +0 -13
- package/dist/index.js +0 -10
- package/dist/node-crypto-adapter.d.ts +0 -35
- package/dist/node-crypto-adapter.js +0 -78
- package/dist/offerer-connection.d.ts +0 -54
- package/dist/offerer-connection.js +0 -177
- package/dist/rondevu-signaler.d.ts +0 -112
- package/dist/rondevu-signaler.js +0 -401
- package/dist/rondevu.d.ts +0 -407
- package/dist/rondevu.js +0 -847
- package/dist/rpc-batcher.d.ts +0 -61
- package/dist/rpc-batcher.js +0 -111
- package/dist/web-crypto-adapter.d.ts +0 -16
- package/dist/web-crypto-adapter.js +0 -52
- /package/dist/{connection-events.js → connections/events.js} +0 -0
- /package/dist/{types.d.ts → core/types.d.ts} +0 -0
- /package/dist/{types.js → core/types.js} +0 -0
- /package/dist/{crypto-adapter.js → crypto/adapter.js} +0 -0
- /package/dist/{exponential-backoff.d.ts → utils/exponential-backoff.d.ts} +0 -0
- /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;
|
package/dist/crypto-adapter.d.ts
DELETED
|
@@ -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
|
-
}
|