openrtc 0.1.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 (122) hide show
  1. package/README.md +106 -0
  2. package/dist/OpenRTC.d.ts +71 -0
  3. package/dist/OpenRTC.js +130 -0
  4. package/dist/api/MediaTransport.d.ts +7 -0
  5. package/dist/api/MediaTransport.js +262 -0
  6. package/dist/api/PlutoPeerConnection.d.ts +50 -0
  7. package/dist/api/PlutoPeerConnection.js +434 -0
  8. package/dist/api/PlutoWebSocket.d.ts +24 -0
  9. package/dist/api/PlutoWebSocket.js +113 -0
  10. package/dist/api/PlutoWebTransport.d.ts +29 -0
  11. package/dist/api/PlutoWebTransport.js +105 -0
  12. package/dist/auth/host.d.ts +73 -0
  13. package/dist/auth/host.js +513 -0
  14. package/dist/auth/index.d.ts +1 -0
  15. package/dist/auth/index.js +1 -0
  16. package/dist/auth/internal.d.ts +1 -0
  17. package/dist/auth/internal.js +1 -0
  18. package/dist/compat/index.d.ts +20 -0
  19. package/dist/compat/index.js +20 -0
  20. package/dist/core/Client.d.ts +352 -0
  21. package/dist/core/Client.js +3689 -0
  22. package/dist/core/Connection.d.ts +67 -0
  23. package/dist/core/Connection.js +404 -0
  24. package/dist/core/IEngineBridge.d.ts +18 -0
  25. package/dist/core/IEngineBridge.js +1 -0
  26. package/dist/core/ISignalingTransport.d.ts +13 -0
  27. package/dist/core/ISignalingTransport.js +1 -0
  28. package/dist/core/PeerLifecycleManager.d.ts +43 -0
  29. package/dist/core/PeerLifecycleManager.js +330 -0
  30. package/dist/core/PeerProjectionStore.d.ts +43 -0
  31. package/dist/core/PeerProjectionStore.js +327 -0
  32. package/dist/core/PlutoRTC.d.ts +13 -0
  33. package/dist/core/PlutoRTC.js +26 -0
  34. package/dist/core/Room.d.ts +47 -0
  35. package/dist/core/Room.js +376 -0
  36. package/dist/core/Signaling.d.ts +39 -0
  37. package/dist/core/Signaling.js +147 -0
  38. package/dist/core/bridges/BridgeCodecs.d.ts +19 -0
  39. package/dist/core/bridges/BridgeCodecs.js +317 -0
  40. package/dist/core/bridges/BrowserFirestoreRooms.d.ts +36 -0
  41. package/dist/core/bridges/BrowserFirestoreRooms.js +169 -0
  42. package/dist/core/bridges/BrowserFirestoreSignaling.d.ts +111 -0
  43. package/dist/core/bridges/BrowserFirestoreSignaling.js +1010 -0
  44. package/dist/core/bridges/NativeIpcBridge.d.ts +156 -0
  45. package/dist/core/bridges/NativeIpcBridge.js +1472 -0
  46. package/dist/core/bridges/RtdbPresence.d.ts +122 -0
  47. package/dist/core/bridges/RtdbPresence.js +201 -0
  48. package/dist/core/bridges/TauriBridge.d.ts +8 -0
  49. package/dist/core/bridges/TauriBridge.js +7 -0
  50. package/dist/core/bridges/WasmBridge.d.ts +233 -0
  51. package/dist/core/bridges/WasmBridge.js +1811 -0
  52. package/dist/core/config.d.ts +31 -0
  53. package/dist/core/config.js +138 -0
  54. package/dist/core/transports/ITransport.d.ts +12 -0
  55. package/dist/core/transports/ITransport.js +1 -0
  56. package/dist/core/transports/LocalDaemonBridge.d.ts +41 -0
  57. package/dist/core/transports/LocalDaemonBridge.js +227 -0
  58. package/dist/core/transports/TauriSignaling.d.ts +28 -0
  59. package/dist/core/transports/TauriSignaling.js +373 -0
  60. package/dist/core/transports/TransportFactory.d.ts +9 -0
  61. package/dist/core/transports/TransportFactory.js +59 -0
  62. package/dist/core/transports/WasmSignaling.d.ts +78 -0
  63. package/dist/core/transports/WasmSignaling.js +522 -0
  64. package/dist/core/transports/WebRTCTransport.d.ts +23 -0
  65. package/dist/core/transports/WebRTCTransport.js +132 -0
  66. package/dist/core/trust.d.ts +23 -0
  67. package/dist/core/trust.js +99 -0
  68. package/dist/core/types.d.ts +559 -0
  69. package/dist/core/types.js +19 -0
  70. package/dist/index.d.ts +3 -0
  71. package/dist/index.js +3 -0
  72. package/dist/moq/MoQMediaTransport.d.ts +6 -0
  73. package/dist/moq/MoQMediaTransport.js +106 -0
  74. package/dist/moq/MoQPublisher.d.ts +22 -0
  75. package/dist/moq/MoQPublisher.js +179 -0
  76. package/dist/moq/MoQSession.d.ts +35 -0
  77. package/dist/moq/MoQSession.js +166 -0
  78. package/dist/moq/MoQSubscriber.d.ts +19 -0
  79. package/dist/moq/MoQSubscriber.js +235 -0
  80. package/dist/moq/common.d.ts +47 -0
  81. package/dist/moq/common.js +304 -0
  82. package/dist/moq/messages.d.ts +105 -0
  83. package/dist/moq/messages.js +367 -0
  84. package/dist/presets/plutoHosted.d.ts +13 -0
  85. package/dist/presets/plutoHosted.js +18 -0
  86. package/dist/runtime/DelegatingRuntimeAdapter.d.ts +68 -0
  87. package/dist/runtime/DelegatingRuntimeAdapter.js +250 -0
  88. package/dist/runtime/IpcRuntimeAdapter.d.ts +9 -0
  89. package/dist/runtime/IpcRuntimeAdapter.js +13 -0
  90. package/dist/runtime/RuntimeClient.d.ts +257 -0
  91. package/dist/runtime/RuntimeClient.js +1484 -0
  92. package/dist/runtime/TauriRuntimeAdapter.d.ts +1 -0
  93. package/dist/runtime/TauriRuntimeAdapter.js +1 -0
  94. package/dist/runtime/WasmRuntimeAdapter.d.ts +6 -0
  95. package/dist/runtime/WasmRuntimeAdapter.js +11 -0
  96. package/dist/runtime/factories.d.ts +24 -0
  97. package/dist/runtime/factories.js +66 -0
  98. package/dist/runtime/index.d.ts +6 -0
  99. package/dist/runtime/index.js +5 -0
  100. package/dist/runtime/ipc.d.ts +8 -0
  101. package/dist/runtime/ipc.js +65 -0
  102. package/dist/runtime/ipcContract.d.ts +46 -0
  103. package/dist/runtime/ipcContract.js +1 -0
  104. package/dist/runtime/tauri.d.ts +16 -0
  105. package/dist/runtime/tauri.js +22 -0
  106. package/dist/runtime/types.d.ts +110 -0
  107. package/dist/runtime/types.js +1 -0
  108. package/dist/transports/TauriTransport.d.ts +17 -0
  109. package/dist/transports/TauriTransport.js +49 -0
  110. package/dist/transports/WebTransport.d.ts +23 -0
  111. package/dist/transports/WebTransport.js +71 -0
  112. package/dist/utils/debug.d.ts +4 -0
  113. package/dist/utils/debug.js +33 -0
  114. package/dist/utils/runtime.d.ts +1 -0
  115. package/dist/utils/runtime.js +10 -0
  116. package/package.json +97 -0
  117. package/wasm/README.md +64 -0
  118. package/wasm/openrtc.d.ts +284 -0
  119. package/wasm/openrtc.js +2132 -0
  120. package/wasm/openrtc_bg.wasm +0 -0
  121. package/wasm/openrtc_bg.wasm.d.ts +110 -0
  122. package/wasm/package.json +16 -0
@@ -0,0 +1,373 @@
1
+ import { WasmSignalingBackend } from './WasmSignaling';
2
+ function isTauri() {
3
+ return typeof window !== 'undefined' && !!window.__TAURI_INTERNALS__;
4
+ }
5
+ export class TauriSignalingBackend extends WasmSignalingBackend {
6
+ constructor(options) {
7
+ super(options);
8
+ this.daemonSignalingEnabled = false;
9
+ this.subscriptionNonce = 0;
10
+ this.lastSyncedAuthToken = null;
11
+ this.cachedLocalDeviceId = null;
12
+ }
13
+ setDaemonSignalingEnabled(enabled) {
14
+ this.daemonSignalingEnabled = enabled;
15
+ }
16
+ async ensureDaemonAuth() {
17
+ if (!isTauri() || !this.daemonSignalingEnabled) {
18
+ return;
19
+ }
20
+ try {
21
+ await this.waitForAuth();
22
+ if (!this.currentUser) {
23
+ await this.signInAnonymously();
24
+ await this.waitForAuth();
25
+ }
26
+ const token = this.currentUser && this.currentUser.getToken
27
+ ? await this.currentUser.getToken()
28
+ : null;
29
+ if (!token) {
30
+ console.warn('[TauriSignaling] No Firebase auth token available for daemon auth sync');
31
+ return;
32
+ }
33
+ if (token === this.lastSyncedAuthToken) {
34
+ return;
35
+ }
36
+ const { invoke } = await import('@tauri-apps/api/core');
37
+ await invoke('set_rtc_auth_token', { authToken: token });
38
+ this.lastSyncedAuthToken = token;
39
+ console.log(`[TauriSignaling] Synced daemon auth token (len=${token.length})`);
40
+ }
41
+ catch (error) {
42
+ console.warn('[TauriSignaling] Failed to sync daemon auth token:', error);
43
+ }
44
+ }
45
+ async resolveLocalDeviceId() {
46
+ if (this.cachedLocalDeviceId) {
47
+ return this.cachedLocalDeviceId;
48
+ }
49
+ if (!isTauri()) {
50
+ return null;
51
+ }
52
+ try {
53
+ const { invoke } = await import('@tauri-apps/api/core');
54
+ const deviceInfo = await invoke('get_device_info');
55
+ const deviceId = typeof deviceInfo?.device_id === 'string' ? deviceInfo.device_id.trim() : '';
56
+ if (!deviceId) {
57
+ return null;
58
+ }
59
+ this.cachedLocalDeviceId = deviceId;
60
+ return deviceId;
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ }
66
+ withPresenceMetadata(metadata, localDeviceId) {
67
+ if (!localDeviceId) {
68
+ return metadata || null;
69
+ }
70
+ if (!metadata || !metadata.trim()) {
71
+ return JSON.stringify({ deviceId: localDeviceId });
72
+ }
73
+ try {
74
+ const parsed = JSON.parse(metadata);
75
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
76
+ return JSON.stringify({
77
+ ...parsed,
78
+ deviceId: localDeviceId,
79
+ });
80
+ }
81
+ }
82
+ catch {
83
+ // fall through to wrapped raw metadata format
84
+ }
85
+ return JSON.stringify({
86
+ deviceId: localDeviceId,
87
+ raw: metadata,
88
+ });
89
+ }
90
+ async updatePresence(localNodeId, ticketStr, isOnline = true, ttlMs = 5 * 60 * 1000, metadata) {
91
+ if (!this.currentUser)
92
+ return;
93
+ if (!isTauri() || !this.daemonSignalingEnabled) {
94
+ return super.updatePresence(localNodeId, ticketStr, isOnline, ttlMs, metadata);
95
+ }
96
+ await this.ensureDaemonAuth();
97
+ const localDeviceId = await this.resolveLocalDeviceId();
98
+ let name = "Desktop App";
99
+ if (typeof navigator !== 'undefined') {
100
+ if (navigator.userAgent.includes("Mac OS X"))
101
+ name = "macOS";
102
+ else if (navigator.userAgent.includes("Windows"))
103
+ name = "Windows";
104
+ else if (navigator.userAgent.includes("Linux"))
105
+ name = "Linux";
106
+ }
107
+ const { invoke } = await import('@tauri-apps/api/core');
108
+ await invoke('update_rtc_presence', {
109
+ userId: this.currentUser.id,
110
+ localNodeId,
111
+ deviceName: name,
112
+ ticket: ticketStr,
113
+ metadata: this.withPresenceMetadata(metadata, localDeviceId)
114
+ });
115
+ }
116
+ async searchDevices(excludeNodeId) {
117
+ if (!this.currentUser)
118
+ return [];
119
+ if (!isTauri() || !this.daemonSignalingEnabled) {
120
+ return super.searchDevices(excludeNodeId);
121
+ }
122
+ await this.ensureDaemonAuth();
123
+ const { invoke } = await import('@tauri-apps/api/core');
124
+ const jsonLine = await invoke('search_rtc_devices', {
125
+ userId: this.currentUser.id,
126
+ excludeNodeId: excludeNodeId || null,
127
+ });
128
+ if (jsonLine) {
129
+ const parsed = JSON.parse(jsonLine);
130
+ if (parsed.type === "devices") {
131
+ const devs = (parsed.devices || [])
132
+ .map((d) => this.normalizeDevice(d))
133
+ .filter((device) => this.matchesTag(device));
134
+ if (excludeNodeId) {
135
+ return devs.filter(d => d.ticket !== excludeNodeId && d.deviceId !== excludeNodeId);
136
+ }
137
+ return devs;
138
+ }
139
+ if (parsed.type === 'error') {
140
+ throw new Error(parsed.message || 'Daemon searchDevices failed');
141
+ }
142
+ }
143
+ throw new Error('Daemon returned unexpected searchDevices response');
144
+ }
145
+ async setOffline(localNodeId) {
146
+ if (!this.currentUser)
147
+ return;
148
+ if (!isTauri() || !this.daemonSignalingEnabled) {
149
+ return super.setOffline(localNodeId);
150
+ }
151
+ await this.ensureDaemonAuth();
152
+ const { invoke } = await import('@tauri-apps/api/core');
153
+ await invoke('set_rtc_offline', {
154
+ userId: this.currentUser.id,
155
+ localNodeId,
156
+ });
157
+ }
158
+ onDevicesChange(callback, excludeNodeId) {
159
+ if (!this.currentUser) {
160
+ return () => { };
161
+ }
162
+ if (!isTauri() || !this.daemonSignalingEnabled) {
163
+ return super.onDevicesChange(callback, excludeNodeId);
164
+ }
165
+ let cancelled = false;
166
+ const devicesById = new Map();
167
+ let reader = null;
168
+ const emit = () => {
169
+ let devices = Array.from(devicesById.values());
170
+ if (excludeNodeId) {
171
+ devices = devices.filter((device) => device.ticket !== excludeNodeId && device.deviceId !== excludeNodeId);
172
+ }
173
+ callback(devices);
174
+ };
175
+ const bootstrap = async () => {
176
+ try {
177
+ const initialDevices = await this.searchDevices(excludeNodeId);
178
+ devicesById.clear();
179
+ for (const device of initialDevices) {
180
+ devicesById.set(device.deviceId, device);
181
+ }
182
+ emit();
183
+ const stream = await this.subscribeDevices(this.currentUser.id);
184
+ reader = stream.getReader();
185
+ while (!cancelled) {
186
+ const { done, value } = await reader.read();
187
+ if (done || !value)
188
+ break;
189
+ for (const event of value) {
190
+ if (event.type === 'removed') {
191
+ devicesById.delete(event.deviceId);
192
+ continue;
193
+ }
194
+ const normalized = this.normalizeDevice(event.device);
195
+ if (!normalized.deviceId)
196
+ continue;
197
+ if (!this.matchesTag(normalized)) {
198
+ devicesById.delete(normalized.deviceId);
199
+ continue;
200
+ }
201
+ devicesById.set(normalized.deviceId, normalized);
202
+ }
203
+ emit();
204
+ }
205
+ }
206
+ catch (error) {
207
+ if (!cancelled) {
208
+ console.error('[TauriSignaling] onDevicesChange stream failed:', error);
209
+ }
210
+ }
211
+ };
212
+ void bootstrap();
213
+ return () => {
214
+ cancelled = true;
215
+ if (reader) {
216
+ void reader.cancel();
217
+ reader = null;
218
+ }
219
+ };
220
+ }
221
+ async subscribeDevices(userId) {
222
+ if (!isTauri() || !this.daemonSignalingEnabled) {
223
+ return super.subscribeDevices(userId);
224
+ }
225
+ await this.ensureDaemonAuth();
226
+ const { invoke } = await import('@tauri-apps/api/core');
227
+ const { listen } = await import('@tauri-apps/api/event');
228
+ const requestId = `rtc-devices-${Date.now()}-${++this.subscriptionNonce}`;
229
+ const normalizeEvents = (events) => {
230
+ if (!Array.isArray(events))
231
+ return [];
232
+ const output = [];
233
+ for (const event of events) {
234
+ if (!event || typeof event !== 'object')
235
+ continue;
236
+ const evt = event;
237
+ const type = typeof evt.type === 'string' ? evt.type : '';
238
+ if (type === 'removed' && typeof evt.deviceId === 'string') {
239
+ output.push({ type: 'removed', deviceId: evt.deviceId });
240
+ continue;
241
+ }
242
+ if ((type === 'added' || type === 'modified') && evt.device && typeof evt.device === 'object') {
243
+ const device = this.normalizeDevice(evt.device);
244
+ if (!this.matchesTag(device)) {
245
+ continue;
246
+ }
247
+ output.push({ type, device });
248
+ }
249
+ }
250
+ return output;
251
+ };
252
+ let stopSubscription = null;
253
+ return new ReadableStream({
254
+ async start(controller) {
255
+ let unlisten = null;
256
+ const stop = async () => {
257
+ if (unlisten) {
258
+ unlisten();
259
+ unlisten = null;
260
+ }
261
+ try {
262
+ await invoke('stop_rtc_subscription', { requestId });
263
+ }
264
+ catch {
265
+ // noop
266
+ }
267
+ };
268
+ stopSubscription = stop;
269
+ unlisten = await listen('rtc-device-events', (event) => {
270
+ const payload = event.payload;
271
+ if (!payload || payload.requestId !== requestId)
272
+ return;
273
+ if (payload.type === 'error') {
274
+ controller.error(new Error(payload.message || 'RTC device subscription failed'));
275
+ void stop();
276
+ return;
277
+ }
278
+ if (payload.type !== 'deviceEvents') {
279
+ return;
280
+ }
281
+ controller.enqueue(normalizeEvents(payload.events));
282
+ });
283
+ try {
284
+ await invoke('start_rtc_device_subscription', { requestId, userId });
285
+ }
286
+ catch (error) {
287
+ await stop();
288
+ controller.error(error);
289
+ }
290
+ },
291
+ async cancel() {
292
+ if (stopSubscription) {
293
+ await stopSubscription();
294
+ stopSubscription = null;
295
+ }
296
+ },
297
+ });
298
+ }
299
+ async subscribeSessions(localDeviceId) {
300
+ if (!isTauri() || !this.daemonSignalingEnabled) {
301
+ return super.subscribeSessions(localDeviceId);
302
+ }
303
+ await this.ensureDaemonAuth();
304
+ const { invoke } = await import('@tauri-apps/api/core');
305
+ const { listen } = await import('@tauri-apps/api/event');
306
+ const requestId = `rtc-sessions-${Date.now()}-${++this.subscriptionNonce}`;
307
+ const normalizeEvents = (events) => {
308
+ if (!Array.isArray(events))
309
+ return [];
310
+ const output = [];
311
+ for (const event of events) {
312
+ if (!event || typeof event !== 'object')
313
+ continue;
314
+ const evt = event;
315
+ const type = typeof evt.type === 'string' ? evt.type : '';
316
+ if (type === 'removed' && typeof evt.sessionId === 'string') {
317
+ output.push({ type: 'removed', sessionId: evt.sessionId });
318
+ continue;
319
+ }
320
+ if ((type === 'added' || type === 'modified') && evt.session && typeof evt.session === 'object') {
321
+ output.push({ type, session: evt.session });
322
+ }
323
+ }
324
+ return output;
325
+ };
326
+ let stopSubscription = null;
327
+ return new ReadableStream({
328
+ async start(controller) {
329
+ let unlisten = null;
330
+ const stop = async () => {
331
+ if (unlisten) {
332
+ unlisten();
333
+ unlisten = null;
334
+ }
335
+ try {
336
+ await invoke('stop_rtc_subscription', { requestId });
337
+ }
338
+ catch {
339
+ // noop
340
+ }
341
+ };
342
+ stopSubscription = stop;
343
+ unlisten = await listen('rtc-session-events', (event) => {
344
+ const payload = event.payload;
345
+ if (!payload || payload.requestId !== requestId)
346
+ return;
347
+ if (payload.type === 'error') {
348
+ controller.error(new Error(payload.message || 'RTC session subscription failed'));
349
+ void stop();
350
+ return;
351
+ }
352
+ if (payload.type !== 'sessionEvents') {
353
+ return;
354
+ }
355
+ controller.enqueue(normalizeEvents(payload.events));
356
+ });
357
+ try {
358
+ await invoke('start_rtc_session_subscription', { requestId, localDeviceId });
359
+ }
360
+ catch (error) {
361
+ await stop();
362
+ controller.error(error);
363
+ }
364
+ },
365
+ async cancel() {
366
+ if (stopSubscription) {
367
+ await stopSubscription();
368
+ stopSubscription = null;
369
+ }
370
+ },
371
+ });
372
+ }
373
+ }
@@ -0,0 +1,9 @@
1
+ import { ITransport } from './ITransport';
2
+ import { ProtocolCapability, ProtocolCapabilityMap, ProtocolName } from '../types';
3
+ export declare class TransportFactory {
4
+ private static readonly capabilityMap;
5
+ static createTransport(name: ProtocolName): ITransport;
6
+ static getProtocolCapability(name: ProtocolName): ProtocolCapability;
7
+ static getProtocolCapabilities(): ProtocolCapabilityMap;
8
+ static assertProtocolAvailable(name: ProtocolName): void;
9
+ }
@@ -0,0 +1,59 @@
1
+ import { WebRTCTransport } from './WebRTCTransport';
2
+ export class TransportFactory {
3
+ static createTransport(name) {
4
+ this.assertProtocolAvailable(name);
5
+ if (name === 'webrtc') {
6
+ return new WebRTCTransport();
7
+ }
8
+ throw new Error(`[TransportFactory] '${name}' is not implemented as an ITransport plugin.`);
9
+ }
10
+ static getProtocolCapability(name) {
11
+ return { ...this.capabilityMap[name] };
12
+ }
13
+ static getProtocolCapabilities() {
14
+ return {
15
+ iroh: this.getProtocolCapability('iroh'),
16
+ webrtc: this.getProtocolCapability('webrtc'),
17
+ websocket: this.getProtocolCapability('websocket'),
18
+ webtransport: this.getProtocolCapability('webtransport'),
19
+ moq: this.getProtocolCapability('moq'),
20
+ };
21
+ }
22
+ static assertProtocolAvailable(name) {
23
+ const capability = this.capabilityMap[name];
24
+ if (!capability.available || capability.maturity === 'unsupported') {
25
+ const reason = capability.reason ? ` ${capability.reason}` : '';
26
+ throw new Error(`[TransportFactory] Protocol '${name}' is unsupported.${reason}`);
27
+ }
28
+ }
29
+ }
30
+ TransportFactory.capabilityMap = {
31
+ iroh: {
32
+ protocol: 'iroh',
33
+ maturity: 'stable',
34
+ available: true,
35
+ },
36
+ webrtc: {
37
+ protocol: 'webrtc',
38
+ maturity: 'stable',
39
+ available: true,
40
+ },
41
+ websocket: {
42
+ protocol: 'websocket',
43
+ maturity: 'experimental',
44
+ available: true,
45
+ reason: 'Adapter over Pluto client connection primitives.',
46
+ },
47
+ webtransport: {
48
+ protocol: 'webtransport',
49
+ maturity: 'experimental',
50
+ available: true,
51
+ reason: 'Pluto ticket-backed adapter via core connection system.',
52
+ },
53
+ moq: {
54
+ protocol: 'moq',
55
+ maturity: 'experimental',
56
+ available: true,
57
+ reason: 'Client-level session lifecycle with evolving media/data semantics.',
58
+ },
59
+ };
@@ -0,0 +1,78 @@
1
+ import { FirebaseApp } from 'firebase/app';
2
+ import { Auth } from 'firebase/auth';
3
+ import { Device, DeviceEvent, ISignalingBackend, LocalDaemonInfo, RuntimeIdentity, SignalingEnvelope, SignalingSession, SessionEvent } from '../types';
4
+ export declare class WasmSignalingBackend implements ISignalingBackend {
5
+ app: FirebaseApp;
6
+ auth: Auth;
7
+ tag: string;
8
+ private options;
9
+ private authListeners;
10
+ private persistenceReady;
11
+ wasmClient: any;
12
+ private missingWasmWarnings;
13
+ private readonly wasmReadyWarningDelayMs;
14
+ private readonly deviceListeners;
15
+ private nextDeviceListenerId;
16
+ private deviceReader;
17
+ private devicesById;
18
+ private activeDeviceUserId;
19
+ private deviceSubscriptionCancelled;
20
+ private deviceSubscriptionTask;
21
+ private authContext;
22
+ constructor(options: {
23
+ tag: string;
24
+ storagePrefix?: string;
25
+ nodeIdPersistence?: 'persistent' | 'ephemeral';
26
+ });
27
+ private static readonly WEB_DEVICE_ID_STORAGE_PREFIX;
28
+ private static readonly EPHEMERAL_DEVICE_ID_TTL_MS;
29
+ private getDeviceIdentityStorageKey;
30
+ private getNodeIdPersistenceMode;
31
+ private createRandomDeviceId;
32
+ private resolveWebLogicalDeviceId;
33
+ private withWebPresenceMetadata;
34
+ setAuthContext(context: {
35
+ userId: string;
36
+ token?: string | null;
37
+ } | null): void;
38
+ private toRuntimeIdentity;
39
+ protected getCurrentUserId(): string | null;
40
+ private getFilteredDevices;
41
+ protected matchesTag(device: Pick<Device, 'tag'>): boolean;
42
+ private emitDeviceUpdateForListener;
43
+ private emitDeviceUpdate;
44
+ private applyDeviceEvents;
45
+ private stopDeviceSubscription;
46
+ private startDeviceSubscription;
47
+ setWasmClient(client: any): void;
48
+ private warnMissingWasmOnce;
49
+ private waitForWasmClient;
50
+ private emptyStream;
51
+ protected normalizeDevice(raw: Record<string, any>, fallbackId?: string): Device;
52
+ get currentUser(): RuntimeIdentity | null;
53
+ onAuthChange(callback: (user: RuntimeIdentity | null) => void): () => void;
54
+ checkForSSOToken(): Promise<void>;
55
+ waitForAuth(): Promise<void>;
56
+ signInAnonymously(): Promise<void>;
57
+ signOut(): Promise<void>;
58
+ getTurnCredentials(): Promise<any>;
59
+ updatePresence(localNodeId: string, ticketStr: string, isOnline?: boolean, ttlMs?: number, metadata?: string): Promise<void>;
60
+ setOffline(localNodeId: string): Promise<void>;
61
+ cleanupStaleDevices(): Promise<void>;
62
+ sendMessage(targetId: string, payload: string, state?: string, replyPayload?: string): Promise<string>;
63
+ pollMessages(targetId: string): Promise<SignalingEnvelope[]>;
64
+ searchDevices(excludeNodeId?: string): Promise<Device[]>;
65
+ onDevicesChange(callback: (devices: Device[]) => void, excludeNodeId?: string): () => void;
66
+ subscribeDevices(userId: string): Promise<ReadableStream<DeviceEvent[]>>;
67
+ createSession(session: SignalingSession): Promise<void>;
68
+ updateSession(sessionId: string, updateData: any): Promise<void>;
69
+ subscribeSessions(localDeviceId: string): Promise<ReadableStream<SessionEvent[]>>;
70
+ advertiseLocalDaemon(params: {
71
+ deviceId: string;
72
+ host: string;
73
+ localPort: number;
74
+ localToken: string;
75
+ ttlMs?: number;
76
+ }): Promise<void>;
77
+ findLocalDaemons(): Promise<LocalDaemonInfo[]>;
78
+ }