@decentnetwork/beagle 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.
@@ -0,0 +1,1070 @@
1
+ var PeerWebRTC = (() => {
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var __accessCheck = (obj, member, msg) => {
20
+ if (!member.has(obj))
21
+ throw TypeError("Cannot " + msg);
22
+ };
23
+ var __privateGet = (obj, member, getter) => {
24
+ __accessCheck(obj, member, "read from private field");
25
+ return getter ? getter.call(obj) : member.get(obj);
26
+ };
27
+ var __privateAdd = (obj, member, value) => {
28
+ if (member.has(obj))
29
+ throw TypeError("Cannot add the same private member more than once");
30
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
31
+ };
32
+ var __privateSet = (obj, member, value, setter) => {
33
+ __accessCheck(obj, member, "write to private field");
34
+ setter ? setter.call(obj, value) : member.set(obj, value);
35
+ return value;
36
+ };
37
+ var __privateMethod = (obj, member, method) => {
38
+ __accessCheck(obj, member, "access private method");
39
+ return method;
40
+ };
41
+
42
+ // node_modules/@decentnetwork/peer-webrtc/dist/index.js
43
+ var dist_exports = {};
44
+ __export(dist_exports, {
45
+ BeaglePushClient: () => BeaglePushClient,
46
+ BroadcastChannelSignaling: () => BroadcastChannelSignaling,
47
+ CallEngine: () => CallEngine,
48
+ CarrierSignaling: () => CarrierSignaling,
49
+ Emitter: () => Emitter,
50
+ SocketIoSignaling: () => SocketIoSignaling,
51
+ decodeSignal: () => decodeSignal,
52
+ decodeSignalBytesGuard: () => decodeSignalBytesGuard,
53
+ encodeSignal: () => encodeSignal,
54
+ encodeSignalBytes: () => encodeSignalBytes,
55
+ looksLikeSignal: () => looksLikeSignal
56
+ });
57
+
58
+ // node_modules/@decentnetwork/peer-webrtc/dist/emitter.js
59
+ var _handlers;
60
+ var Emitter = class {
61
+ constructor() {
62
+ __privateAdd(this, _handlers, {});
63
+ }
64
+ on(event, handler) {
65
+ var _a, _b;
66
+ ((_b = (_a = __privateGet(this, _handlers))[event]) != null ? _b : _a[event] = /* @__PURE__ */ new Set()).add(handler);
67
+ return () => this.off(event, handler);
68
+ }
69
+ off(event, handler) {
70
+ var _a;
71
+ (_a = __privateGet(this, _handlers)[event]) == null ? void 0 : _a.delete(handler);
72
+ }
73
+ once(event, handler) {
74
+ const wrapped = (...args) => {
75
+ this.off(event, wrapped);
76
+ handler(...args);
77
+ };
78
+ return this.on(event, wrapped);
79
+ }
80
+ emit(event, ...args) {
81
+ const set = __privateGet(this, _handlers)[event];
82
+ if (!set)
83
+ return;
84
+ for (const handler of [...set]) {
85
+ handler(...args);
86
+ }
87
+ }
88
+ removeAll() {
89
+ __privateSet(this, _handlers, {});
90
+ }
91
+ };
92
+ _handlers = new WeakMap();
93
+
94
+ // node_modules/@decentnetwork/peer-webrtc/dist/signal.js
95
+ var SDP_TYPES = /* @__PURE__ */ new Set([
96
+ "offer",
97
+ "answer",
98
+ "candidate",
99
+ "remove-candidates",
100
+ "prAnswer",
101
+ "bye",
102
+ "action",
103
+ "event"
104
+ ]);
105
+ function encodeSignal(signal) {
106
+ const out = { type: signal.type };
107
+ if (signal.sdp !== void 0)
108
+ out.sdp = signal.sdp;
109
+ if (signal.candidates !== void 0) {
110
+ out.candidates = signal.candidates.map((c) => {
111
+ var _a;
112
+ const o = { sdp: c.sdp, sdpMLineIndex: c.sdpMLineIndex };
113
+ o.sdpMid = (_a = c.sdpMid) != null ? _a : null;
114
+ return o;
115
+ });
116
+ }
117
+ if (signal.reason !== void 0)
118
+ out.reason = signal.reason;
119
+ if (signal.options !== void 0)
120
+ out.options = signal.options;
121
+ if (signal.action !== void 0)
122
+ out.action = signal.action;
123
+ out.callId = signal.callId;
124
+ if (signal.event !== void 0)
125
+ out.event = signal.event;
126
+ return JSON.stringify(out);
127
+ }
128
+ function encodeSignalBytes(signal) {
129
+ return new TextEncoder().encode(encodeSignal(signal));
130
+ }
131
+ function decodeSignal(input) {
132
+ const text = (typeof input === "string" ? input : new TextDecoder().decode(input)).replace(/\0+$/u, "").trim();
133
+ const obj = JSON.parse(text);
134
+ if (typeof obj.type !== "string" || !SDP_TYPES.has(obj.type)) {
135
+ throw new Error(`RtcSignal: invalid or missing "type" (${String(obj.type)})`);
136
+ }
137
+ if (typeof obj.callId !== "string" || obj.callId.length === 0) {
138
+ throw new Error('RtcSignal: missing "callId"');
139
+ }
140
+ const signal = { type: obj.type, callId: obj.callId };
141
+ if (typeof obj.sdp === "string")
142
+ signal.sdp = obj.sdp;
143
+ if (Array.isArray(obj.candidates)) {
144
+ signal.candidates = obj.candidates.filter((c) => c && typeof c.sdp === "string").map((c) => ({
145
+ sdp: c.sdp,
146
+ sdpMLineIndex: typeof c.sdpMLineIndex === "number" ? c.sdpMLineIndex : 0,
147
+ sdpMid: typeof c.sdpMid === "string" ? c.sdpMid : null
148
+ }));
149
+ }
150
+ if (typeof obj.reason === "string")
151
+ signal.reason = obj.reason;
152
+ if (Array.isArray(obj.options)) {
153
+ signal.options = obj.options.filter((o) => o === "audio" || o === "video" || o === "data");
154
+ }
155
+ if (obj.action === "accept" || obj.action === "reject")
156
+ signal.action = obj.action;
157
+ if (typeof obj.event === "string")
158
+ signal.event = obj.event;
159
+ return signal;
160
+ }
161
+ function looksLikeSignal(input) {
162
+ const text = (typeof input === "string" ? input : new TextDecoder().decode(input)).replace(/\0+$/u, "").trimStart();
163
+ return text.startsWith("{") && text.includes('"callId"') && text.includes('"type"');
164
+ }
165
+
166
+ // node_modules/@decentnetwork/peer-webrtc/dist/call-engine.js
167
+ var DEFAULT_ICE_SERVERS = [
168
+ { urls: "stun:stun.l.google.com:19302" }
169
+ ];
170
+ var _opts, _iceServers, _sessions, _setOutgoingVideoTrack, setOutgoingVideoTrack_fn, _renegotiate, renegotiate_fn, _handleSignal, handleSignal_fn, _onOffer, onOffer_fn, _answerRenegotiation, answerRenegotiation_fn, _onAnswer, onAnswer_fn, _onCandidate, onCandidate_fn, _onBye, onBye_fn, _onAuxiliary, onAuxiliary_fn, _createSession, createSession_fn, _wirePeerConnection, wirePeerConnection_fn, _ensureRemoteStream, ensureRemoteStream_fn, _attachLocalMedia, attachLocalMedia_fn, _flushLocalCandidates, flushLocalCandidates_fn, _drainRemoteCandidates, drainRemoteCandidates_fn, _send, send_fn, _sendByeSafe, sendByeSafe_fn, _cleanup, cleanup_fn, _setState, setState_fn, _normId, normId_fn, _toInfo, _newCallId, newCallId_fn, _log, log_fn;
171
+ var CallEngine = class extends Emitter {
172
+ constructor(opts) {
173
+ var _a;
174
+ super();
175
+ /** Point the outgoing video sender at `track` (replaceTrack, no renegotiation
176
+ * needed if a sender exists), flip the transceiver to send, and refresh the
177
+ * local-preview stream. `track === null` removes the outgoing video. */
178
+ __privateAdd(this, _setOutgoingVideoTrack);
179
+ /** Create + send a fresh offer to renegotiate media (e.g. after adding a
180
+ * screen-share track). The peer applies it via #onOffer's renegotiation path. */
181
+ __privateAdd(this, _renegotiate);
182
+ // ---- internals -------------------------------------------------------
183
+ __privateAdd(this, _handleSignal);
184
+ __privateAdd(this, _onOffer);
185
+ /** Apply a mid-call re-offer (renegotiation) and send the answer. */
186
+ __privateAdd(this, _answerRenegotiation);
187
+ __privateAdd(this, _onAnswer);
188
+ __privateAdd(this, _onCandidate);
189
+ __privateAdd(this, _onBye);
190
+ __privateAdd(this, _onAuxiliary);
191
+ __privateAdd(this, _createSession);
192
+ __privateAdd(this, _wirePeerConnection);
193
+ __privateAdd(this, _ensureRemoteStream);
194
+ __privateAdd(this, _attachLocalMedia);
195
+ __privateAdd(this, _flushLocalCandidates);
196
+ __privateAdd(this, _drainRemoteCandidates);
197
+ __privateAdd(this, _send);
198
+ __privateAdd(this, _sendByeSafe);
199
+ __privateAdd(this, _cleanup);
200
+ __privateAdd(this, _setState);
201
+ /** Canonical session key. callId is a UUID; iOS re-serializes it UPPERCASE
202
+ * (it parses our lowercase UUID into a `UUID` and echoes `.uuidString`), so
203
+ * the answer/candidates come back cased differently than the offer. Key and
204
+ * look up sessions case-insensitively — exactly as the native SDK does
205
+ * (`callId.lowercased()`). Without this, outgoing calls to iOS never match
206
+ * the answer → candidates never flush → ICE stalls at "connecting". */
207
+ __privateAdd(this, _normId);
208
+ __privateAdd(this, _newCallId);
209
+ __privateAdd(this, _log);
210
+ __privateAdd(this, _opts, void 0);
211
+ __privateAdd(this, _iceServers, void 0);
212
+ __privateAdd(this, _sessions, /* @__PURE__ */ new Map());
213
+ __privateAdd(this, _toInfo, (session) => ({
214
+ callId: session.callId,
215
+ peerId: session.peerId,
216
+ direction: session.direction,
217
+ audio: session.audio,
218
+ video: session.video,
219
+ data: session.data,
220
+ state: session.state
221
+ }));
222
+ __privateSet(this, _opts, opts);
223
+ __privateSet(this, _iceServers, (_a = opts.iceServers) != null ? _a : DEFAULT_ICE_SERVERS);
224
+ opts.signaling.onSignal((peerId, signal) => {
225
+ try {
226
+ __privateMethod(this, _handleSignal, handleSignal_fn).call(this, peerId, signal);
227
+ } catch (err) {
228
+ __privateMethod(this, _log, log_fn).call(this, `handleSignal error: ${err.message}`);
229
+ }
230
+ });
231
+ }
232
+ /** Calls currently tracked by the engine. */
233
+ get calls() {
234
+ return [...__privateGet(this, _sessions).values()].map(__privateGet(this, _toInfo));
235
+ }
236
+ /** True while any call is active (useful for busy-signalling). */
237
+ get isBusy() {
238
+ for (const s of __privateGet(this, _sessions).values()) {
239
+ if (!s.closed && s.state !== "ended" && s.state !== "failed")
240
+ return true;
241
+ }
242
+ return false;
243
+ }
244
+ /**
245
+ * Place an outgoing call. Acquires local media, sends an offer, and returns
246
+ * the new callId. Emits "localStream" once media is up, "stateChanged" and
247
+ * "remoteStream"/"ended" as the call progresses.
248
+ */
249
+ async call(peerId, kinds = {}) {
250
+ var _a, _b, _c, _d, _e;
251
+ const audio = (_a = kinds.audio) != null ? _a : true;
252
+ const video = (_b = kinds.video) != null ? _b : false;
253
+ const data = (_c = kinds.data) != null ? _c : false;
254
+ const callId = __privateMethod(this, _newCallId, newCallId_fn).call(this);
255
+ const session = __privateMethod(this, _createSession, createSession_fn).call(this, callId, peerId, "outgoing", { audio, video, data });
256
+ await __privateMethod(this, _attachLocalMedia, attachLocalMedia_fn).call(this, session);
257
+ if (audio && !((_d = session.localStream) == null ? void 0 : _d.getAudioTracks().length)) {
258
+ try {
259
+ session.pc.addTransceiver("audio", { direction: "recvonly" });
260
+ } catch {
261
+ }
262
+ }
263
+ if (video && !((_e = session.localStream) == null ? void 0 : _e.getVideoTracks().length)) {
264
+ try {
265
+ session.pc.addTransceiver("video", { direction: "recvonly" });
266
+ } catch {
267
+ }
268
+ }
269
+ const offer = await session.pc.createOffer();
270
+ await session.pc.setLocalDescription(offer);
271
+ const options = [];
272
+ if (audio)
273
+ options.push("audio");
274
+ if (video)
275
+ options.push("video");
276
+ if (data)
277
+ options.push("data");
278
+ await __privateMethod(this, _send, send_fn).call(this, peerId, {
279
+ type: "offer",
280
+ sdp: offer.sdp,
281
+ options,
282
+ callId,
283
+ event: void 0
284
+ });
285
+ __privateMethod(this, _setState, setState_fn).call(this, session, "ringing");
286
+ __privateMethod(this, _log, log_fn).call(this, `call \u2192 ${peerId} callId=${callId} audio=${audio} video=${video}`);
287
+ return callId;
288
+ }
289
+ /**
290
+ * Accept an incoming call (one that surfaced via "incomingCall"). Acquires
291
+ * local media, applies the stored offer, and sends the answer.
292
+ */
293
+ async accept(callId) {
294
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, callId));
295
+ if (!session || session.direction !== "incoming" || !session.pendingOffer) {
296
+ throw new Error(`accept: no pending incoming call ${callId}`);
297
+ }
298
+ await __privateMethod(this, _attachLocalMedia, attachLocalMedia_fn).call(this, session);
299
+ await session.pc.setRemoteDescription({ type: "offer", sdp: session.pendingOffer });
300
+ session.hasReceivedSdp = true;
301
+ session.pendingOffer = void 0;
302
+ await __privateMethod(this, _drainRemoteCandidates, drainRemoteCandidates_fn).call(this, session);
303
+ const answer = await session.pc.createAnswer();
304
+ await session.pc.setLocalDescription(answer);
305
+ await __privateMethod(this, _send, send_fn).call(this, session.peerId, { type: "answer", sdp: answer.sdp, callId });
306
+ __privateMethod(this, _setState, setState_fn).call(this, session, "connecting");
307
+ await __privateMethod(this, _flushLocalCandidates, flushLocalCandidates_fn).call(this, session);
308
+ __privateMethod(this, _log, log_fn).call(this, `accept callId=${callId}`);
309
+ }
310
+ /** Reject an incoming call (sends bye/declined). */
311
+ async reject(callId) {
312
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, callId));
313
+ if (!session)
314
+ return;
315
+ await __privateMethod(this, _sendByeSafe, sendByeSafe_fn).call(this, session, "declined");
316
+ __privateMethod(this, _setState, setState_fn).call(this, session, "declined");
317
+ __privateMethod(this, _cleanup, cleanup_fn).call(this, session, "declined");
318
+ }
319
+ /** Hang up an active call (sends bye/normal). */
320
+ async hangup(callId, reason = "normal") {
321
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, callId));
322
+ if (!session)
323
+ return;
324
+ await __privateMethod(this, _sendByeSafe, sendByeSafe_fn).call(this, session, reason);
325
+ __privateMethod(this, _cleanup, cleanup_fn).call(this, session, reason);
326
+ }
327
+ /** Enable/disable a local track kind on an active call (mute / camera off). */
328
+ setLocalTrackEnabled(callId, kind, enabled) {
329
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, callId));
330
+ if (!(session == null ? void 0 : session.localStream))
331
+ return;
332
+ for (const track of session.localStream.getTracks()) {
333
+ if (track.kind === kind)
334
+ track.enabled = enabled;
335
+ }
336
+ }
337
+ /** Start sharing the screen on an active call. Captures the display, sends it
338
+ * as the outgoing video track (replacing the camera if any), and renegotiates
339
+ * so the peer receives it. Works even with no camera. Ending the OS "stop
340
+ * sharing" prompt reverts automatically. */
341
+ async shareScreen(callId) {
342
+ var _a, _b, _c;
343
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, callId));
344
+ if (!session)
345
+ throw new Error(`shareScreen: no call ${callId}`);
346
+ if (!__privateGet(this, _opts).getDisplayMedia)
347
+ throw new Error("screen share not supported here");
348
+ const screen = await __privateGet(this, _opts).getDisplayMedia({ video: true, audio: false });
349
+ const track = screen.getVideoTracks()[0];
350
+ if (!track)
351
+ return;
352
+ if (!session.screenStream) {
353
+ session.hadCamera = !!((_a = session.localStream) == null ? void 0 : _a.getVideoTracks().length);
354
+ for (const t of (_c = (_b = session.localStream) == null ? void 0 : _b.getVideoTracks()) != null ? _c : [])
355
+ t.stop();
356
+ }
357
+ session.screenStream = screen;
358
+ await __privateMethod(this, _setOutgoingVideoTrack, setOutgoingVideoTrack_fn).call(this, session, track, screen);
359
+ track.addEventListener("ended", () => {
360
+ void this.stopScreenShare(callId);
361
+ });
362
+ await __privateMethod(this, _renegotiate, renegotiate_fn).call(this, session);
363
+ __privateMethod(this, _log, log_fn).call(this, `shareScreen started for ${callId}`);
364
+ }
365
+ /** Stop screen sharing; re-acquire the camera if there was one. */
366
+ async stopScreenShare(callId) {
367
+ var _a;
368
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, callId));
369
+ if (!(session == null ? void 0 : session.screenStream))
370
+ return;
371
+ for (const t of session.screenStream.getTracks())
372
+ t.stop();
373
+ session.screenStream = void 0;
374
+ let cam;
375
+ if (session.hadCamera && __privateGet(this, _opts).getLocalMedia) {
376
+ cam = await __privateGet(this, _opts).getLocalMedia({ audio: false, video: true }).catch(() => void 0);
377
+ }
378
+ session.hadCamera = false;
379
+ await __privateMethod(this, _setOutgoingVideoTrack, setOutgoingVideoTrack_fn).call(this, session, (_a = cam == null ? void 0 : cam.getVideoTracks()[0]) != null ? _a : null, cam);
380
+ await __privateMethod(this, _renegotiate, renegotiate_fn).call(this, session);
381
+ __privateMethod(this, _log, log_fn).call(this, `shareScreen stopped for ${callId}`);
382
+ }
383
+ /** True when the call is currently sharing the screen. */
384
+ isSharingScreen(callId) {
385
+ var _a;
386
+ return !!((_a = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, callId))) == null ? void 0 : _a.screenStream);
387
+ }
388
+ /** Tear down every call (e.g. on app shutdown). */
389
+ dispose() {
390
+ for (const session of [...__privateGet(this, _sessions).values()]) {
391
+ __privateMethod(this, _cleanup, cleanup_fn).call(this, session, "close");
392
+ }
393
+ this.removeAll();
394
+ }
395
+ };
396
+ _opts = new WeakMap();
397
+ _iceServers = new WeakMap();
398
+ _sessions = new WeakMap();
399
+ _setOutgoingVideoTrack = new WeakSet();
400
+ setOutgoingVideoTrack_fn = async function(session, track, stream) {
401
+ var _a;
402
+ const transceivers = session.pc.getTransceivers();
403
+ const tr = (_a = transceivers.find((t) => {
404
+ var _a2;
405
+ return ((_a2 = t.sender.track) == null ? void 0 : _a2.kind) === "video";
406
+ })) != null ? _a : transceivers.find((t) => {
407
+ var _a2;
408
+ return ((_a2 = t.receiver.track) == null ? void 0 : _a2.kind) === "video";
409
+ });
410
+ if (tr) {
411
+ await tr.sender.replaceTrack(track);
412
+ if (track) {
413
+ if (tr.direction === "recvonly")
414
+ tr.direction = "sendrecv";
415
+ else if (tr.direction === "inactive")
416
+ tr.direction = "sendonly";
417
+ }
418
+ } else if (track && stream) {
419
+ session.pc.addTrack(track, stream);
420
+ }
421
+ session.localStream = stream;
422
+ this.emit("localStream", session.callId, stream != null ? stream : new MediaStream());
423
+ };
424
+ _renegotiate = new WeakSet();
425
+ renegotiate_fn = async function(session) {
426
+ try {
427
+ const offer = await session.pc.createOffer();
428
+ await session.pc.setLocalDescription(offer);
429
+ const options = [];
430
+ if (session.audio)
431
+ options.push("audio");
432
+ if (session.video || session.screenStream)
433
+ options.push("video");
434
+ await __privateMethod(this, _send, send_fn).call(this, session.peerId, { type: "offer", sdp: offer.sdp, options, callId: session.callId });
435
+ } catch (err) {
436
+ __privateMethod(this, _log, log_fn).call(this, `renegotiate failed: ${err.message}`);
437
+ }
438
+ };
439
+ _handleSignal = new WeakSet();
440
+ handleSignal_fn = function(peerId, signal) {
441
+ switch (signal.type) {
442
+ case "offer":
443
+ __privateMethod(this, _onOffer, onOffer_fn).call(this, peerId, signal);
444
+ return;
445
+ case "answer":
446
+ __privateMethod(this, _onAnswer, onAnswer_fn).call(this, peerId, signal);
447
+ return;
448
+ case "candidate":
449
+ __privateMethod(this, _onCandidate, onCandidate_fn).call(this, peerId, signal);
450
+ return;
451
+ case "remove-candidates":
452
+ __privateMethod(this, _log, log_fn).call(this, `remove-candidates from ${peerId} (ignored)`);
453
+ return;
454
+ case "bye":
455
+ __privateMethod(this, _onBye, onBye_fn).call(this, peerId, signal);
456
+ return;
457
+ case "action":
458
+ case "event":
459
+ case "prAnswer":
460
+ __privateMethod(this, _onAuxiliary, onAuxiliary_fn).call(this, peerId, signal);
461
+ return;
462
+ }
463
+ };
464
+ _onOffer = new WeakSet();
465
+ onOffer_fn = function(peerId, signal) {
466
+ if (!signal.sdp)
467
+ return;
468
+ const existing = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, signal.callId));
469
+ if (existing) {
470
+ if (existing.hasReceivedSdp)
471
+ void __privateMethod(this, _answerRenegotiation, answerRenegotiation_fn).call(this, existing, signal.sdp);
472
+ else
473
+ existing.pendingOffer = signal.sdp;
474
+ return;
475
+ }
476
+ const audio = signal.options ? signal.options.includes("audio") : true;
477
+ const video = signal.options ? signal.options.includes("video") : false;
478
+ const data = signal.options ? signal.options.includes("data") : false;
479
+ const session = __privateMethod(this, _createSession, createSession_fn).call(this, signal.callId, peerId, "incoming", { audio, video, data });
480
+ session.pendingOffer = signal.sdp;
481
+ this.emit("incomingCall", __privateGet(this, _toInfo).call(this, session));
482
+ __privateMethod(this, _log, log_fn).call(this, `incoming call from ${peerId} callId=${signal.callId} audio=${audio} video=${video}`);
483
+ };
484
+ _answerRenegotiation = new WeakSet();
485
+ answerRenegotiation_fn = async function(session, sdp) {
486
+ try {
487
+ await session.pc.setRemoteDescription({ type: "offer", sdp });
488
+ const answer = await session.pc.createAnswer();
489
+ await session.pc.setLocalDescription(answer);
490
+ await __privateMethod(this, _send, send_fn).call(this, session.peerId, { type: "answer", sdp: answer.sdp, callId: session.callId });
491
+ } catch (err) {
492
+ __privateMethod(this, _log, log_fn).call(this, `renegotiation answer failed: ${err.message}`);
493
+ }
494
+ };
495
+ _onAnswer = new WeakSet();
496
+ onAnswer_fn = function(peerId, signal) {
497
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, signal.callId));
498
+ if (!session || !signal.sdp)
499
+ return;
500
+ session.peerId = peerId;
501
+ void (async () => {
502
+ try {
503
+ await session.pc.setRemoteDescription({ type: "answer", sdp: signal.sdp });
504
+ session.hasReceivedSdp = true;
505
+ if (session.state !== "connected")
506
+ __privateMethod(this, _setState, setState_fn).call(this, session, "connecting");
507
+ await __privateMethod(this, _drainRemoteCandidates, drainRemoteCandidates_fn).call(this, session);
508
+ await __privateMethod(this, _flushLocalCandidates, flushLocalCandidates_fn).call(this, session);
509
+ } catch (err) {
510
+ __privateMethod(this, _log, log_fn).call(this, `setRemoteDescription(answer) failed: ${err.message}`);
511
+ }
512
+ })();
513
+ };
514
+ _onCandidate = new WeakSet();
515
+ onCandidate_fn = function(peerId, signal) {
516
+ var _a;
517
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, signal.callId));
518
+ if (!session || !signal.candidates)
519
+ return;
520
+ for (const c of signal.candidates) {
521
+ const init = {
522
+ candidate: c.sdp,
523
+ sdpMLineIndex: c.sdpMLineIndex,
524
+ sdpMid: (_a = c.sdpMid) != null ? _a : void 0
525
+ };
526
+ if (session.pc.remoteDescription) {
527
+ session.pc.addIceCandidate(init).catch((err) => __privateMethod(this, _log, log_fn).call(this, `addIceCandidate failed: ${err.message}`));
528
+ } else {
529
+ session.remoteCandidateQueue.push(init);
530
+ }
531
+ }
532
+ };
533
+ _onBye = new WeakSet();
534
+ onBye_fn = function(peerId, signal) {
535
+ var _a;
536
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, signal.callId));
537
+ if (!session)
538
+ return;
539
+ const reason = (_a = signal.reason) != null ? _a : "normal";
540
+ const state = reason === "busy" ? "busy" : reason === "declined" ? "declined" : "ended";
541
+ __privateMethod(this, _setState, setState_fn).call(this, session, state);
542
+ __privateMethod(this, _cleanup, cleanup_fn).call(this, session, reason);
543
+ __privateMethod(this, _log, log_fn).call(this, `bye from ${peerId} callId=${signal.callId} reason=${reason}`);
544
+ };
545
+ _onAuxiliary = new WeakSet();
546
+ onAuxiliary_fn = function(peerId, signal) {
547
+ const session = __privateGet(this, _sessions).get(__privateMethod(this, _normId, normId_fn).call(this, signal.callId));
548
+ if (!session)
549
+ return;
550
+ if (signal.type === "event") {
551
+ if (signal.event === "ringing")
552
+ __privateMethod(this, _setState, setState_fn).call(this, session, "remoteRinging");
553
+ else if (signal.event === "online")
554
+ __privateMethod(this, _setState, setState_fn).call(this, session, "remoteOnline");
555
+ } else if (signal.type === "action") {
556
+ if (signal.action === "reject") {
557
+ __privateMethod(this, _setState, setState_fn).call(this, session, "declined");
558
+ __privateMethod(this, _cleanup, cleanup_fn).call(this, session, "declined");
559
+ }
560
+ }
561
+ };
562
+ _createSession = new WeakSet();
563
+ createSession_fn = function(callId, peerId, direction, kinds) {
564
+ const pc = __privateGet(this, _opts).createPeerConnection({ iceServers: __privateGet(this, _iceServers) });
565
+ const session = {
566
+ callId,
567
+ peerId,
568
+ direction,
569
+ pc,
570
+ audio: kinds.audio,
571
+ video: kinds.video,
572
+ data: kinds.data,
573
+ state: "connecting",
574
+ hasReceivedSdp: false,
575
+ localCandidateQueue: [],
576
+ remoteCandidateQueue: [],
577
+ closed: false
578
+ };
579
+ __privateGet(this, _sessions).set(__privateMethod(this, _normId, normId_fn).call(this, callId), session);
580
+ __privateMethod(this, _wirePeerConnection, wirePeerConnection_fn).call(this, session);
581
+ return session;
582
+ };
583
+ _wirePeerConnection = new WeakSet();
584
+ wirePeerConnection_fn = function(session) {
585
+ const pc = session.pc;
586
+ pc.onicecandidate = (ev) => {
587
+ var _a, _b;
588
+ if (!ev.candidate || !ev.candidate.candidate)
589
+ return;
590
+ const sig = {
591
+ sdp: ev.candidate.candidate,
592
+ sdpMLineIndex: (_a = ev.candidate.sdpMLineIndex) != null ? _a : 0,
593
+ sdpMid: (_b = ev.candidate.sdpMid) != null ? _b : null
594
+ };
595
+ if (session.hasReceivedSdp) {
596
+ void __privateMethod(this, _send, send_fn).call(this, session.peerId, { type: "candidate", candidates: [sig], callId: session.callId });
597
+ } else {
598
+ session.localCandidateQueue.push(sig);
599
+ }
600
+ };
601
+ pc.ontrack = (ev) => {
602
+ __privateMethod(this, _ensureRemoteStream, ensureRemoteStream_fn).call(this, session, ev.track);
603
+ const snapshot = new MediaStream(session.remoteStream.getTracks());
604
+ this.emit("remoteStream", session.callId, snapshot);
605
+ ev.track.addEventListener("unmute", () => {
606
+ if (!session.remoteStream)
607
+ return;
608
+ this.emit("remoteStream", session.callId, new MediaStream(session.remoteStream.getTracks()));
609
+ });
610
+ };
611
+ pc.oniceconnectionstatechange = () => {
612
+ switch (pc.iceConnectionState) {
613
+ case "connected":
614
+ case "completed":
615
+ __privateMethod(this, _setState, setState_fn).call(this, session, "connected");
616
+ break;
617
+ case "disconnected":
618
+ __privateMethod(this, _setState, setState_fn).call(this, session, "disconnected");
619
+ break;
620
+ case "failed":
621
+ __privateMethod(this, _setState, setState_fn).call(this, session, "failed");
622
+ __privateMethod(this, _cleanup, cleanup_fn).call(this, session, "close", "failed");
623
+ break;
624
+ case "closed":
625
+ if (!session.closed)
626
+ __privateMethod(this, _cleanup, cleanup_fn).call(this, session, "close");
627
+ break;
628
+ default:
629
+ break;
630
+ }
631
+ };
632
+ };
633
+ _ensureRemoteStream = new WeakSet();
634
+ ensureRemoteStream_fn = function(session, track) {
635
+ if (!session.remoteStream)
636
+ session.remoteStream = new MediaStream();
637
+ if (!session.remoteStream.getTracks().includes(track))
638
+ session.remoteStream.addTrack(track);
639
+ return session.remoteStream;
640
+ };
641
+ _attachLocalMedia = new WeakSet();
642
+ attachLocalMedia_fn = async function(session) {
643
+ if (session.localStream)
644
+ return;
645
+ if (!__privateGet(this, _opts).getLocalMedia || !session.audio && !session.video)
646
+ return;
647
+ let stream;
648
+ try {
649
+ stream = await __privateGet(this, _opts).getLocalMedia({ audio: session.audio, video: session.video });
650
+ } catch (err) {
651
+ __privateMethod(this, _log, log_fn).call(this, `getLocalMedia(audio:${session.audio},video:${session.video}) failed: ${err.message}`);
652
+ if (session.video && session.audio) {
653
+ try {
654
+ stream = await __privateGet(this, _opts).getLocalMedia({ audio: true, video: false });
655
+ __privateMethod(this, _log, log_fn).call(this, `local camera unavailable \u2014 sending audio only, still receiving video, call ${session.callId}`);
656
+ } catch (err2) {
657
+ __privateMethod(this, _log, log_fn).call(this, `audio-only fallback failed too: ${err2.message}`);
658
+ }
659
+ }
660
+ }
661
+ if (!stream) {
662
+ __privateMethod(this, _log, log_fn).call(this, `no local media for ${session.callId}; connecting receive-only`);
663
+ return;
664
+ }
665
+ session.localStream = stream;
666
+ for (const track of stream.getTracks()) {
667
+ session.pc.addTrack(track, stream);
668
+ }
669
+ this.emit("localStream", session.callId, stream);
670
+ };
671
+ _flushLocalCandidates = new WeakSet();
672
+ flushLocalCandidates_fn = async function(session) {
673
+ if (!session.hasReceivedSdp || session.localCandidateQueue.length === 0)
674
+ return;
675
+ const queued = session.localCandidateQueue.splice(0);
676
+ for (const sig of queued) {
677
+ await __privateMethod(this, _send, send_fn).call(this, session.peerId, { type: "candidate", candidates: [sig], callId: session.callId });
678
+ }
679
+ };
680
+ _drainRemoteCandidates = new WeakSet();
681
+ drainRemoteCandidates_fn = async function(session) {
682
+ if (!session.pc.remoteDescription)
683
+ return;
684
+ const queued = session.remoteCandidateQueue.splice(0);
685
+ for (const init of queued) {
686
+ await session.pc.addIceCandidate(init).catch((err) => __privateMethod(this, _log, log_fn).call(this, `addIceCandidate (drain) failed: ${err.message}`));
687
+ }
688
+ };
689
+ _send = new WeakSet();
690
+ send_fn = async function(peerId, signal) {
691
+ try {
692
+ await __privateGet(this, _opts).signaling.send(peerId, signal);
693
+ } catch (err) {
694
+ __privateMethod(this, _log, log_fn).call(this, `signal send failed (${signal.type} \u2192 ${peerId}): ${err.message}`);
695
+ throw err;
696
+ }
697
+ };
698
+ _sendByeSafe = new WeakSet();
699
+ sendByeSafe_fn = async function(session, reason) {
700
+ try {
701
+ await __privateGet(this, _opts).signaling.send(session.peerId, { type: "bye", reason, callId: session.callId });
702
+ } catch (err) {
703
+ __privateMethod(this, _log, log_fn).call(this, `bye send failed: ${err.message}`);
704
+ }
705
+ };
706
+ _cleanup = new WeakSet();
707
+ cleanup_fn = function(session, reason, endedReason) {
708
+ var _a, _b;
709
+ if (session.closed)
710
+ return;
711
+ session.closed = true;
712
+ try {
713
+ session.pc.onicecandidate = null;
714
+ session.pc.ontrack = null;
715
+ session.pc.oniceconnectionstatechange = null;
716
+ session.pc.close();
717
+ } catch {
718
+ }
719
+ for (const track of (_b = (_a = session.localStream) == null ? void 0 : _a.getTracks()) != null ? _b : []) {
720
+ try {
721
+ track.stop();
722
+ } catch {
723
+ }
724
+ }
725
+ __privateGet(this, _sessions).delete(__privateMethod(this, _normId, normId_fn).call(this, session.callId));
726
+ if (session.state !== "ended" && session.state !== "failed") {
727
+ session.state = endedReason === "failed" ? "failed" : "ended";
728
+ }
729
+ this.emit("ended", session.callId, endedReason != null ? endedReason : reason);
730
+ };
731
+ _setState = new WeakSet();
732
+ setState_fn = function(session, state) {
733
+ if (session.state === state)
734
+ return;
735
+ session.state = state;
736
+ this.emit("stateChanged", __privateGet(this, _toInfo).call(this, session), state);
737
+ };
738
+ _normId = new WeakSet();
739
+ normId_fn = function(callId) {
740
+ return callId.toLowerCase();
741
+ };
742
+ _toInfo = new WeakMap();
743
+ _newCallId = new WeakSet();
744
+ newCallId_fn = function() {
745
+ if (__privateGet(this, _opts).generateCallId)
746
+ return __privateGet(this, _opts).generateCallId();
747
+ const c = globalThis.crypto;
748
+ if (c && typeof c.randomUUID === "function")
749
+ return c.randomUUID();
750
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (ch) => {
751
+ const r = Math.floor(Math.random() * 16);
752
+ const v = ch === "x" ? r : r & 3 | 8;
753
+ return v.toString(16);
754
+ });
755
+ };
756
+ _log = new WeakSet();
757
+ log_fn = function(msg) {
758
+ var _a, _b;
759
+ (_b = (_a = __privateGet(this, _opts)).logger) == null ? void 0 : _b.call(_a, `[peer-webrtc] ${msg}`);
760
+ };
761
+
762
+ // node_modules/@decentnetwork/peer-webrtc/dist/signaling/broadcast.js
763
+ var _selfId, _channel, _handler;
764
+ var BroadcastChannelSignaling = class {
765
+ constructor(selfId, channelName = "peer-webrtc-demo") {
766
+ __privateAdd(this, _selfId, void 0);
767
+ __privateAdd(this, _channel, void 0);
768
+ __privateAdd(this, _handler, void 0);
769
+ __privateSet(this, _selfId, selfId);
770
+ __privateSet(this, _channel, new BroadcastChannel(channelName));
771
+ __privateGet(this, _channel).onmessage = (ev) => {
772
+ var _a;
773
+ const msg = ev.data;
774
+ if (!msg || msg.to !== __privateGet(this, _selfId) || msg.from === __privateGet(this, _selfId))
775
+ return;
776
+ (_a = __privateGet(this, _handler)) == null ? void 0 : _a.call(this, msg.from, msg.signal);
777
+ };
778
+ }
779
+ send(peerId, signal) {
780
+ const env = { from: __privateGet(this, _selfId), to: peerId, signal };
781
+ __privateGet(this, _channel).postMessage(env);
782
+ }
783
+ onSignal(handler) {
784
+ __privateSet(this, _handler, handler);
785
+ }
786
+ close() {
787
+ __privateGet(this, _channel).close();
788
+ }
789
+ };
790
+ _selfId = new WeakMap();
791
+ _channel = new WeakMap();
792
+ _handler = new WeakMap();
793
+
794
+ // node_modules/@decentnetwork/peer-webrtc/dist/guard.js
795
+ function decodeSignalBytesGuard(input) {
796
+ try {
797
+ return decodeSignal(input);
798
+ } catch {
799
+ return void 0;
800
+ }
801
+ }
802
+
803
+ // node_modules/@decentnetwork/peer-webrtc/dist/signaling/carrier.js
804
+ var DEFAULT_EXT = "carrier";
805
+ var _peer, _ext;
806
+ var CarrierSignaling = class {
807
+ constructor(peer, opts = {}) {
808
+ __privateAdd(this, _peer, void 0);
809
+ __privateAdd(this, _ext, void 0);
810
+ var _a;
811
+ __privateSet(this, _peer, peer);
812
+ __privateSet(this, _ext, (_a = opts.ext) != null ? _a : DEFAULT_EXT);
813
+ }
814
+ async send(peerId, signal) {
815
+ await __privateGet(this, _peer).sendInvite(peerId, encodeSignalBytes(signal), { ext: __privateGet(this, _ext) });
816
+ }
817
+ onSignal(handler) {
818
+ __privateGet(this, _peer).onInvite((evt) => {
819
+ if (evt.ext !== void 0 && evt.ext !== __privateGet(this, _ext))
820
+ return;
821
+ if (!looksLikeSignal(evt.data))
822
+ return;
823
+ const signal = decodeSignalBytesGuard(evt.data);
824
+ if (signal)
825
+ handler(evt.pubkey, signal);
826
+ });
827
+ }
828
+ };
829
+ _peer = new WeakMap();
830
+ _ext = new WeakMap();
831
+
832
+ // node_modules/@decentnetwork/peer-webrtc/dist/signaling/socketio.js
833
+ var _socket, _userId, _handler2, _rooms, _pending, _lastOffer, _wired, _roomKey, roomKey_fn, _ensureRoom, ensureRoom_fn, _emitMessage, emitMessage_fn, _wire, wire_fn;
834
+ var SocketIoSignaling = class {
835
+ constructor(socket, opts) {
836
+ /** The socket.io ROOM key. The native Beagle apps join the room with the
837
+ * call's `UUID.uuidString`, which Swift renders UPPERCASE — so a lowercase
838
+ * `crypto.randomUUID()` from JS would land us in a DIFFERENT room and we'd
839
+ * never receive the peer's answer/candidates. Canonicalize to UPPERCASE to
840
+ * share the native peer's room. (The RtcSignal payload callId stays as-is;
841
+ * the CallEngine matches it case-insensitively.) */
842
+ __privateAdd(this, _roomKey);
843
+ __privateAdd(this, _ensureRoom);
844
+ __privateAdd(this, _emitMessage);
845
+ __privateAdd(this, _wire);
846
+ __privateAdd(this, _socket, void 0);
847
+ __privateAdd(this, _userId, void 0);
848
+ __privateAdd(this, _handler2, void 0);
849
+ /** Rooms we've asked to join (callId -> confirmed self-membership). */
850
+ __privateAdd(this, _rooms, /* @__PURE__ */ new Map());
851
+ /** Signals queued per room until the server confirms our membership. */
852
+ __privateAdd(this, _pending, /* @__PURE__ */ new Map());
853
+ /** Last offer per callId, RE-SENT when the peer joins the room — the callee
854
+ * (woken by a push) joins seconds after we sent the offer, and socket.io does
855
+ * NOT replay, so without this the peer never sees the offer and never
856
+ * answers (offline call stuck at "connecting"). */
857
+ __privateAdd(this, _lastOffer, /* @__PURE__ */ new Map());
858
+ /** The remote peer id per room, learned from inbound messages so a queued
859
+ * peer-greeting can be addressed. */
860
+ __privateAdd(this, _wired, false);
861
+ __privateSet(this, _socket, socket);
862
+ __privateSet(this, _userId, opts.userId);
863
+ }
864
+ onSignal(handler) {
865
+ __privateSet(this, _handler2, handler);
866
+ __privateMethod(this, _wire, wire_fn).call(this);
867
+ }
868
+ /**
869
+ * Deliver a signal to `peerId`. Joins the call's room (keyed by
870
+ * `signal.callId`) on first use and queues until the server confirms
871
+ * membership, then emits — mirroring the iOS provider, which queues until
872
+ * `connectToRoom`.
873
+ */
874
+ send(peerId, signal) {
875
+ var _a;
876
+ __privateMethod(this, _wire, wire_fn).call(this);
877
+ const callId = signal.callId;
878
+ if (!callId) {
879
+ __privateMethod(this, _emitMessage, emitMessage_fn).call(this, signal);
880
+ return;
881
+ }
882
+ if (signal.type === "offer")
883
+ __privateGet(this, _lastOffer).set(callId, signal);
884
+ const room = __privateMethod(this, _ensureRoom, ensureRoom_fn).call(this, callId);
885
+ if (room.joined) {
886
+ __privateMethod(this, _emitMessage, emitMessage_fn).call(this, signal);
887
+ } else {
888
+ const q = (_a = __privateGet(this, _pending).get(callId)) != null ? _a : [];
889
+ q.push(signal);
890
+ __privateGet(this, _pending).set(callId, q);
891
+ }
892
+ }
893
+ /**
894
+ * Explicitly join the room for an INCOMING call (e.g. after a push
895
+ * notification delivered the `callId`), so inbound signals for it are
896
+ * received. Safe to call more than once.
897
+ */
898
+ joinCall(callId) {
899
+ __privateMethod(this, _wire, wire_fn).call(this);
900
+ __privateMethod(this, _ensureRoom, ensureRoom_fn).call(this, callId);
901
+ }
902
+ /** Leave a call's room (best-effort) and forget its queued state. */
903
+ leaveCall(callId) {
904
+ __privateGet(this, _rooms).delete(callId);
905
+ __privateGet(this, _pending).delete(callId);
906
+ __privateGet(this, _lastOffer).delete(callId);
907
+ __privateGet(this, _socket).emit("leave-channel", { channel: __privateMethod(this, _roomKey, roomKey_fn).call(this, callId), sender: __privateGet(this, _userId) });
908
+ }
909
+ };
910
+ _socket = new WeakMap();
911
+ _userId = new WeakMap();
912
+ _handler2 = new WeakMap();
913
+ _rooms = new WeakMap();
914
+ _pending = new WeakMap();
915
+ _lastOffer = new WeakMap();
916
+ _wired = new WeakMap();
917
+ _roomKey = new WeakSet();
918
+ roomKey_fn = function(callId) {
919
+ return callId.toUpperCase();
920
+ };
921
+ _ensureRoom = new WeakSet();
922
+ ensureRoom_fn = function(callId) {
923
+ let room = __privateGet(this, _rooms).get(callId);
924
+ if (!room) {
925
+ room = { joined: false };
926
+ __privateGet(this, _rooms).set(callId, room);
927
+ __privateGet(this, _socket).emit("new-channel", { channel: __privateMethod(this, _roomKey, roomKey_fn).call(this, callId), sender: __privateGet(this, _userId) });
928
+ }
929
+ return room;
930
+ };
931
+ _emitMessage = new WeakSet();
932
+ emitMessage_fn = function(signal) {
933
+ __privateGet(this, _socket).emit("message", { data: encodeSignal(signal), sender: __privateGet(this, _userId) });
934
+ };
935
+ _wire = new WeakSet();
936
+ wire_fn = function() {
937
+ if (__privateGet(this, _wired))
938
+ return;
939
+ __privateSet(this, _wired, true);
940
+ __privateGet(this, _socket).on("message", (...args) => {
941
+ var _a;
942
+ const payload = firstObject(args);
943
+ if (!(payload == null ? void 0 : payload.data) || !payload.sender)
944
+ return;
945
+ if (payload.sender === __privateGet(this, _userId))
946
+ return;
947
+ const signal = decodeSignalBytesGuard(payload.data);
948
+ if (signal)
949
+ (_a = __privateGet(this, _handler2)) == null ? void 0 : _a.call(this, payload.sender, signal);
950
+ });
951
+ __privateGet(this, _socket).on("connectToRoom", (...args) => {
952
+ const payload = firstObject(args);
953
+ const sender = payload == null ? void 0 : payload.sender;
954
+ if (!sender)
955
+ return;
956
+ if (sender === __privateGet(this, _userId)) {
957
+ for (const [callId, room] of __privateGet(this, _rooms)) {
958
+ room.joined = true;
959
+ const q = __privateGet(this, _pending).get(callId);
960
+ if (q && q.length) {
961
+ for (const sig of q)
962
+ __privateMethod(this, _emitMessage, emitMessage_fn).call(this, sig);
963
+ __privateGet(this, _pending).delete(callId);
964
+ }
965
+ }
966
+ } else {
967
+ for (const callId of __privateGet(this, _rooms).keys()) {
968
+ __privateMethod(this, _emitMessage, emitMessage_fn).call(this, { type: "event", callId, event: "online" });
969
+ const offer = __privateGet(this, _lastOffer).get(callId);
970
+ if (offer)
971
+ __privateMethod(this, _emitMessage, emitMessage_fn).call(this, offer);
972
+ }
973
+ }
974
+ });
975
+ __privateGet(this, _socket).on("disconnectToRoom", (...args) => {
976
+ const payload = firstObject(args);
977
+ const sender = payload == null ? void 0 : payload.sender;
978
+ if (sender && sender === __privateGet(this, _userId)) {
979
+ for (const room of __privateGet(this, _rooms).values())
980
+ room.joined = false;
981
+ }
982
+ });
983
+ };
984
+ function firstObject(args) {
985
+ const first = args[0];
986
+ return first && typeof first === "object" ? first : void 0;
987
+ }
988
+
989
+ // node_modules/@decentnetwork/peer-webrtc/dist/signaling/push.js
990
+ var DEFAULT_ENDPOINTS = [
991
+ "https://pushapi.beagle.chat/push-api/push-message",
992
+ "https://www.callpass.cn/push-api/push-message",
993
+ "https://tokyo.fi.chat:3004/push-api/push-message"
994
+ ];
995
+ var _appKey, _appName, _endpoints, _fetch;
996
+ var BeaglePushClient = class {
997
+ constructor(opts) {
998
+ __privateAdd(this, _appKey, void 0);
999
+ __privateAdd(this, _appName, void 0);
1000
+ __privateAdd(this, _endpoints, void 0);
1001
+ __privateAdd(this, _fetch, void 0);
1002
+ var _a, _b;
1003
+ __privateSet(this, _appKey, opts.appKey);
1004
+ __privateSet(this, _appName, opts.appName);
1005
+ __privateSet(this, _endpoints, ((_a = opts.endpoints) == null ? void 0 : _a.length) ? opts.endpoints : DEFAULT_ENDPOINTS);
1006
+ const f = (_b = opts.fetch) != null ? _b : globalThis.fetch;
1007
+ if (!f)
1008
+ throw new Error("BeaglePushClient: no fetch available \u2014 pass opts.fetch");
1009
+ __privateSet(this, _fetch, f);
1010
+ }
1011
+ /**
1012
+ * Ring an offline peer. `calleeUserId` is the destination (their Carrier user
1013
+ * id); the payload describes the call. Tries each endpoint until one accepts.
1014
+ * Resolves `true` on success, `false` if every endpoint failed.
1015
+ */
1016
+ async sendCallPush(calleeUserId, payload) {
1017
+ var _a;
1018
+ const params = new URLSearchParams({
1019
+ account: calleeUserId,
1020
+ payload: JSON.stringify(payload),
1021
+ appKey: __privateGet(this, _appKey),
1022
+ appName: __privateGet(this, _appName)
1023
+ }).toString();
1024
+ for (const endpoint of __privateGet(this, _endpoints)) {
1025
+ try {
1026
+ const url = endpoint + (endpoint.includes("?") ? "&" : "?") + params;
1027
+ const res = await __privateGet(this, _fetch).call(this, url, { method: "POST" });
1028
+ if (!res.ok)
1029
+ continue;
1030
+ const json = await res.json().catch(() => ({}));
1031
+ const code = json.code;
1032
+ const ok = code === void 0 || code === 0 || code === "0" || ((_a = json.data) == null ? void 0 : _a.success) === true;
1033
+ if (ok)
1034
+ return true;
1035
+ } catch {
1036
+ }
1037
+ }
1038
+ return false;
1039
+ }
1040
+ /** Convenience: ring `calleeUserId` for a call over `channel`. */
1041
+ ring(calleeUserId, args) {
1042
+ var _a;
1043
+ return this.sendCallPush(calleeUserId, {
1044
+ userId: args.callerUserId,
1045
+ hasVideo: args.hasVideo ? "true" : "false",
1046
+ callId: args.callId,
1047
+ callName: args.callerName,
1048
+ action: "call",
1049
+ channel: (_a = args.channel) != null ? _a : "socketio"
1050
+ });
1051
+ }
1052
+ /** Convenience: cancel a ring (e.g. caller hung up before answer). */
1053
+ cancel(calleeUserId, args) {
1054
+ var _a;
1055
+ return this.sendCallPush(calleeUserId, {
1056
+ userId: args.callerUserId,
1057
+ hasVideo: args.hasVideo ? "true" : "false",
1058
+ callId: args.callId,
1059
+ callName: args.callerName,
1060
+ action: "decline",
1061
+ channel: (_a = args.channel) != null ? _a : "socketio"
1062
+ });
1063
+ }
1064
+ };
1065
+ _appKey = new WeakMap();
1066
+ _appName = new WeakMap();
1067
+ _endpoints = new WeakMap();
1068
+ _fetch = new WeakMap();
1069
+ return __toCommonJS(dist_exports);
1070
+ })();