peer-client 1.0.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1086 -0
  3. package/dist/core/client.d.ts +41 -0
  4. package/dist/core/client.js +361 -0
  5. package/dist/core/emitter.d.ts +11 -0
  6. package/dist/core/emitter.js +46 -0
  7. package/dist/core/identity.d.ts +15 -0
  8. package/dist/core/identity.js +54 -0
  9. package/dist/core/index.d.ts +6 -0
  10. package/dist/core/index.js +6 -0
  11. package/dist/core/peer.d.ts +29 -0
  12. package/dist/core/peer.js +234 -0
  13. package/dist/core/transport.d.ts +35 -0
  14. package/dist/core/transport.js +174 -0
  15. package/dist/core/types.d.ts +173 -0
  16. package/dist/core/types.js +28 -0
  17. package/dist/crypto.d.ts +32 -0
  18. package/dist/crypto.js +168 -0
  19. package/dist/index.d.ts +11 -0
  20. package/dist/index.js +11 -0
  21. package/dist/media.d.ts +63 -0
  22. package/dist/media.js +275 -0
  23. package/dist/react/Audio.d.ts +6 -0
  24. package/dist/react/Audio.js +18 -0
  25. package/dist/react/PeerProvider.d.ts +17 -0
  26. package/dist/react/PeerProvider.js +46 -0
  27. package/dist/react/PeerStatus.d.ts +7 -0
  28. package/dist/react/PeerStatus.js +20 -0
  29. package/dist/react/TransferProgress.d.ts +10 -0
  30. package/dist/react/TransferProgress.js +17 -0
  31. package/dist/react/Video.d.ts +7 -0
  32. package/dist/react/Video.js +18 -0
  33. package/dist/react/index.d.ts +19 -0
  34. package/dist/react/index.js +18 -0
  35. package/dist/react/useBroadcast.d.ts +12 -0
  36. package/dist/react/useBroadcast.js +21 -0
  37. package/dist/react/useCRDT.d.ts +8 -0
  38. package/dist/react/useCRDT.js +37 -0
  39. package/dist/react/useE2E.d.ts +11 -0
  40. package/dist/react/useE2E.js +62 -0
  41. package/dist/react/useFileTransfer.d.ts +24 -0
  42. package/dist/react/useFileTransfer.js +133 -0
  43. package/dist/react/useIdentity.d.ts +9 -0
  44. package/dist/react/useIdentity.js +63 -0
  45. package/dist/react/useMatch.d.ts +11 -0
  46. package/dist/react/useMatch.js +33 -0
  47. package/dist/react/useMedia.d.ts +13 -0
  48. package/dist/react/useMedia.js +89 -0
  49. package/dist/react/useNamespace.d.ts +7 -0
  50. package/dist/react/useNamespace.js +38 -0
  51. package/dist/react/usePeer.d.ts +6 -0
  52. package/dist/react/usePeer.js +49 -0
  53. package/dist/react/usePeerClient.d.ts +7 -0
  54. package/dist/react/usePeerClient.js +5 -0
  55. package/dist/react/useRelay.d.ts +11 -0
  56. package/dist/react/useRelay.js +19 -0
  57. package/dist/react/useRoom.d.ts +17 -0
  58. package/dist/react/useRoom.js +67 -0
  59. package/dist/react/useSync.d.ts +8 -0
  60. package/dist/react/useSync.js +45 -0
  61. package/dist/room.d.ts +44 -0
  62. package/dist/room.js +246 -0
  63. package/dist/sync.d.ts +45 -0
  64. package/dist/sync.js +333 -0
  65. package/dist/transfer.d.ts +49 -0
  66. package/dist/transfer.js +454 -0
  67. package/package.json +76 -0
@@ -0,0 +1,41 @@
1
+ import { Emitter } from './emitter';
2
+ import { Transport } from './transport';
3
+ import { Identity } from './identity';
4
+ import { Peer } from './peer';
5
+ import type { ClientConfig, PeerClientEvent, PeerInfo, MatchResult, DataChannelConfig, RoomCreatedResult, RoomInfoResult, RoomConfig } from './types';
6
+ export declare class PeerClient extends Emitter<PeerClientEvent> {
7
+ private transport;
8
+ private identity;
9
+ private config;
10
+ private peers;
11
+ private namespaces;
12
+ private matchResolvers;
13
+ private registerPromise;
14
+ private registerAbort;
15
+ constructor(config: ClientConfig);
16
+ get fingerprint(): string;
17
+ get alias(): string;
18
+ get connected(): boolean;
19
+ get peerMap(): ReadonlyMap<string, Peer>;
20
+ getIdentity(): Identity;
21
+ getTransport(): Transport;
22
+ connect(): Promise<void>;
23
+ join(namespace: string, appType?: string, version?: string): Promise<PeerInfo[]>;
24
+ leave(namespace: string): void;
25
+ discover(namespace: string, limit?: number): Promise<PeerInfo[]>;
26
+ match(namespace: string, criteria?: Record<string, any>, groupSize?: number): Promise<MatchResult>;
27
+ createRoom(roomId: string, config?: RoomConfig): Promise<RoomCreatedResult>;
28
+ joinRoom(roomId: string): Promise<PeerInfo[]>;
29
+ roomInfo(roomId: string): Promise<RoomInfoResult>;
30
+ kick(roomId: string, fingerprint: string): void;
31
+ connectToPeer(fingerprint: string, alias?: string, channelConfig?: DataChannelConfig): Peer;
32
+ getPeer(fingerprint: string): Peer | undefined;
33
+ relay(to: string, payload: any): void;
34
+ broadcast(namespace: string, data: any): void;
35
+ updateMetadata(meta: Record<string, any>): void;
36
+ closePeer(fingerprint: string): void;
37
+ disconnect(): void;
38
+ private doRegister;
39
+ createPeer(fingerprint: string, alias: string): Peer;
40
+ private handleMessage;
41
+ }
@@ -0,0 +1,361 @@
1
+ import { Emitter } from './emitter';
2
+ import { Transport } from './transport';
3
+ import { Identity } from './identity';
4
+ import { Peer } from './peer';
5
+ import { DEFAULT_ICE_SERVERS } from './types';
6
+ export class PeerClient extends Emitter {
7
+ transport;
8
+ identity;
9
+ config;
10
+ peers = new Map();
11
+ namespaces = new Set();
12
+ matchResolvers = new Map();
13
+ registerPromise = null;
14
+ registerAbort = null;
15
+ constructor(config) {
16
+ super();
17
+ this.config = {
18
+ url: config.url,
19
+ iceServers: config.iceServers ?? DEFAULT_ICE_SERVERS,
20
+ alias: config.alias ?? '',
21
+ meta: config.meta ?? {},
22
+ autoReconnect: config.autoReconnect ?? true,
23
+ reconnectDelay: config.reconnectDelay ?? 1000,
24
+ reconnectMaxDelay: config.reconnectMaxDelay ?? 30000,
25
+ pingInterval: config.pingInterval ?? 25000,
26
+ maxReconnectAttempts: config.maxReconnectAttempts ?? Infinity,
27
+ identityKeys: config.identityKeys,
28
+ };
29
+ this.identity = new Identity();
30
+ this.transport = new Transport(this.config.url, this.config.autoReconnect, this.config.reconnectDelay, this.config.reconnectMaxDelay, this.config.maxReconnectAttempts, this.config.pingInterval);
31
+ this.transport.on('message', (msg) => this.handleMessage(msg));
32
+ this.transport.on('close', () => this.emit('disconnected'));
33
+ this.transport.on('reconnecting', (attempt, delay) => {
34
+ this.emit('reconnecting', attempt, delay);
35
+ });
36
+ this.transport.on('open', () => {
37
+ if (this.identity.fingerprint) {
38
+ this.doRegister().then(() => {
39
+ this.namespaces.forEach((ns) => {
40
+ this.transport.send({
41
+ type: 'join',
42
+ payload: { namespace: ns },
43
+ });
44
+ });
45
+ this.emit('reconnected');
46
+ }).catch(() => { });
47
+ }
48
+ });
49
+ }
50
+ get fingerprint() {
51
+ return this.identity.fingerprint;
52
+ }
53
+ get alias() {
54
+ return this.identity.alias;
55
+ }
56
+ get connected() {
57
+ return this.transport.connected;
58
+ }
59
+ get peerMap() {
60
+ return this.peers;
61
+ }
62
+ getIdentity() {
63
+ return this.identity;
64
+ }
65
+ getTransport() {
66
+ return this.transport;
67
+ }
68
+ async connect() {
69
+ await this.transport.connect();
70
+ await this.doRegister();
71
+ }
72
+ async join(namespace, appType, version) {
73
+ this.namespaces.add(namespace);
74
+ return new Promise((resolve) => {
75
+ const off = this.on('peer_list', (ns, peers) => {
76
+ if (ns === namespace) {
77
+ off();
78
+ resolve(peers);
79
+ }
80
+ });
81
+ this.transport.send({
82
+ type: 'join',
83
+ payload: { namespace, app_type: appType, version },
84
+ });
85
+ });
86
+ }
87
+ leave(namespace) {
88
+ this.namespaces.delete(namespace);
89
+ this.transport.send({ type: 'leave', payload: { namespace } });
90
+ }
91
+ async discover(namespace, limit = 20) {
92
+ return new Promise((resolve) => {
93
+ const off = this.on('peer_list', (ns, peers) => {
94
+ if (ns === namespace) {
95
+ off();
96
+ resolve(peers);
97
+ }
98
+ });
99
+ this.transport.send({
100
+ type: 'discover',
101
+ payload: { namespace, limit },
102
+ });
103
+ });
104
+ }
105
+ async match(namespace, criteria, groupSize) {
106
+ return new Promise((resolve) => {
107
+ this.matchResolvers.set(namespace, resolve);
108
+ this.transport.send({
109
+ type: 'match',
110
+ payload: { namespace, criteria, group_size: groupSize },
111
+ });
112
+ });
113
+ }
114
+ async createRoom(roomId, config) {
115
+ return new Promise((resolve, reject) => {
116
+ let offCreated = null;
117
+ let offError = null;
118
+ const cleanup = () => {
119
+ offCreated?.();
120
+ offError?.();
121
+ };
122
+ offCreated = this.on('room_created', (result) => {
123
+ if (result.room_id === roomId) {
124
+ cleanup();
125
+ resolve(result);
126
+ }
127
+ });
128
+ offError = this.on('error', (err) => {
129
+ cleanup();
130
+ reject(new Error(typeof err === 'string' ? err : err?.message ?? 'create_room failed'));
131
+ });
132
+ this.transport.send({
133
+ type: 'create_room',
134
+ payload: { room_id: roomId, max_size: config?.maxSize ?? 20 },
135
+ });
136
+ });
137
+ }
138
+ async joinRoom(roomId) {
139
+ this.namespaces.add(roomId);
140
+ return new Promise((resolve, reject) => {
141
+ let offList = null;
142
+ let offError = null;
143
+ const cleanup = () => {
144
+ offList?.();
145
+ offError?.();
146
+ };
147
+ offList = this.on('peer_list', (ns, peers) => {
148
+ if (ns === roomId) {
149
+ cleanup();
150
+ resolve(peers);
151
+ }
152
+ });
153
+ offError = this.on('error', (err) => {
154
+ cleanup();
155
+ this.namespaces.delete(roomId);
156
+ reject(new Error(typeof err === 'string' ? err : err?.message ?? 'join_room failed'));
157
+ });
158
+ this.transport.send({
159
+ type: 'join_room',
160
+ payload: { room_id: roomId },
161
+ });
162
+ });
163
+ }
164
+ async roomInfo(roomId) {
165
+ return new Promise((resolve, reject) => {
166
+ let offMsg = null;
167
+ const timeout = setTimeout(() => {
168
+ offMsg?.();
169
+ reject(new Error('room_info timeout'));
170
+ }, 10000);
171
+ offMsg = this.transport.on('message', (msg) => {
172
+ if (msg.type === 'room_info') {
173
+ const info = typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload;
174
+ if (info.room_id === roomId) {
175
+ clearTimeout(timeout);
176
+ offMsg?.();
177
+ resolve(info);
178
+ }
179
+ }
180
+ });
181
+ this.transport.send({
182
+ type: 'room_info',
183
+ payload: { room_id: roomId },
184
+ });
185
+ });
186
+ }
187
+ kick(roomId, fingerprint) {
188
+ this.transport.send({
189
+ type: 'kick',
190
+ payload: { room_id: roomId, fingerprint },
191
+ });
192
+ }
193
+ connectToPeer(fingerprint, alias = '', channelConfig) {
194
+ const existing = this.peers.get(fingerprint);
195
+ if (existing)
196
+ return existing;
197
+ const peer = this.createPeer(fingerprint, alias);
198
+ peer.createOffer(channelConfig);
199
+ return peer;
200
+ }
201
+ getPeer(fingerprint) {
202
+ return this.peers.get(fingerprint);
203
+ }
204
+ relay(to, payload) {
205
+ this.transport.send({ type: 'relay', to, payload });
206
+ }
207
+ broadcast(namespace, data) {
208
+ this.transport.send({
209
+ type: 'broadcast',
210
+ payload: { namespace, data },
211
+ });
212
+ }
213
+ updateMetadata(meta) {
214
+ this.transport.send({ type: 'metadata', payload: meta });
215
+ }
216
+ closePeer(fingerprint) {
217
+ const peer = this.peers.get(fingerprint);
218
+ if (peer) {
219
+ peer.close();
220
+ this.peers.delete(fingerprint);
221
+ }
222
+ }
223
+ disconnect() {
224
+ this.peers.forEach((p) => p.close());
225
+ this.peers.clear();
226
+ this.namespaces.clear();
227
+ this.matchResolvers.clear();
228
+ if (this.registerPromise) {
229
+ this.registerPromise.reject(new Error('Disconnected'));
230
+ this.registerPromise = null;
231
+ }
232
+ this.transport.close();
233
+ }
234
+ async doRegister() {
235
+ if (this.registerPromise) {
236
+ this.registerPromise.reject(new Error('Register superseded'));
237
+ this.registerPromise = null;
238
+ }
239
+ if (!this.identity.publicKeyB64) {
240
+ if (this.config.identityKeys) {
241
+ await this.identity.restore(this.config.identityKeys);
242
+ }
243
+ else {
244
+ await this.identity.generate();
245
+ }
246
+ }
247
+ return new Promise((resolve, reject) => {
248
+ this.registerPromise = { resolve, reject };
249
+ this.transport.send({
250
+ type: 'register',
251
+ payload: {
252
+ public_key: this.identity.publicKeyB64,
253
+ alias: this.config.alias,
254
+ meta: this.config.meta,
255
+ },
256
+ });
257
+ });
258
+ }
259
+ createPeer(fingerprint, alias) {
260
+ const existing = this.peers.get(fingerprint);
261
+ if (existing)
262
+ return existing;
263
+ const peer = new Peer(fingerprint, alias, this.config.iceServers, (payload) => {
264
+ this.transport.send({ type: 'signal', to: fingerprint, payload });
265
+ });
266
+ peer.on('disconnected', () => {
267
+ this.peers.delete(fingerprint);
268
+ });
269
+ this.peers.set(fingerprint, peer);
270
+ return peer;
271
+ }
272
+ handleMessage(msg) {
273
+ switch (msg.type) {
274
+ case 'registered': {
275
+ const reg = typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload;
276
+ this.identity.setRegistered(reg.fingerprint, reg.alias);
277
+ this.registerPromise?.resolve();
278
+ this.registerPromise = null;
279
+ this.emit('registered', reg.fingerprint, reg.alias);
280
+ break;
281
+ }
282
+ case 'peer_list': {
283
+ const ns = msg.namespace ?? msg.payload?.namespace ?? '';
284
+ const peers = msg.payload?.peers ?? msg.payload ?? [];
285
+ this.emit('peer_list', ns, peers);
286
+ break;
287
+ }
288
+ case 'peer_joined': {
289
+ const info = msg.payload ?? { fingerprint: msg.from ?? '', alias: '' };
290
+ this.emit('peer_joined', info);
291
+ break;
292
+ }
293
+ case 'peer_left': {
294
+ const fp = msg.from ?? msg.payload?.fingerprint ?? '';
295
+ const peer = this.peers.get(fp);
296
+ if (peer) {
297
+ peer.close();
298
+ this.peers.delete(fp);
299
+ }
300
+ this.emit('peer_left', fp);
301
+ break;
302
+ }
303
+ case 'signal': {
304
+ const from = msg.from ?? '';
305
+ let peer = this.peers.get(from);
306
+ if (!peer) {
307
+ peer = this.createPeer(from, '');
308
+ }
309
+ peer.handleSignal(msg.payload);
310
+ break;
311
+ }
312
+ case 'matched': {
313
+ const result = typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload;
314
+ const resolver = this.matchResolvers.get(result.namespace);
315
+ if (resolver) {
316
+ this.matchResolvers.delete(result.namespace);
317
+ resolver(result);
318
+ }
319
+ this.emit('matched', result);
320
+ break;
321
+ }
322
+ case 'relay': {
323
+ this.emit('relay', msg.from, msg.payload);
324
+ break;
325
+ }
326
+ case 'broadcast': {
327
+ const ns = msg.namespace ?? msg.payload?.namespace ?? '';
328
+ const data = msg.payload?.data ?? msg.payload;
329
+ this.emit('broadcast', msg.from, ns, data);
330
+ break;
331
+ }
332
+ case 'room_created': {
333
+ const result = typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload;
334
+ this.emit('room_created', result);
335
+ break;
336
+ }
337
+ case 'room_closed': {
338
+ const result = typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload;
339
+ if (result?.room_id) {
340
+ this.namespaces.delete(result.room_id);
341
+ }
342
+ this.emit('room_closed', result);
343
+ break;
344
+ }
345
+ case 'kick': {
346
+ const payload = typeof msg.payload === 'string' ? JSON.parse(msg.payload) : msg.payload;
347
+ if (payload?.room_id) {
348
+ this.namespaces.delete(payload.room_id);
349
+ }
350
+ this.emit('kicked', payload);
351
+ break;
352
+ }
353
+ case 'error': {
354
+ this.emit('error', msg.payload);
355
+ this.registerPromise?.reject(new Error(typeof msg.payload === 'string' ? msg.payload : JSON.stringify(msg.payload)));
356
+ this.registerPromise = null;
357
+ break;
358
+ }
359
+ }
360
+ }
361
+ }
@@ -0,0 +1,11 @@
1
+ export type ErrorHandler = (error: unknown, event: string) => void;
2
+ export declare function setEmitterErrorHandler(handler: ErrorHandler): void;
3
+ export declare class Emitter<Events extends string = string> {
4
+ private listeners;
5
+ on(event: Events, fn: (...args: any[]) => void): () => void;
6
+ once(event: Events, fn: (...args: any[]) => void): () => void;
7
+ off(event: Events, fn: (...args: any[]) => void): void;
8
+ emit(event: Events, ...args: any[]): void;
9
+ listenerCount(event: Events): number;
10
+ removeAllListeners(event?: Events): void;
11
+ }
@@ -0,0 +1,46 @@
1
+ let globalErrorHandler = (error, event) => {
2
+ console.error(`[Emitter] Error in "${event}" listener:`, error);
3
+ };
4
+ export function setEmitterErrorHandler(handler) {
5
+ globalErrorHandler = handler;
6
+ }
7
+ export class Emitter {
8
+ listeners = new Map();
9
+ on(event, fn) {
10
+ if (!this.listeners.has(event))
11
+ this.listeners.set(event, new Set());
12
+ this.listeners.get(event).add(fn);
13
+ return () => this.off(event, fn);
14
+ }
15
+ once(event, fn) {
16
+ const wrapper = (...args) => {
17
+ this.off(event, wrapper);
18
+ fn(...args);
19
+ };
20
+ return this.on(event, wrapper);
21
+ }
22
+ off(event, fn) {
23
+ this.listeners.get(event)?.delete(fn);
24
+ }
25
+ emit(event, ...args) {
26
+ this.listeners.get(event)?.forEach((fn) => {
27
+ try {
28
+ fn(...args);
29
+ }
30
+ catch (e) {
31
+ globalErrorHandler(e, event);
32
+ }
33
+ });
34
+ }
35
+ listenerCount(event) {
36
+ return this.listeners.get(event)?.size ?? 0;
37
+ }
38
+ removeAllListeners(event) {
39
+ if (event) {
40
+ this.listeners.delete(event);
41
+ }
42
+ else {
43
+ this.listeners.clear();
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,15 @@
1
+ import type { IdentityKeys } from './types';
2
+ export declare class Identity {
3
+ fingerprint: string;
4
+ alias: string;
5
+ publicKeyB64: string;
6
+ private keyPair;
7
+ generate(): Promise<string>;
8
+ restore(keys: IdentityKeys): Promise<void>;
9
+ export(): Promise<IdentityKeys>;
10
+ setRegistered(fingerprint: string, alias: string): void;
11
+ sign(data: ArrayBuffer): Promise<ArrayBuffer>;
12
+ verify(publicKey: CryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean>;
13
+ getPublicKey(): CryptoKey | null;
14
+ getPrivateKey(): CryptoKey | null;
15
+ }
@@ -0,0 +1,54 @@
1
+ export class Identity {
2
+ fingerprint = '';
3
+ alias = '';
4
+ publicKeyB64 = '';
5
+ keyPair = null;
6
+ async generate() {
7
+ this.keyPair = await crypto.subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, ['sign', 'verify']);
8
+ const raw = await crypto.subtle.exportKey('raw', this.keyPair.publicKey);
9
+ this.publicKeyB64 = btoa(String.fromCharCode(...new Uint8Array(raw)));
10
+ return this.publicKeyB64;
11
+ }
12
+ async restore(keys) {
13
+ const privateKey = await crypto.subtle.importKey('jwk', keys.privateKeyJwk, { name: 'ECDSA', namedCurve: 'P-256' }, true, ['sign']);
14
+ const publicKey = await crypto.subtle.importKey('jwk', keys.publicKeyJwk, { name: 'ECDSA', namedCurve: 'P-256' }, true, ['verify']);
15
+ this.keyPair = { privateKey, publicKey };
16
+ this.fingerprint = keys.fingerprint;
17
+ this.alias = keys.alias;
18
+ this.publicKeyB64 = keys.publicKeyB64;
19
+ }
20
+ async export() {
21
+ if (!this.keyPair)
22
+ throw new Error('No keypair generated');
23
+ const [privateKeyJwk, publicKeyJwk] = await Promise.all([
24
+ crypto.subtle.exportKey('jwk', this.keyPair.privateKey),
25
+ crypto.subtle.exportKey('jwk', this.keyPair.publicKey),
26
+ ]);
27
+ return {
28
+ fingerprint: this.fingerprint,
29
+ alias: this.alias,
30
+ publicKeyB64: this.publicKeyB64,
31
+ privateKeyJwk,
32
+ publicKeyJwk,
33
+ };
34
+ }
35
+ setRegistered(fingerprint, alias) {
36
+ this.fingerprint = fingerprint;
37
+ this.alias = alias;
38
+ }
39
+ async sign(data) {
40
+ if (!this.keyPair)
41
+ throw new Error('No keypair generated');
42
+ const result = await crypto.subtle.sign({ name: 'ECDSA', hash: 'SHA-256' }, this.keyPair.privateKey, data);
43
+ return new Uint8Array(result).buffer;
44
+ }
45
+ async verify(publicKey, signature, data) {
46
+ return crypto.subtle.verify({ name: 'ECDSA', hash: 'SHA-256' }, publicKey, signature, data);
47
+ }
48
+ getPublicKey() {
49
+ return this.keyPair?.publicKey ?? null;
50
+ }
51
+ getPrivateKey() {
52
+ return this.keyPair?.privateKey ?? null;
53
+ }
54
+ }
@@ -0,0 +1,6 @@
1
+ export { PeerClient } from './client';
2
+ export { Peer } from './peer';
3
+ export { Identity } from './identity';
4
+ export { Transport } from './transport';
5
+ export { Emitter, setEmitterErrorHandler } from './emitter';
6
+ export * from './types';
@@ -0,0 +1,6 @@
1
+ export { PeerClient } from './client';
2
+ export { Peer } from './peer';
3
+ export { Identity } from './identity';
4
+ export { Transport } from './transport';
5
+ export { Emitter, setEmitterErrorHandler } from './emitter';
6
+ export * from './types';
@@ -0,0 +1,29 @@
1
+ import { Emitter } from './emitter';
2
+ import type { PeerEvent, DataChannelConfig } from './types';
3
+ export declare class Peer extends Emitter<PeerEvent> {
4
+ readonly fingerprint: string;
5
+ readonly alias: string;
6
+ readonly pc: RTCPeerConnection;
7
+ private channels;
8
+ private pendingCandidates;
9
+ private remoteDescSet;
10
+ private _closed;
11
+ private _sendSignal;
12
+ constructor(fingerprint: string, alias: string, iceServers: RTCIceServer[], sendSignal: (payload: any) => void);
13
+ createOffer(channelConfig?: DataChannelConfig): Promise<void>;
14
+ handleSignal(payload: any): Promise<void>;
15
+ send(data: any, channel?: string): void;
16
+ sendBinary(data: ArrayBuffer, channel?: string): void;
17
+ addStream(stream: MediaStream): void;
18
+ removeStream(stream: MediaStream): void;
19
+ createDataChannel(config: DataChannelConfig): RTCDataChannel;
20
+ getChannel(label: string): RTCDataChannel | undefined;
21
+ getBufferedAmount(channel?: string): number;
22
+ get connectionState(): string;
23
+ get channelLabels(): string[];
24
+ get closed(): boolean;
25
+ restartIce(): void;
26
+ close(): void;
27
+ private setupChannel;
28
+ private flushCandidates;
29
+ }