@signalwire/js 4.0.0-beta.8 → 4.0.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{base-BxFSgMTI.d.cts → base-CQPEW1lJ.d.mts} +8 -7
- package/dist/base-CQPEW1lJ.d.mts.map +1 -0
- package/dist/{base-DKDZK4Rr.d.mts → base-Cif20s3C.d.cts} +8 -7
- package/dist/base-Cif20s3C.d.cts.map +1 -0
- package/dist/browser.mjs +176 -63
- package/dist/browser.mjs.map +1 -1
- package/dist/browser.umd.js +176 -63
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +173 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +58 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +174 -53
- package/dist/index.mjs.map +1 -1
- package/dist/operators/index.cjs +1 -1
- package/dist/operators/index.d.cts +1 -1
- package/dist/operators/index.d.mts +1 -1
- package/dist/operators/index.mjs +1 -1
- package/dist/{operators-CJEML6aa.cjs → operators-mm21prWr.cjs} +3 -17
- package/dist/operators-mm21prWr.cjs.map +1 -0
- package/dist/{operators-C8Tqm86j.mjs → operators-uT_fb8ba.mjs} +4 -12
- package/dist/operators-uT_fb8ba.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/base-BxFSgMTI.d.cts.map +0 -1
- package/dist/base-DKDZK4Rr.d.mts.map +0 -1
- package/dist/operators-C8Tqm86j.mjs.map +0 -1
- package/dist/operators-CJEML6aa.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_operators = require('./operators-
|
|
1
|
+
const require_operators = require('./operators-mm21prWr.cjs');
|
|
2
2
|
let jwt_decode = require("jwt-decode");
|
|
3
3
|
let rxjs = require("rxjs");
|
|
4
4
|
let uuid = require("uuid");
|
|
@@ -27,6 +27,40 @@ var Destroyable = class {
|
|
|
27
27
|
}
|
|
28
28
|
return cached;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Like `cachedObservable`, but defers emissions to the microtask queue
|
|
32
|
+
* via `observeOn(asapScheduler)`.
|
|
33
|
+
*
|
|
34
|
+
* Use ONLY for public-facing observable getters that external consumers
|
|
35
|
+
* subscribe to. Prevents a class of bugs where `BehaviorSubject` or
|
|
36
|
+
* `ReplaySubject` replays synchronously during `subscribe()`, before
|
|
37
|
+
* the subscription variable is assigned in the caller's scope.
|
|
38
|
+
*
|
|
39
|
+
* Do NOT use for observables consumed internally by the SDK — internal
|
|
40
|
+
* code using `subscribeTo()`, `firstValueFrom()`, or `withLatestFrom()`
|
|
41
|
+
* depends on synchronous emission delivery.
|
|
42
|
+
*/
|
|
43
|
+
publicCachedObservable(key, factory) {
|
|
44
|
+
const publicKey = `public:${key}`;
|
|
45
|
+
this._observableCache ??= /* @__PURE__ */ new Map();
|
|
46
|
+
let cached = this._observableCache.get(publicKey);
|
|
47
|
+
if (!cached) {
|
|
48
|
+
cached = factory().pipe((0, rxjs.observeOn)(rxjs.asapScheduler));
|
|
49
|
+
this._observableCache.set(publicKey, cached);
|
|
50
|
+
}
|
|
51
|
+
return cached;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Wraps an observable so emissions are deferred to the microtask queue.
|
|
55
|
+
*
|
|
56
|
+
* Use ONLY for public-facing getters that expose a subject via
|
|
57
|
+
* `.asObservable()` without going through `cachedObservable`.
|
|
58
|
+
*
|
|
59
|
+
* Do NOT use for observables consumed internally by the SDK.
|
|
60
|
+
*/
|
|
61
|
+
deferEmission(observable) {
|
|
62
|
+
return observable.pipe((0, rxjs.observeOn)(rxjs.asapScheduler));
|
|
63
|
+
}
|
|
30
64
|
subscribeTo(observable, observerOrNext) {
|
|
31
65
|
const subscription = observable.subscribe(observerOrNext);
|
|
32
66
|
this.subscriptions.push(subscription);
|
|
@@ -1231,17 +1265,21 @@ var AttachManager = class {
|
|
|
1231
1265
|
buildCallOptions(attachment) {
|
|
1232
1266
|
const { audio: audioDirection, video: videoDirection } = attachment.mediaDirections;
|
|
1233
1267
|
const { audioInputDevice, videoInputDevice } = attachment;
|
|
1268
|
+
const receiveAudio = audioDirection.includes("recv");
|
|
1269
|
+
const receiveVideo = videoDirection.includes("recv");
|
|
1270
|
+
const sendAudio = audioDirection.includes("send");
|
|
1271
|
+
const sendVideo = videoDirection.includes("send");
|
|
1234
1272
|
return {
|
|
1235
|
-
receiveAudio
|
|
1236
|
-
receiveVideo
|
|
1237
|
-
inputAudioDeviceConstraints: {
|
|
1238
|
-
audio:
|
|
1273
|
+
receiveAudio,
|
|
1274
|
+
receiveVideo,
|
|
1275
|
+
inputAudioDeviceConstraints: sendAudio ? {
|
|
1276
|
+
audio: true,
|
|
1239
1277
|
...this.deviceController.deviceInfoToConstraints(audioInputDevice)
|
|
1240
|
-
},
|
|
1241
|
-
inputVideoDeviceConstraints: {
|
|
1242
|
-
video:
|
|
1278
|
+
} : void 0,
|
|
1279
|
+
inputVideoDeviceConstraints: sendVideo ? {
|
|
1280
|
+
video: true,
|
|
1243
1281
|
...this.deviceController.deviceInfoToConstraints(videoInputDevice)
|
|
1244
|
-
},
|
|
1282
|
+
} : void 0,
|
|
1245
1283
|
reattach: true
|
|
1246
1284
|
};
|
|
1247
1285
|
}
|
|
@@ -1947,6 +1985,9 @@ function isJSONRPCRequest(value) {
|
|
|
1947
1985
|
function isJSONRPCResponse(value) {
|
|
1948
1986
|
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "id") && typeof value.id === "string" && (hasProperty(value, "result") || hasProperty(value, "error"));
|
|
1949
1987
|
}
|
|
1988
|
+
function isJSONRPCErrorResponse(value) {
|
|
1989
|
+
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "id") && typeof value.id === "string" && (hasProperty(value, "error") && isObject(value.error) && hasProperty(value.error, "code") && hasProperty(value.error, "message") || hasProperty(value, "result") && isObject(value.result) && hasProperty(value.result, "code") && value.result.code !== "200" && hasProperty(value.result, "message"));
|
|
1990
|
+
}
|
|
1950
1991
|
|
|
1951
1992
|
//#endregion
|
|
1952
1993
|
//#region src/core/RPCMessages/guards/events.guards.ts
|
|
@@ -3668,6 +3709,11 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3668
3709
|
].includes(connectionState)))));
|
|
3669
3710
|
}
|
|
3670
3711
|
initSubscriptions() {
|
|
3712
|
+
this.subscribeTo(this.callJoinedEvent$, (event) => {
|
|
3713
|
+
const memberNodeId = event.room_session.members.find((m) => m.call_id === event.call_id)?.node_id;
|
|
3714
|
+
if (memberNodeId) this.setNodeIdIfNull(memberNodeId);
|
|
3715
|
+
if (event.member_id) this.setSelfIdIfNull(event.member_id);
|
|
3716
|
+
});
|
|
3671
3717
|
this.subscribeTo(this.vertoMedia$, (event) => {
|
|
3672
3718
|
logger$10.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
|
|
3673
3719
|
this._signalingStatus$.next("ringing");
|
|
@@ -3699,6 +3745,28 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3699
3745
|
this.sendVertoPong(vertoPing);
|
|
3700
3746
|
});
|
|
3701
3747
|
}
|
|
3748
|
+
/**
|
|
3749
|
+
* Set node_id/selfId only when the current value is null.
|
|
3750
|
+
*
|
|
3751
|
+
* During reattach, `call.joined` and `verto.answer` events can deliver
|
|
3752
|
+
* these identifiers before the `verto.invite` RPC response (`CALL CREATED`)
|
|
3753
|
+
* arrives. These methods let early events populate them eagerly so that
|
|
3754
|
+
* downstream RPC calls (e.g. `call.layout.list`) don't fail with empty
|
|
3755
|
+
* identifiers. `processInviteResponse()` remains the authoritative source
|
|
3756
|
+
* and always overwrites unconditionally.
|
|
3757
|
+
*/
|
|
3758
|
+
setNodeIdIfNull(nodeId) {
|
|
3759
|
+
if (!this._nodeId$.value && nodeId) {
|
|
3760
|
+
logger$10.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
|
|
3761
|
+
this._nodeId$.next(nodeId);
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
setSelfIdIfNull(selfId) {
|
|
3765
|
+
if (!this._selfId$.value && selfId) {
|
|
3766
|
+
logger$10.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
|
|
3767
|
+
this._selfId$.next(selfId);
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3702
3770
|
async sendVertoPong(vertoPing) {
|
|
3703
3771
|
try {
|
|
3704
3772
|
const vertoPongMessage = VertoPong({ ...vertoPing });
|
|
@@ -3722,6 +3790,9 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3722
3790
|
get selfId() {
|
|
3723
3791
|
return this._selfId$.value;
|
|
3724
3792
|
}
|
|
3793
|
+
get callJoinedEvent$() {
|
|
3794
|
+
return this.webRtcCallSession.callEvent$.pipe((0, rxjs.filter)(isCallJoinedPayload), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3795
|
+
}
|
|
3725
3796
|
get vertoMedia$() {
|
|
3726
3797
|
return this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoMediaInnerParams, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3727
3798
|
}
|
|
@@ -4252,7 +4323,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4252
4323
|
}
|
|
4253
4324
|
/** Observable stream of errors from media, signaling, and peer connection layers. */
|
|
4254
4325
|
get errors$() {
|
|
4255
|
-
return this._errors$.asObservable();
|
|
4326
|
+
return this.deferEmission(this._errors$.asObservable());
|
|
4256
4327
|
}
|
|
4257
4328
|
/**
|
|
4258
4329
|
* @internal Push an error to the call's error stream.
|
|
@@ -4272,7 +4343,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4272
4343
|
}
|
|
4273
4344
|
/** Observable of the address associated with this call. */
|
|
4274
4345
|
get address$() {
|
|
4275
|
-
return (0, rxjs.from)([this.address]);
|
|
4346
|
+
return this.deferEmission((0, rxjs.from)([this.address])).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4276
4347
|
}
|
|
4277
4348
|
/** Display name of the caller. */
|
|
4278
4349
|
get fromName() {
|
|
@@ -4333,7 +4404,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4333
4404
|
}
|
|
4334
4405
|
/** Observable of layout layer positions for all participants. */
|
|
4335
4406
|
get layoutLayers$() {
|
|
4336
|
-
return this.callEventsManager.layoutLayers
|
|
4407
|
+
return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4337
4408
|
}
|
|
4338
4409
|
/** Current snapshot of layout layers. */
|
|
4339
4410
|
get layoutLayers() {
|
|
@@ -4347,7 +4418,9 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4347
4418
|
params
|
|
4348
4419
|
});
|
|
4349
4420
|
try {
|
|
4350
|
-
|
|
4421
|
+
const response = await this.clientSession.execute(request);
|
|
4422
|
+
if (isJSONRPCErrorResponse(response)) throw new require_operators.JSONRPCError(parseInt(response.result?.code ?? "0"), `Error response from method ${method}: ${response.result?.code} ${response.result?.message}`, void 0, void 0, request.id);
|
|
4423
|
+
return response;
|
|
4351
4424
|
} catch (error) {
|
|
4352
4425
|
logger$9.error(`[Call] Error executing method ${method} with params`, params, error);
|
|
4353
4426
|
throw error;
|
|
@@ -4376,45 +4449,45 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4376
4449
|
}
|
|
4377
4450
|
/** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
|
|
4378
4451
|
get status$() {
|
|
4379
|
-
return this.
|
|
4452
|
+
return this.publicCachedObservable("status$", () => (0, rxjs.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, rxjs.distinctUntilChanged)(), (0, rxjs.tap)((status) => {
|
|
4380
4453
|
this._lastMergedStatus = status;
|
|
4381
4454
|
})));
|
|
4382
4455
|
}
|
|
4383
4456
|
/** Observable of the participants list, emits on join/leave/update. */
|
|
4384
4457
|
get participants$() {
|
|
4385
|
-
return this.callEventsManager.participants
|
|
4458
|
+
return this.deferEmission(this.callEventsManager.participants$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4386
4459
|
}
|
|
4387
4460
|
/** Observable of the local (self) participant. */
|
|
4388
4461
|
get self$() {
|
|
4389
|
-
return this.callEventsManager.self
|
|
4462
|
+
return this.deferEmission(this.callEventsManager.self$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4390
4463
|
}
|
|
4391
4464
|
/** Observable indicating whether the call is being recorded. */
|
|
4392
4465
|
get recording$() {
|
|
4393
|
-
return this.callEventsManager.recording
|
|
4466
|
+
return this.deferEmission(this.callEventsManager.recording$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4394
4467
|
}
|
|
4395
4468
|
/** Observable indicating whether the call is being streamed. */
|
|
4396
4469
|
get streaming$() {
|
|
4397
|
-
return this.callEventsManager.streaming
|
|
4470
|
+
return this.deferEmission(this.callEventsManager.streaming$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4398
4471
|
}
|
|
4399
4472
|
/** Observable indicating whether raise-hand priority is active. */
|
|
4400
4473
|
get raiseHandPriority$() {
|
|
4401
|
-
return this.callEventsManager.raiseHandPriority
|
|
4474
|
+
return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4402
4475
|
}
|
|
4403
4476
|
/** Observable indicating whether the call room is locked. */
|
|
4404
4477
|
get locked$() {
|
|
4405
|
-
return this.callEventsManager.locked
|
|
4478
|
+
return this.deferEmission(this.callEventsManager.locked$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4406
4479
|
}
|
|
4407
4480
|
/** Observable of custom metadata associated with the call. */
|
|
4408
4481
|
get meta$() {
|
|
4409
|
-
return this.callEventsManager.meta
|
|
4482
|
+
return this.deferEmission(this.callEventsManager.meta$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4410
4483
|
}
|
|
4411
4484
|
/** Observable of the call's capability flags. */
|
|
4412
4485
|
get capabilities$() {
|
|
4413
|
-
return this.callEventsManager.capabilities
|
|
4486
|
+
return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4414
4487
|
}
|
|
4415
4488
|
/** Observable of the current layout name. */
|
|
4416
4489
|
get layout$() {
|
|
4417
|
-
return this.callEventsManager.layout
|
|
4490
|
+
return this.deferEmission(this.callEventsManager.layout$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4418
4491
|
}
|
|
4419
4492
|
/** Current call status. */
|
|
4420
4493
|
get status() {
|
|
@@ -4446,7 +4519,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4446
4519
|
}
|
|
4447
4520
|
/** Observable of available layout names. */
|
|
4448
4521
|
get layouts$() {
|
|
4449
|
-
return this.callEventsManager.layouts
|
|
4522
|
+
return this.deferEmission(this.callEventsManager.layouts$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4450
4523
|
}
|
|
4451
4524
|
/** Current snapshot of available layout names. */
|
|
4452
4525
|
get layouts() {
|
|
@@ -4454,7 +4527,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4454
4527
|
}
|
|
4455
4528
|
/** Observable of the local media stream (camera/microphone). */
|
|
4456
4529
|
get localStream$() {
|
|
4457
|
-
return this.vertoManager.localStream
|
|
4530
|
+
return this.deferEmission(this.vertoManager.localStream$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4458
4531
|
}
|
|
4459
4532
|
/** Current local media stream, or `null` if not available. */
|
|
4460
4533
|
get localStream() {
|
|
@@ -4462,7 +4535,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4462
4535
|
}
|
|
4463
4536
|
/** Observable of the remote media stream from the far end. */
|
|
4464
4537
|
get remoteStream$() {
|
|
4465
|
-
return this.vertoManager.remoteStream
|
|
4538
|
+
return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4466
4539
|
}
|
|
4467
4540
|
/** Current remote media stream, or `null` if not available. */
|
|
4468
4541
|
get remoteStream() {
|
|
@@ -4470,7 +4543,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4470
4543
|
}
|
|
4471
4544
|
/** Observable of custom user variables associated with the call. */
|
|
4472
4545
|
get userVariables$() {
|
|
4473
|
-
return this._userVariables$.asObservable();
|
|
4546
|
+
return this.deferEmission(this._userVariables$.asObservable());
|
|
4474
4547
|
}
|
|
4475
4548
|
/** a copy of the current custom user variables of the call. */
|
|
4476
4549
|
get userVariables() {
|
|
@@ -4490,7 +4563,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4490
4563
|
}
|
|
4491
4564
|
/** Observable of the current audio/video send/receive directions. */
|
|
4492
4565
|
get mediaDirections$() {
|
|
4493
|
-
return this.vertoManager.mediaDirections
|
|
4566
|
+
return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4494
4567
|
}
|
|
4495
4568
|
/** Current audio/video send/receive directions. */
|
|
4496
4569
|
get mediaDirections() {
|
|
@@ -4536,31 +4609,31 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4536
4609
|
}
|
|
4537
4610
|
/** Observable of call-updated events. */
|
|
4538
4611
|
get callUpdated$() {
|
|
4539
|
-
return this.
|
|
4612
|
+
return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isCallUpdatedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4540
4613
|
}
|
|
4541
4614
|
/** Observable of member-joined events. */
|
|
4542
4615
|
get memberJoined$() {
|
|
4543
|
-
return this.
|
|
4616
|
+
return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isMemberJoinedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4544
4617
|
}
|
|
4545
4618
|
/** Observable of member-left events. */
|
|
4546
4619
|
get memberLeft$() {
|
|
4547
|
-
return this.
|
|
4620
|
+
return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isMemberLeftMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4548
4621
|
}
|
|
4549
4622
|
/** Observable of member-updated events (mute, volume, etc.). */
|
|
4550
4623
|
get memberUpdated$() {
|
|
4551
|
-
return this.
|
|
4624
|
+
return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isMemberUpdatedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4552
4625
|
}
|
|
4553
4626
|
/** Observable of member-talking events (speech start/stop). */
|
|
4554
4627
|
get memberTalking$() {
|
|
4555
|
-
return this.
|
|
4628
|
+
return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isMemberTalkingMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4556
4629
|
}
|
|
4557
4630
|
/** Observable of call state-change events. */
|
|
4558
4631
|
get callStates$() {
|
|
4559
|
-
return this.
|
|
4632
|
+
return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isCallStateMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4560
4633
|
}
|
|
4561
4634
|
/** Observable of layout-changed events. */
|
|
4562
4635
|
get layoutUpdates$() {
|
|
4563
|
-
return this.
|
|
4636
|
+
return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isLayoutChangedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4564
4637
|
}
|
|
4565
4638
|
/** Underlying `RTCPeerConnection`, for advanced use cases. */
|
|
4566
4639
|
get rtcPeerConnection() {
|
|
@@ -4568,7 +4641,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4568
4641
|
}
|
|
4569
4642
|
/** Observable of raw signaling events as plain objects. */
|
|
4570
4643
|
get signalingEvent$() {
|
|
4571
|
-
return this.
|
|
4644
|
+
return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, rxjs.map)((event) => JSON.parse(JSON.stringify(event)))));
|
|
4572
4645
|
}
|
|
4573
4646
|
/** Observable of WebRTC-specific signaling messages. */
|
|
4574
4647
|
get webrtcMessages$() {
|
|
@@ -4610,7 +4683,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4610
4683
|
}
|
|
4611
4684
|
/** Observable that emits `true` when answered, `false` when rejected. */
|
|
4612
4685
|
get answered$() {
|
|
4613
|
-
return this._answered$.asObservable();
|
|
4686
|
+
return this.deferEmission(this._answered$.asObservable());
|
|
4614
4687
|
}
|
|
4615
4688
|
/**
|
|
4616
4689
|
* Sets the call layout and participant positions.
|
|
@@ -5064,7 +5137,7 @@ var PendingRPC = class PendingRPC {
|
|
|
5064
5137
|
next: (response) => {
|
|
5065
5138
|
isSettled = true;
|
|
5066
5139
|
if (response.error) {
|
|
5067
|
-
const rpcError = new require_operators.
|
|
5140
|
+
const rpcError = new require_operators.JSONRPCError(response.error.code, response.error.message, response.error.data, void 0, request.id);
|
|
5068
5141
|
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
|
|
5069
5142
|
reject(rpcError);
|
|
5070
5143
|
} else {
|
|
@@ -5354,6 +5427,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
5354
5427
|
...params,
|
|
5355
5428
|
...persistedParams
|
|
5356
5429
|
});
|
|
5430
|
+
this.transport.resetSessionEpoch();
|
|
5357
5431
|
const response = await (0, rxjs.lastValueFrom)((0, rxjs.from)(this.transport.execute(rpcConnectRequest)).pipe(require_operators.throwOnRPCError(), (0, rxjs.map)((res) => res.result), (0, rxjs.filter)(isRPCConnectResult), (0, rxjs.tap)(() => {
|
|
5358
5432
|
logger$6.debug("[Session] Response passed filter, processing authentication result");
|
|
5359
5433
|
}), (0, rxjs.take)(1), (0, rxjs.catchError)((err) => {
|
|
@@ -5833,7 +5907,30 @@ function isSignalwirePingRequest(value) {
|
|
|
5833
5907
|
//#endregion
|
|
5834
5908
|
//#region src/managers/TransportManager.ts
|
|
5835
5909
|
const logger$2 = require_operators.getLogger();
|
|
5836
|
-
var TransportManager = class extends Destroyable {
|
|
5910
|
+
var TransportManager = class TransportManager extends Destroyable {
|
|
5911
|
+
/**
|
|
5912
|
+
* Normalise a server event timestamp to epoch seconds.
|
|
5913
|
+
*
|
|
5914
|
+
* The server uses two formats:
|
|
5915
|
+
* - `webrtc.message`: float epoch seconds (e.g. 1774372099.022817)
|
|
5916
|
+
* - all other events: int epoch microseconds (e.g. 1774372099925857)
|
|
5917
|
+
*
|
|
5918
|
+
* Values above 1e12 are treated as microseconds and divided by 1e6.
|
|
5919
|
+
*/
|
|
5920
|
+
static toEpochSeconds(ts) {
|
|
5921
|
+
const n = typeof ts === "string" ? Number(ts) : ts;
|
|
5922
|
+
return n > 0xe8d4a51000 ? n / 1e6 : n;
|
|
5923
|
+
}
|
|
5924
|
+
/**
|
|
5925
|
+
* Extract the event timestamp from a signalwire.event message.
|
|
5926
|
+
* Returns `null` for messages that have no timestamp
|
|
5927
|
+
* (e.g. signalwire.authorization.state, RPC responses).
|
|
5928
|
+
*/
|
|
5929
|
+
static extractEventTimestamp(message) {
|
|
5930
|
+
if (!isSignalwireRequest(message)) return null;
|
|
5931
|
+
if (message.params.event_type === "signalwire.authorization.state") return null;
|
|
5932
|
+
return TransportManager.toEpochSeconds(message.params.timestamp);
|
|
5933
|
+
}
|
|
5837
5934
|
constructor(storage, protocolKey, webSocketConstructor, relayHost, onError) {
|
|
5838
5935
|
super();
|
|
5839
5936
|
this.storage = storage;
|
|
@@ -5866,6 +5963,23 @@ var TransportManager = class extends Destroyable {
|
|
|
5866
5963
|
return true;
|
|
5867
5964
|
});
|
|
5868
5965
|
};
|
|
5966
|
+
this.discardStaleEvents = () => {
|
|
5967
|
+
return (0, rxjs.filter)((message) => {
|
|
5968
|
+
const ts = TransportManager.extractEventTimestamp(message);
|
|
5969
|
+
if (ts === null) return true;
|
|
5970
|
+
if (this._sessionEpoch === null) {
|
|
5971
|
+
this._sessionEpoch = ts;
|
|
5972
|
+
return true;
|
|
5973
|
+
}
|
|
5974
|
+
if (ts < this._sessionEpoch) {
|
|
5975
|
+
const eventType = isSignalwireRequest(message) ? message.params.event_type : "unknown";
|
|
5976
|
+
logger$2.warn(`[Transport] Discarding stale event: ${eventType} (timestamp=${ts.toFixed(3)}, sessionEpoch=${this._sessionEpoch.toFixed(3)}, delta=${(this._sessionEpoch - ts).toFixed(3)}s)`);
|
|
5977
|
+
return false;
|
|
5978
|
+
}
|
|
5979
|
+
return true;
|
|
5980
|
+
});
|
|
5981
|
+
};
|
|
5982
|
+
this._sessionEpoch = null;
|
|
5869
5983
|
this._outgoingMessages$ = this.createSubject();
|
|
5870
5984
|
this._webSocketConnections = new WebSocketController(webSocketConstructor, relayHost, this._outgoingMessages$.asObservable(), {
|
|
5871
5985
|
connectionTimeout: PreferencesContainer.instance.connectionTimeout,
|
|
@@ -5890,7 +6004,14 @@ var TransportManager = class extends Destroyable {
|
|
|
5890
6004
|
return rxjs.EMPTY;
|
|
5891
6005
|
}), (0, rxjs.share)(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
5892
6006
|
this._jsonRPCResponse$ = this._jsonRPCMessage$.pipe((0, rxjs.filter)(isJSONRPCResponse));
|
|
5893
|
-
this._incomingEvent$ = this._jsonRPCMessage$.pipe(this.ackEvent(), this.replySignalwirePing(), (0, rxjs.filter)((message) => !isJSONRPCResponse(message)), (0, rxjs.share)(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
6007
|
+
this._incomingEvent$ = this._jsonRPCMessage$.pipe(this.ackEvent(), this.replySignalwirePing(), (0, rxjs.filter)((message) => !isJSONRPCResponse(message)), this.discardStaleEvents(), (0, rxjs.share)(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
6008
|
+
}
|
|
6009
|
+
/**
|
|
6010
|
+
* Reset the session epoch. Call this before each signalwire.connect
|
|
6011
|
+
* so that the first event after authentication establishes the new baseline.
|
|
6012
|
+
*/
|
|
6013
|
+
resetSessionEpoch() {
|
|
6014
|
+
this._sessionEpoch = null;
|
|
5894
6015
|
}
|
|
5895
6016
|
async setProtocol(protocol) {
|
|
5896
6017
|
this.protocol$.next(protocol);
|
|
@@ -6213,7 +6334,7 @@ var SignalWire = class extends Destroyable {
|
|
|
6213
6334
|
* ```
|
|
6214
6335
|
*/
|
|
6215
6336
|
get subscriber$() {
|
|
6216
|
-
return this._subscriber$.asObservable();
|
|
6337
|
+
return this.deferEmission(this._subscriber$.asObservable());
|
|
6217
6338
|
}
|
|
6218
6339
|
/** Current subscriber snapshot, or `undefined` if not yet authenticated. */
|
|
6219
6340
|
get subscriber() {
|
|
@@ -6232,7 +6353,7 @@ var SignalWire = class extends Destroyable {
|
|
|
6232
6353
|
* ```
|
|
6233
6354
|
*/
|
|
6234
6355
|
get directory$() {
|
|
6235
|
-
return this._directory$.asObservable();
|
|
6356
|
+
return this.deferEmission(this._directory$.asObservable());
|
|
6236
6357
|
}
|
|
6237
6358
|
/**
|
|
6238
6359
|
* Current directory snapshot, or `undefined` if the client is not yet connected.
|
|
@@ -6243,7 +6364,7 @@ var SignalWire = class extends Destroyable {
|
|
|
6243
6364
|
}
|
|
6244
6365
|
/** Observable that emits when the subscriber registration state changes. */
|
|
6245
6366
|
get isRegistered$() {
|
|
6246
|
-
return this._isRegistered$.asObservable();
|
|
6367
|
+
return this.deferEmission(this._isRegistered$.asObservable());
|
|
6247
6368
|
}
|
|
6248
6369
|
/** Whether the subscriber is currently registered. */
|
|
6249
6370
|
get isRegistered() {
|
|
@@ -6255,15 +6376,15 @@ var SignalWire = class extends Destroyable {
|
|
|
6255
6376
|
}
|
|
6256
6377
|
/** Observable that emits when the connection state changes. */
|
|
6257
6378
|
get isConnected$() {
|
|
6258
|
-
return this._isConnected$.asObservable();
|
|
6379
|
+
return this.deferEmission(this._isConnected$.asObservable());
|
|
6259
6380
|
}
|
|
6260
6381
|
/** Observable that emits `true` when the client is both connected and authenticated. */
|
|
6261
6382
|
get ready$() {
|
|
6262
|
-
return this.
|
|
6383
|
+
return this.publicCachedObservable("ready$", () => this._isConnected$.pipe((0, rxjs.switchMap)((connected) => connected ? this._clientSession.authenticated$ : (0, rxjs.of)(false))));
|
|
6263
6384
|
}
|
|
6264
6385
|
/** Observable stream of errors from transport, authentication, and devices. */
|
|
6265
6386
|
get errors$() {
|
|
6266
|
-
return this._errors$.asObservable();
|
|
6387
|
+
return this.deferEmission(this._errors$.asObservable());
|
|
6267
6388
|
}
|
|
6268
6389
|
/** Disconnects the WebSocket and tears down the session. */
|
|
6269
6390
|
async disconnect() {
|
|
@@ -6338,7 +6459,7 @@ var SignalWire = class extends Destroyable {
|
|
|
6338
6459
|
}
|
|
6339
6460
|
/** Observable list of available audio input (microphone) devices. */
|
|
6340
6461
|
get audioInputDevices$() {
|
|
6341
|
-
return this._deviceController.audioInputDevices
|
|
6462
|
+
return this.deferEmission(this._deviceController.audioInputDevices$);
|
|
6342
6463
|
}
|
|
6343
6464
|
/** Current snapshot of available audio input devices. */
|
|
6344
6465
|
get audioInputDevices() {
|
|
@@ -6346,7 +6467,7 @@ var SignalWire = class extends Destroyable {
|
|
|
6346
6467
|
}
|
|
6347
6468
|
/** Observable list of available audio output (speaker) devices. */
|
|
6348
6469
|
get audioOutputDevices$() {
|
|
6349
|
-
return this._deviceController.audioOutputDevices
|
|
6470
|
+
return this.deferEmission(this._deviceController.audioOutputDevices$);
|
|
6350
6471
|
}
|
|
6351
6472
|
/** Current snapshot of available audio output devices. */
|
|
6352
6473
|
get audioOutputDevices() {
|
|
@@ -6354,7 +6475,7 @@ var SignalWire = class extends Destroyable {
|
|
|
6354
6475
|
}
|
|
6355
6476
|
/** Observable list of available video input (camera) devices. */
|
|
6356
6477
|
get videoInputDevices$() {
|
|
6357
|
-
return this._deviceController.videoInputDevices
|
|
6478
|
+
return this.deferEmission(this._deviceController.videoInputDevices$);
|
|
6358
6479
|
}
|
|
6359
6480
|
/** Current snapshot of available video input devices. */
|
|
6360
6481
|
get videoInputDevices() {
|
|
@@ -6362,15 +6483,15 @@ var SignalWire = class extends Destroyable {
|
|
|
6362
6483
|
}
|
|
6363
6484
|
/** Observable of the currently selected audio input device. */
|
|
6364
6485
|
get selectedAudioInputDevice$() {
|
|
6365
|
-
return this._deviceController.selectedAudioInputDevice
|
|
6486
|
+
return this.deferEmission(this._deviceController.selectedAudioInputDevice$);
|
|
6366
6487
|
}
|
|
6367
6488
|
/** Observable of the currently selected audio output device. */
|
|
6368
6489
|
get selectedAudioOutputDevice$() {
|
|
6369
|
-
return this._deviceController.selectedAudioOutputDevice
|
|
6490
|
+
return this.deferEmission(this._deviceController.selectedAudioOutputDevice$);
|
|
6370
6491
|
}
|
|
6371
6492
|
/** Observable of the currently selected video input device. */
|
|
6372
6493
|
get selectedVideoInputDevice$() {
|
|
6373
|
-
return this._deviceController.selectedVideoInputDevice
|
|
6494
|
+
return this.deferEmission(this._deviceController.selectedVideoInputDevice$);
|
|
6374
6495
|
}
|
|
6375
6496
|
/** Currently selected audio input device, or `null` if none. */
|
|
6376
6497
|
get selectedAudioInputDevice() {
|