@signalwire/js 4.0.0-dev-20260410164129 → 4.0.0-dev-20260413184400
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/browser.mjs +906 -599
- package/dist/browser.mjs.map +1 -1
- package/dist/browser.umd.js +906 -599
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +670 -364
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +6 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +660 -354
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser.umd.js
CHANGED
|
@@ -3394,7 +3394,7 @@ var require_map = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3394
3394
|
exports.map = void 0;
|
|
3395
3395
|
var lift_1$64 = require_lift();
|
|
3396
3396
|
var OperatorSubscriber_1$54 = require_OperatorSubscriber();
|
|
3397
|
-
function map$
|
|
3397
|
+
function map$19(project, thisArg) {
|
|
3398
3398
|
return lift_1$64.operate(function(source, subscriber) {
|
|
3399
3399
|
var index = 0;
|
|
3400
3400
|
source.subscribe(OperatorSubscriber_1$54.createOperatorSubscriber(subscriber, function(value) {
|
|
@@ -3402,7 +3402,7 @@ var require_map = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3402
3402
|
}));
|
|
3403
3403
|
});
|
|
3404
3404
|
}
|
|
3405
|
-
exports.map = map$
|
|
3405
|
+
exports.map = map$19;
|
|
3406
3406
|
}));
|
|
3407
3407
|
|
|
3408
3408
|
//#endregion
|
|
@@ -4144,7 +4144,7 @@ var require_timer = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4144
4144
|
var async_1$11 = require_async();
|
|
4145
4145
|
var isScheduler_1 = require_isScheduler();
|
|
4146
4146
|
var isDate_1$1 = require_isDate();
|
|
4147
|
-
function timer$
|
|
4147
|
+
function timer$2(dueTime, intervalOrScheduler, scheduler) {
|
|
4148
4148
|
if (dueTime === void 0) dueTime = 0;
|
|
4149
4149
|
if (scheduler === void 0) scheduler = async_1$11.async;
|
|
4150
4150
|
var intervalDuration = -1;
|
|
@@ -4163,7 +4163,7 @@ var require_timer = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4163
4163
|
}, due);
|
|
4164
4164
|
});
|
|
4165
4165
|
}
|
|
4166
|
-
exports.timer = timer$
|
|
4166
|
+
exports.timer = timer$2;
|
|
4167
4167
|
}));
|
|
4168
4168
|
|
|
4169
4169
|
//#endregion
|
|
@@ -4297,7 +4297,7 @@ var require_filter = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4297
4297
|
exports.filter = void 0;
|
|
4298
4298
|
var lift_1$62 = require_lift();
|
|
4299
4299
|
var OperatorSubscriber_1$49 = require_OperatorSubscriber();
|
|
4300
|
-
function filter$
|
|
4300
|
+
function filter$16(predicate, thisArg) {
|
|
4301
4301
|
return lift_1$62.operate(function(source, subscriber) {
|
|
4302
4302
|
var index = 0;
|
|
4303
4303
|
source.subscribe(OperatorSubscriber_1$49.createOperatorSubscriber(subscriber, function(value) {
|
|
@@ -4305,7 +4305,7 @@ var require_filter = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4305
4305
|
}));
|
|
4306
4306
|
});
|
|
4307
4307
|
}
|
|
4308
|
-
exports.filter = filter$
|
|
4308
|
+
exports.filter = filter$16;
|
|
4309
4309
|
}));
|
|
4310
4310
|
|
|
4311
4311
|
//#endregion
|
|
@@ -6938,7 +6938,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6938
6938
|
var innerFrom_1$6 = require_innerFrom();
|
|
6939
6939
|
var lift_1$13 = require_lift();
|
|
6940
6940
|
var OperatorSubscriber_1$11 = require_OperatorSubscriber();
|
|
6941
|
-
function switchMap$
|
|
6941
|
+
function switchMap$7(project, resultSelector) {
|
|
6942
6942
|
return lift_1$13.operate(function(source, subscriber) {
|
|
6943
6943
|
var innerSubscriber = null;
|
|
6944
6944
|
var index = 0;
|
|
@@ -6962,7 +6962,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6962
6962
|
}));
|
|
6963
6963
|
});
|
|
6964
6964
|
}
|
|
6965
|
-
exports.switchMap = switchMap$
|
|
6965
|
+
exports.switchMap = switchMap$7;
|
|
6966
6966
|
}));
|
|
6967
6967
|
|
|
6968
6968
|
//#endregion
|
|
@@ -7586,7 +7586,7 @@ var require_withLatestFrom = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
7586
7586
|
var identity_1$1 = require_identity();
|
|
7587
7587
|
var noop_1$1 = require_noop();
|
|
7588
7588
|
var args_1 = require_args();
|
|
7589
|
-
function withLatestFrom$
|
|
7589
|
+
function withLatestFrom$2() {
|
|
7590
7590
|
var inputs = [];
|
|
7591
7591
|
for (var _i = 0; _i < arguments.length; _i++) inputs[_i] = arguments[_i];
|
|
7592
7592
|
var project = args_1.popResultSelector(inputs);
|
|
@@ -7615,7 +7615,7 @@ var require_withLatestFrom = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
7615
7615
|
}));
|
|
7616
7616
|
});
|
|
7617
7617
|
}
|
|
7618
|
-
exports.withLatestFrom = withLatestFrom$
|
|
7618
|
+
exports.withLatestFrom = withLatestFrom$2;
|
|
7619
7619
|
}));
|
|
7620
7620
|
|
|
7621
7621
|
//#endregion
|
|
@@ -8937,13 +8937,13 @@ var require_cjs = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
8937
8937
|
|
|
8938
8938
|
//#endregion
|
|
8939
8939
|
//#region src/behaviors/Destroyable.ts
|
|
8940
|
-
var import_cjs$
|
|
8940
|
+
var import_cjs$28 = require_cjs();
|
|
8941
8941
|
var Destroyable = class {
|
|
8942
8942
|
constructor() {
|
|
8943
8943
|
this.subscriptions = [];
|
|
8944
8944
|
this.subjects = [];
|
|
8945
|
-
this._destroyed$ = new import_cjs$
|
|
8946
|
-
this._change$ = new import_cjs$
|
|
8945
|
+
this._destroyed$ = new import_cjs$28.Subject();
|
|
8946
|
+
this._change$ = new import_cjs$28.Subject();
|
|
8947
8947
|
}
|
|
8948
8948
|
destroy() {
|
|
8949
8949
|
this._observableCache?.clear();
|
|
@@ -8980,7 +8980,7 @@ var Destroyable = class {
|
|
|
8980
8980
|
this._observableCache ??= /* @__PURE__ */ new Map();
|
|
8981
8981
|
let cached = this._observableCache.get(publicKey);
|
|
8982
8982
|
if (!cached) {
|
|
8983
|
-
cached = factory().pipe((0, import_cjs$
|
|
8983
|
+
cached = factory().pipe((0, import_cjs$28.observeOn)(import_cjs$28.asapScheduler));
|
|
8984
8984
|
this._observableCache.set(publicKey, cached);
|
|
8985
8985
|
}
|
|
8986
8986
|
return cached;
|
|
@@ -8994,32 +8994,32 @@ var Destroyable = class {
|
|
|
8994
8994
|
* Do NOT use for observables consumed internally by the SDK.
|
|
8995
8995
|
*/
|
|
8996
8996
|
deferEmission(observable) {
|
|
8997
|
-
return observable.pipe((0, import_cjs$
|
|
8997
|
+
return observable.pipe((0, import_cjs$28.observeOn)(import_cjs$28.asapScheduler));
|
|
8998
8998
|
}
|
|
8999
8999
|
subscribeTo(observable, observerOrNext) {
|
|
9000
9000
|
const subscription = observable.subscribe(observerOrNext);
|
|
9001
9001
|
this.subscriptions.push(subscription);
|
|
9002
9002
|
}
|
|
9003
9003
|
createSubject() {
|
|
9004
|
-
const subject = new import_cjs$
|
|
9004
|
+
const subject = new import_cjs$28.Subject();
|
|
9005
9005
|
this.subjects.push(subject);
|
|
9006
|
-
this.subscriptions.push(subject.pipe((0, import_cjs$
|
|
9006
|
+
this.subscriptions.push(subject.pipe((0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
|
|
9007
9007
|
return subject;
|
|
9008
9008
|
}
|
|
9009
9009
|
createReplaySubject(bufferSize, windowTime$1) {
|
|
9010
|
-
const subject = new import_cjs$
|
|
9010
|
+
const subject = new import_cjs$28.ReplaySubject(bufferSize, windowTime$1);
|
|
9011
9011
|
this.subjects.push(subject);
|
|
9012
|
-
this.subscriptions.push(subject.pipe((0, import_cjs$
|
|
9012
|
+
this.subscriptions.push(subject.pipe((0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
|
|
9013
9013
|
return subject;
|
|
9014
9014
|
}
|
|
9015
9015
|
createBehaviorSubject(initialValue) {
|
|
9016
|
-
const subject = new import_cjs$
|
|
9016
|
+
const subject = new import_cjs$28.BehaviorSubject(initialValue);
|
|
9017
9017
|
this.subjects.push(subject);
|
|
9018
|
-
this.subscriptions.push(subject.pipe((0, import_cjs$
|
|
9018
|
+
this.subscriptions.push(subject.pipe((0, import_cjs$28.skip)(1), (0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
|
|
9019
9019
|
return subject;
|
|
9020
9020
|
}
|
|
9021
9021
|
get $() {
|
|
9022
|
-
return this._change$.pipe((0, import_cjs$
|
|
9022
|
+
return this._change$.pipe((0, import_cjs$28.map)(() => this));
|
|
9023
9023
|
}
|
|
9024
9024
|
/**
|
|
9025
9025
|
* Observable that emits when the instance is destroyed
|
|
@@ -9478,9 +9478,9 @@ var require_loglevel = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
9478
9478
|
defaultLogger$1 = new Logger();
|
|
9479
9479
|
defaultLogger$1.getLogger = function getLogger$1(name) {
|
|
9480
9480
|
if (typeof name !== "symbol" && typeof name !== "string" || name === "") throw new TypeError("You must supply a name when creating a logger.");
|
|
9481
|
-
var logger$
|
|
9482
|
-
if (!logger$
|
|
9483
|
-
return logger$
|
|
9481
|
+
var logger$30 = _loggersByName[name];
|
|
9482
|
+
if (!logger$30) logger$30 = _loggersByName[name] = new Logger(name, defaultLogger$1.methodFactory);
|
|
9483
|
+
return logger$30;
|
|
9484
9484
|
};
|
|
9485
9485
|
var _log = typeof window !== undefinedType ? window.log : void 0;
|
|
9486
9486
|
defaultLogger$1.noConflict = function() {
|
|
@@ -9520,15 +9520,15 @@ const shouldStringify = (payload) => {
|
|
|
9520
9520
|
return true;
|
|
9521
9521
|
};
|
|
9522
9522
|
const wsTraffic = ({ type, payload }) => {
|
|
9523
|
-
const logger$
|
|
9523
|
+
const logger$30 = getLoggerInstance();
|
|
9524
9524
|
const { logWsTraffic } = debugOptions ?? {};
|
|
9525
9525
|
if (!logWsTraffic) return;
|
|
9526
9526
|
const msg = shouldStringify(payload) ? JSON.stringify(payload, null, 2) : payload;
|
|
9527
|
-
return logger$
|
|
9527
|
+
return logger$30.debug(`${type.toUpperCase()}: \n`, msg, "\n");
|
|
9528
9528
|
};
|
|
9529
9529
|
const getLogger = () => {
|
|
9530
|
-
const logger$
|
|
9531
|
-
return new Proxy(logger$
|
|
9530
|
+
const logger$30 = getLoggerInstance();
|
|
9531
|
+
return new Proxy(logger$30, { get(target, prop, receiver) {
|
|
9532
9532
|
if (prop === "wsTraffic") return wsTraffic;
|
|
9533
9533
|
return Reflect.get(target, prop, receiver);
|
|
9534
9534
|
} });
|
|
@@ -9577,8 +9577,8 @@ const asyncRetry = async ({ asyncCallable, maxRetries: retries = DEFAULT_MAX_RET
|
|
|
9577
9577
|
|
|
9578
9578
|
//#endregion
|
|
9579
9579
|
//#region src/controllers/HTTPRequestController.ts
|
|
9580
|
-
var import_cjs$
|
|
9581
|
-
const logger$
|
|
9580
|
+
var import_cjs$27 = require_cjs();
|
|
9581
|
+
const logger$29 = getLogger();
|
|
9582
9582
|
const GET_PARAMS = {
|
|
9583
9583
|
method: "GET",
|
|
9584
9584
|
headers: { Accept: "application/json" }
|
|
@@ -9613,9 +9613,9 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9613
9613
|
constructor(baseURL, getCredential, options = {}) {
|
|
9614
9614
|
this.baseURL = baseURL;
|
|
9615
9615
|
this.getCredential = getCredential;
|
|
9616
|
-
this._responses$ = new import_cjs$
|
|
9617
|
-
this._errors$ = new import_cjs$
|
|
9618
|
-
this._status$ = new import_cjs$
|
|
9616
|
+
this._responses$ = new import_cjs$27.Subject();
|
|
9617
|
+
this._errors$ = new import_cjs$27.Subject();
|
|
9618
|
+
this._status$ = new import_cjs$27.BehaviorSubject("idle");
|
|
9619
9619
|
this.maxRetries = options.maxRetries ?? HTTPRequestController.defaultMaxRetries;
|
|
9620
9620
|
this.retryDelayMin = options.retryDelayMin ?? HTTPRequestController.defaultRetryDelayMinMs;
|
|
9621
9621
|
this.retryDelayMax = options.retryDelayMax ?? HTTPRequestController.defaultRetryDelayMaxMs;
|
|
@@ -9641,7 +9641,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9641
9641
|
this._responses$.next(response);
|
|
9642
9642
|
return response;
|
|
9643
9643
|
} catch (error) {
|
|
9644
|
-
logger$
|
|
9644
|
+
logger$29.error("[HTTPRequestController] Request error:", error);
|
|
9645
9645
|
this._status$.next("error");
|
|
9646
9646
|
const err = error instanceof Error ? error : new Error("HTTP request failed", { cause: error });
|
|
9647
9647
|
this._errors$.next(err);
|
|
@@ -9668,7 +9668,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9668
9668
|
const url = this.buildURL(request.url);
|
|
9669
9669
|
const headers = this.buildHeaders(request.headers);
|
|
9670
9670
|
const timeout$5 = request.timeout ?? this.requestTimeout;
|
|
9671
|
-
logger$
|
|
9671
|
+
logger$29.debug("[HTTPRequestController] Executing request:", {
|
|
9672
9672
|
method: request.method,
|
|
9673
9673
|
url,
|
|
9674
9674
|
headers: Object.keys(headers).reduce((acc, key) => {
|
|
@@ -9688,7 +9688,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9688
9688
|
});
|
|
9689
9689
|
clearTimeout(timeoutId);
|
|
9690
9690
|
const httpResponse = await this.convertResponse(response);
|
|
9691
|
-
logger$
|
|
9691
|
+
logger$29.debug("[HTTPRequestController] Response received:", {
|
|
9692
9692
|
status: response.status,
|
|
9693
9693
|
statusText: response.statusText,
|
|
9694
9694
|
headers: [...response.headers.entries()],
|
|
@@ -9698,7 +9698,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9698
9698
|
} catch (error) {
|
|
9699
9699
|
clearTimeout(timeoutId);
|
|
9700
9700
|
if (error instanceof Error && error.name === "AbortError") throw new RequestTimeoutError(`Request timeout after ${timeout$5}ms`, { cause: error });
|
|
9701
|
-
logger$
|
|
9701
|
+
logger$29.error("[HTTPRequestController] Request failed:", error);
|
|
9702
9702
|
throw error;
|
|
9703
9703
|
}
|
|
9704
9704
|
}
|
|
@@ -9712,8 +9712,8 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9712
9712
|
const credential = this.getCredential();
|
|
9713
9713
|
if (credential.token) {
|
|
9714
9714
|
headers.Authorization = `Bearer ${credential.token}`;
|
|
9715
|
-
logger$
|
|
9716
|
-
} else logger$
|
|
9715
|
+
logger$29.debug("[HTTPRequestController] Using Bearer token auth, token length:", credential.token.length);
|
|
9716
|
+
} else logger$29.warn("[HTTPRequestController] No credentials available for authentication");
|
|
9717
9717
|
return headers;
|
|
9718
9718
|
}
|
|
9719
9719
|
/**
|
|
@@ -9862,6 +9862,19 @@ const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
|
|
|
9862
9862
|
const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
|
|
9863
9863
|
const DEFAULT_DEVICE_POLLING_INTERVAL_MS = 0;
|
|
9864
9864
|
const PREFERENCES_STORAGE_KEY = "sw:preferences";
|
|
9865
|
+
/** Scope value that enables automatic token refresh. */
|
|
9866
|
+
const SAT_REFRESH_SCOPE = "sat:refresh";
|
|
9867
|
+
/** API endpoints for device token operations. */
|
|
9868
|
+
const DEVICE_TOKEN_ENDPOINT = "/api/fabric/subscriber/devices/token";
|
|
9869
|
+
const DEVICE_REFRESH_ENDPOINT = "/api/fabric/subscriber/devices/refresh";
|
|
9870
|
+
/** Default device token TTL in seconds (15 minutes). */
|
|
9871
|
+
const DEVICE_TOKEN_DEFAULT_EXPIRE_IN = 900;
|
|
9872
|
+
/** Buffer time in milliseconds before expiry to trigger refresh. */
|
|
9873
|
+
const DEVICE_TOKEN_REFRESH_BUFFER_MS = 3e4;
|
|
9874
|
+
/** Maximum retry attempts for device token refresh on transient failure. */
|
|
9875
|
+
const DEVICE_TOKEN_REFRESH_MAX_RETRIES = 3;
|
|
9876
|
+
/** Base delay in milliseconds for exponential backoff on refresh retry. */
|
|
9877
|
+
const DEVICE_TOKEN_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9865
9878
|
/** JSON-RPC error code for requester validation failure (corrupted auth state). */
|
|
9866
9879
|
const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
|
|
9867
9880
|
/** JSON-RPC error code for invalid params (e.g., missing authentication block). */
|
|
@@ -9952,7 +9965,7 @@ function fromMsToSec(milliseconds) {
|
|
|
9952
9965
|
|
|
9953
9966
|
//#endregion
|
|
9954
9967
|
//#region src/containers/PreferencesContainer.ts
|
|
9955
|
-
const logger$
|
|
9968
|
+
const logger$28 = getLogger();
|
|
9956
9969
|
var PreferencesContainer = class PreferencesContainer {
|
|
9957
9970
|
static get instance() {
|
|
9958
9971
|
this._instance ??= new PreferencesContainer();
|
|
@@ -10614,7 +10627,7 @@ var ClientPreferences = class {
|
|
|
10614
10627
|
if (!this._storage) return;
|
|
10615
10628
|
const data = collectStoredPreferences();
|
|
10616
10629
|
this._storage.setItem(PREFERENCES_STORAGE_KEY, data, "local").catch((error) => {
|
|
10617
|
-
logger$
|
|
10630
|
+
logger$28.error(`[ClientPreferences] Failed to save preferences: ${String(error)}`);
|
|
10618
10631
|
});
|
|
10619
10632
|
}
|
|
10620
10633
|
/** Loads preferences from storage and applies them to the container. */
|
|
@@ -10623,15 +10636,15 @@ var ClientPreferences = class {
|
|
|
10623
10636
|
this._storage.getItem(PREFERENCES_STORAGE_KEY, "local").then((stored) => {
|
|
10624
10637
|
if (stored) applyStoredPreferences(stored);
|
|
10625
10638
|
}).catch((error) => {
|
|
10626
|
-
logger$
|
|
10639
|
+
logger$28.error(`[ClientPreferences] Failed to load preferences: ${String(error)}`);
|
|
10627
10640
|
});
|
|
10628
10641
|
}
|
|
10629
10642
|
};
|
|
10630
10643
|
|
|
10631
10644
|
//#endregion
|
|
10632
10645
|
//#region src/controllers/NavigatorDeviceController.ts
|
|
10633
|
-
var import_cjs$
|
|
10634
|
-
const logger$
|
|
10646
|
+
var import_cjs$26 = require_cjs();
|
|
10647
|
+
const logger$27 = getLogger();
|
|
10635
10648
|
/** Maps a device kind to its storage key. */
|
|
10636
10649
|
const DEVICE_STORAGE_KEYS = {
|
|
10637
10650
|
audioinput: DEVICE_STORAGE_KEY_AUDIO_INPUT,
|
|
@@ -10653,7 +10666,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10653
10666
|
super();
|
|
10654
10667
|
this.webRTCApiProvider = webRTCApiProvider;
|
|
10655
10668
|
this.deviceChangeHandler = () => {
|
|
10656
|
-
logger$
|
|
10669
|
+
logger$27.debug("[DeviceController] Device change detected");
|
|
10657
10670
|
this.enumerateDevices();
|
|
10658
10671
|
};
|
|
10659
10672
|
this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
|
|
@@ -10690,17 +10703,17 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10690
10703
|
return {};
|
|
10691
10704
|
}
|
|
10692
10705
|
get errors$() {
|
|
10693
|
-
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$
|
|
10706
|
+
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10694
10707
|
}
|
|
10695
10708
|
/** Observable that emits when the SDK auto-switches a device. */
|
|
10696
10709
|
get deviceRecovered$() {
|
|
10697
|
-
return this._deviceRecovered$.asObservable().pipe((0, import_cjs$
|
|
10710
|
+
return this._deviceRecovered$.asObservable().pipe((0, import_cjs$26.takeUntil)(this.destroyed$));
|
|
10698
10711
|
}
|
|
10699
10712
|
get videoInputDisabled$() {
|
|
10700
|
-
return this.cachedObservable("videoInputDisabled$", () => this._videoInputDisabled$.asObservable().pipe((0, import_cjs$
|
|
10713
|
+
return this.cachedObservable("videoInputDisabled$", () => this._videoInputDisabled$.asObservable().pipe((0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10701
10714
|
}
|
|
10702
10715
|
get audioInputDisabled$() {
|
|
10703
|
-
return this.cachedObservable("audioInputDisabled$", () => this._audioInputDisabled$.asObservable().pipe((0, import_cjs$
|
|
10716
|
+
return this.cachedObservable("audioInputDisabled$", () => this._audioInputDisabled$.asObservable().pipe((0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10704
10717
|
}
|
|
10705
10718
|
get videoInputDisabled() {
|
|
10706
10719
|
return this._videoInputDisabled$.value;
|
|
@@ -10709,22 +10722,22 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10709
10722
|
return this._audioInputDisabled$.value;
|
|
10710
10723
|
}
|
|
10711
10724
|
get audioInputDevices$() {
|
|
10712
|
-
return this.cachedObservable("audioInputDevices$", () => this._devicesState$.pipe((0, import_cjs$
|
|
10725
|
+
return this.cachedObservable("audioInputDevices$", () => this._devicesState$.pipe((0, import_cjs$26.map)((state) => state.audioinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10713
10726
|
}
|
|
10714
10727
|
get audioOutputDevices$() {
|
|
10715
|
-
return this.cachedObservable("audioOutputDevices$", () => this._devicesState$.pipe((0, import_cjs$
|
|
10728
|
+
return this.cachedObservable("audioOutputDevices$", () => this._devicesState$.pipe((0, import_cjs$26.map)((state) => state.audiooutput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10716
10729
|
}
|
|
10717
10730
|
get videoInputDevices$() {
|
|
10718
|
-
return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, import_cjs$
|
|
10731
|
+
return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, import_cjs$26.map)((state) => state.videoinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10719
10732
|
}
|
|
10720
10733
|
get selectedAudioInputDevice$() {
|
|
10721
|
-
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$
|
|
10734
|
+
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$26.map)((state) => state.audioinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$), (0, import_cjs$26.tap)((info) => logger$27.debug("[DeviceController] Selected audio input device changed:", info))));
|
|
10722
10735
|
}
|
|
10723
10736
|
get selectedAudioOutputDevice$() {
|
|
10724
|
-
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$
|
|
10737
|
+
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$26.map)((state) => state.audiooutput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$), (0, import_cjs$26.tap)((info) => logger$27.debug("[DeviceController] Selected audio output device changed:", info))));
|
|
10725
10738
|
}
|
|
10726
10739
|
get selectedVideoInputDevice$() {
|
|
10727
|
-
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$
|
|
10740
|
+
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$26.map)((state) => state.videoinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$), (0, import_cjs$26.tap)((info) => logger$27.debug("[DeviceController] Selected video input device changed:", info))));
|
|
10728
10741
|
}
|
|
10729
10742
|
get selectedAudioInputDevice() {
|
|
10730
10743
|
if (this._audioInputDisabled$.value) return null;
|
|
@@ -10799,7 +10812,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10799
10812
|
if (device) this.persistDeviceSelection("audioinput", device);
|
|
10800
10813
|
}
|
|
10801
10814
|
selectVideoInputDevice(device) {
|
|
10802
|
-
logger$
|
|
10815
|
+
logger$27.debug("[DeviceController] Setting selected video input device:", device);
|
|
10803
10816
|
if (this._videoInputDisabled$.value && device) this._videoInputDisabled$.next(false);
|
|
10804
10817
|
const previous = this._selectedDevicesState$.value.videoinput;
|
|
10805
10818
|
if (previous && previous.deviceId !== device?.deviceId) this._deviceHistory.push("videoinput", previous);
|
|
@@ -10820,7 +10833,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10820
10833
|
}
|
|
10821
10834
|
init() {
|
|
10822
10835
|
this.loadPersistedDevices();
|
|
10823
|
-
this.subscribeTo(this._devicesState$.pipe((0, import_cjs$
|
|
10836
|
+
this.subscribeTo(this._devicesState$.pipe((0, import_cjs$26.debounceTime)(PreferencesContainer.instance.deviceDebounceTime)), (devicesState) => {
|
|
10824
10837
|
const currentSelected = this._selectedDevicesState$.value;
|
|
10825
10838
|
const newAudioInput = this._audioInputDisabled$.value ? null : this.resolveDevice("audioinput", devicesState.audioinput, currentSelected.audioinput, PreferencesContainer.instance.preferredAudioInput);
|
|
10826
10839
|
const newAudioOutput = this.resolveDevice("audiooutput", devicesState.audiooutput, currentSelected.audiooutput, PreferencesContainer.instance.preferredAudioOutput);
|
|
@@ -10856,7 +10869,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10856
10869
|
}
|
|
10857
10870
|
const fromHistory = this._deviceHistory.findInHistory(kind, devices);
|
|
10858
10871
|
if (fromHistory) {
|
|
10859
|
-
logger$
|
|
10872
|
+
logger$27.debug(`[DeviceController] Device disappeared, falling back to history: ${fromHistory.label}`);
|
|
10860
10873
|
this.emitDeviceRecovered(kind, selected, fromHistory, "device_disconnected");
|
|
10861
10874
|
return fromHistory;
|
|
10862
10875
|
}
|
|
@@ -10909,7 +10922,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10909
10922
|
try {
|
|
10910
10923
|
await this._storageManager.setItem(DEVICE_STORAGE_KEYS[kind], stored, "local");
|
|
10911
10924
|
} catch (error) {
|
|
10912
|
-
logger$
|
|
10925
|
+
logger$27.error(`[DeviceController] Failed to persist device selection for ${kind}:`, error);
|
|
10913
10926
|
}
|
|
10914
10927
|
}
|
|
10915
10928
|
async loadPersistedDevices() {
|
|
@@ -10925,7 +10938,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10925
10938
|
[kind]: stored
|
|
10926
10939
|
};
|
|
10927
10940
|
} catch (error) {
|
|
10928
|
-
logger$
|
|
10941
|
+
logger$27.error(`[DeviceController] Failed to load persisted device for ${kind}:`, error);
|
|
10929
10942
|
}
|
|
10930
10943
|
}
|
|
10931
10944
|
/** Clears device history, persisted selections, and re-enumerates devices. */
|
|
@@ -10942,8 +10955,8 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10942
10955
|
enableDeviceMonitoring() {
|
|
10943
10956
|
this.disableDeviceMonitoring();
|
|
10944
10957
|
this.webRTCApiProvider.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
|
|
10945
|
-
if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$
|
|
10946
|
-
logger$
|
|
10958
|
+
if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$26.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
|
|
10959
|
+
logger$27.debug("[DeviceController] Polling devices due to interval");
|
|
10947
10960
|
this.enumerateDevices();
|
|
10948
10961
|
});
|
|
10949
10962
|
this.enumerateDevices();
|
|
@@ -10969,13 +10982,13 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10969
10982
|
videoinput: []
|
|
10970
10983
|
});
|
|
10971
10984
|
this._devicesState$.next(devicesByKind);
|
|
10972
|
-
logger$
|
|
10985
|
+
logger$27.debug("[DeviceController] Devices enumerated:", {
|
|
10973
10986
|
audioInputs: devicesByKind.audioinput.length,
|
|
10974
10987
|
audioOutputs: devicesByKind.audiooutput.length,
|
|
10975
10988
|
videoInputs: devicesByKind.videoinput.length
|
|
10976
10989
|
});
|
|
10977
10990
|
} catch (error) {
|
|
10978
|
-
logger$
|
|
10991
|
+
logger$27.error("[DeviceController] Failed to enumerate devices:", error);
|
|
10979
10992
|
this._errors$.next(error);
|
|
10980
10993
|
}
|
|
10981
10994
|
}
|
|
@@ -10991,7 +11004,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10991
11004
|
stream.getTracks().forEach((t) => t.stop());
|
|
10992
11005
|
return capabilities;
|
|
10993
11006
|
} catch (error) {
|
|
10994
|
-
logger$
|
|
11007
|
+
logger$27.error("[DeviceController] Failed to get device capabilities:", error);
|
|
10995
11008
|
this._errors$.next(error);
|
|
10996
11009
|
throw error;
|
|
10997
11010
|
}
|
|
@@ -11242,7 +11255,7 @@ var DependencyContainer = class {
|
|
|
11242
11255
|
|
|
11243
11256
|
//#endregion
|
|
11244
11257
|
//#region src/controllers/CryptoController.ts
|
|
11245
|
-
const logger$
|
|
11258
|
+
const logger$26 = getLogger();
|
|
11246
11259
|
const DPOP_DB_NAME = "sw-dpop";
|
|
11247
11260
|
const DPOP_DB_VERSION = 1;
|
|
11248
11261
|
const DPOP_STORE_NAME = "keys";
|
|
@@ -11301,7 +11314,7 @@ async function loadKeyPairFromDB() {
|
|
|
11301
11314
|
tx.oncomplete = () => db.close();
|
|
11302
11315
|
});
|
|
11303
11316
|
} catch (error) {
|
|
11304
|
-
logger$
|
|
11317
|
+
logger$26.warn("[DPoP] Failed to load key pair from IndexedDB:", error);
|
|
11305
11318
|
return null;
|
|
11306
11319
|
}
|
|
11307
11320
|
}
|
|
@@ -11321,7 +11334,7 @@ async function saveKeyPairToDB(keyPair) {
|
|
|
11321
11334
|
};
|
|
11322
11335
|
});
|
|
11323
11336
|
} catch (error) {
|
|
11324
|
-
logger$
|
|
11337
|
+
logger$26.warn("[DPoP] Failed to save key pair to IndexedDB:", error);
|
|
11325
11338
|
}
|
|
11326
11339
|
}
|
|
11327
11340
|
async function deleteKeyPairFromDB() {
|
|
@@ -11340,7 +11353,7 @@ async function deleteKeyPairFromDB() {
|
|
|
11340
11353
|
};
|
|
11341
11354
|
});
|
|
11342
11355
|
} catch (error) {
|
|
11343
|
-
logger$
|
|
11356
|
+
logger$26.warn("[DPoP] Failed to delete key pair from IndexedDB:", error);
|
|
11344
11357
|
}
|
|
11345
11358
|
}
|
|
11346
11359
|
/**
|
|
@@ -11400,13 +11413,13 @@ var CryptoController = class {
|
|
|
11400
11413
|
this._publicJwk = await crypto.subtle.exportKey("jwk", stored.publicKey);
|
|
11401
11414
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11402
11415
|
this._initialized = true;
|
|
11403
|
-
logger$
|
|
11416
|
+
logger$26.debug("[DPoP] Key pair restored from IndexedDB, fingerprint:", this._fingerprint);
|
|
11404
11417
|
return this._fingerprint;
|
|
11405
11418
|
} catch (error) {
|
|
11406
|
-
logger$
|
|
11419
|
+
logger$26.warn("[DPoP] Stored key pair unusable, generating new one:", error);
|
|
11407
11420
|
await deleteKeyPairFromDB();
|
|
11408
11421
|
}
|
|
11409
|
-
logger$
|
|
11422
|
+
logger$26.debug("[DPoP] Generating RSA key pair");
|
|
11410
11423
|
this._keyPair = await crypto.subtle.generateKey({
|
|
11411
11424
|
name: "RSASSA-PKCS1-v1_5",
|
|
11412
11425
|
modulusLength: 2048,
|
|
@@ -11421,7 +11434,7 @@ var CryptoController = class {
|
|
|
11421
11434
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11422
11435
|
this._initialized = true;
|
|
11423
11436
|
await saveKeyPairToDB(this._keyPair);
|
|
11424
|
-
logger$
|
|
11437
|
+
logger$26.debug("[DPoP] Key pair generated and persisted, fingerprint:", this._fingerprint);
|
|
11425
11438
|
return this._fingerprint;
|
|
11426
11439
|
}
|
|
11427
11440
|
/**
|
|
@@ -11487,7 +11500,7 @@ var CryptoController = class {
|
|
|
11487
11500
|
this._fingerprint = null;
|
|
11488
11501
|
this._initialized = false;
|
|
11489
11502
|
deleteKeyPairFromDB();
|
|
11490
|
-
logger$
|
|
11503
|
+
logger$26.debug("[DPoP] Controller destroyed");
|
|
11491
11504
|
}
|
|
11492
11505
|
get publicJwk() {
|
|
11493
11506
|
if (!this._publicJwk) throw new DPoPInitError("CryptoController not initialized. Call init() first.");
|
|
@@ -11510,8 +11523,8 @@ var CryptoController = class {
|
|
|
11510
11523
|
|
|
11511
11524
|
//#endregion
|
|
11512
11525
|
//#region src/controllers/NetworkMonitor.ts
|
|
11513
|
-
var import_cjs$
|
|
11514
|
-
const logger$
|
|
11526
|
+
var import_cjs$25 = require_cjs();
|
|
11527
|
+
const logger$25 = getLogger();
|
|
11515
11528
|
/**
|
|
11516
11529
|
* Safely check whether we are running in a browser environment
|
|
11517
11530
|
* with `window` and the relevant event targets.
|
|
@@ -11554,13 +11567,13 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11554
11567
|
this.attachListeners();
|
|
11555
11568
|
}
|
|
11556
11569
|
get isOnline$() {
|
|
11557
|
-
return this._isOnline$.asObservable().pipe((0, import_cjs$
|
|
11570
|
+
return this._isOnline$.asObservable().pipe((0, import_cjs$25.takeUntil)(this._destroyed$));
|
|
11558
11571
|
}
|
|
11559
11572
|
get isOnline() {
|
|
11560
11573
|
return this._isOnline$.value;
|
|
11561
11574
|
}
|
|
11562
11575
|
get networkChange$() {
|
|
11563
|
-
return this._networkChange$.asObservable().pipe((0, import_cjs$
|
|
11576
|
+
return this._networkChange$.asObservable().pipe((0, import_cjs$25.takeUntil)(this._destroyed$));
|
|
11564
11577
|
}
|
|
11565
11578
|
destroy() {
|
|
11566
11579
|
this.removeListeners();
|
|
@@ -11568,7 +11581,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11568
11581
|
}
|
|
11569
11582
|
attachListeners() {
|
|
11570
11583
|
if (!hasBrowserNetworkEvents()) {
|
|
11571
|
-
logger$
|
|
11584
|
+
logger$25.debug("NetworkMonitor: no browser environment detected, skipping event listeners");
|
|
11572
11585
|
return;
|
|
11573
11586
|
}
|
|
11574
11587
|
window.addEventListener("online", this._onOnline);
|
|
@@ -11576,7 +11589,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11576
11589
|
const connection = getNetworkConnection();
|
|
11577
11590
|
if (connection) connection.addEventListener("change", this._onConnectionChange);
|
|
11578
11591
|
this._listenersAttached = true;
|
|
11579
|
-
logger$
|
|
11592
|
+
logger$25.debug("NetworkMonitor: event listeners attached");
|
|
11580
11593
|
}
|
|
11581
11594
|
removeListeners() {
|
|
11582
11595
|
if (!this._listenersAttached) return;
|
|
@@ -11587,10 +11600,10 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11587
11600
|
if (connection) connection.removeEventListener("change", this._onConnectionChange);
|
|
11588
11601
|
}
|
|
11589
11602
|
this._listenersAttached = false;
|
|
11590
|
-
logger$
|
|
11603
|
+
logger$25.debug("NetworkMonitor: event listeners removed");
|
|
11591
11604
|
}
|
|
11592
11605
|
handleOnline() {
|
|
11593
|
-
logger$
|
|
11606
|
+
logger$25.info("NetworkMonitor: browser went online");
|
|
11594
11607
|
this._isOnline$.next(true);
|
|
11595
11608
|
this._networkChange$.next({
|
|
11596
11609
|
type: "online",
|
|
@@ -11599,7 +11612,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11599
11612
|
});
|
|
11600
11613
|
}
|
|
11601
11614
|
handleOffline() {
|
|
11602
|
-
logger$
|
|
11615
|
+
logger$25.info("NetworkMonitor: browser went offline");
|
|
11603
11616
|
this._isOnline$.next(false);
|
|
11604
11617
|
this._networkChange$.next({
|
|
11605
11618
|
type: "offline",
|
|
@@ -11608,7 +11621,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11608
11621
|
}
|
|
11609
11622
|
handleConnectionChange() {
|
|
11610
11623
|
const networkType = getNetworkType();
|
|
11611
|
-
logger$
|
|
11624
|
+
logger$25.info(`NetworkMonitor: connection changed — effectiveType=${networkType ?? "unknown"}`);
|
|
11612
11625
|
this._networkChange$.next({
|
|
11613
11626
|
type: "connection_change",
|
|
11614
11627
|
timestamp: Date.now(),
|
|
@@ -11723,8 +11736,8 @@ function getNavigatorMediaDevices() {
|
|
|
11723
11736
|
|
|
11724
11737
|
//#endregion
|
|
11725
11738
|
//#region src/controllers/PreflightRunner.ts
|
|
11726
|
-
var import_cjs$
|
|
11727
|
-
const logger$
|
|
11739
|
+
var import_cjs$24 = require_cjs();
|
|
11740
|
+
const logger$24 = getLogger();
|
|
11728
11741
|
const DEFAULT_MEDIA_TEST_DURATION_S = 10;
|
|
11729
11742
|
const ICE_GATHERING_TIMEOUT_MS = 1e4;
|
|
11730
11743
|
const SIGNALING_RTT_TIMEOUT_MS = 5e3;
|
|
@@ -11773,7 +11786,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11773
11786
|
if (!this._options.skipMediaTest) try {
|
|
11774
11787
|
bandwidth = await this.testMediaBandwidth(destination);
|
|
11775
11788
|
} catch (error) {
|
|
11776
|
-
logger$
|
|
11789
|
+
logger$24.warn("[PreflightRunner] Media bandwidth test failed:", error);
|
|
11777
11790
|
warnings.push("Media bandwidth test failed");
|
|
11778
11791
|
}
|
|
11779
11792
|
return {
|
|
@@ -11785,7 +11798,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11785
11798
|
warnings
|
|
11786
11799
|
};
|
|
11787
11800
|
} catch (error) {
|
|
11788
|
-
logger$
|
|
11801
|
+
logger$24.error("[PreflightRunner] Preflight test failed:", error);
|
|
11789
11802
|
throw new PreflightError("preflight", error instanceof Error ? error : new Error(String(error)));
|
|
11790
11803
|
} finally {
|
|
11791
11804
|
this.destroy();
|
|
@@ -11816,7 +11829,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11816
11829
|
if (track.kind === "video" && track.readyState === "live") videoWorking = true;
|
|
11817
11830
|
}
|
|
11818
11831
|
} catch (error) {
|
|
11819
|
-
logger$
|
|
11832
|
+
logger$24.warn("[PreflightRunner] Device test failed:", error);
|
|
11820
11833
|
} finally {
|
|
11821
11834
|
if (audioStream) audioStream.getTracks().forEach((t) => t.stop());
|
|
11822
11835
|
}
|
|
@@ -11843,7 +11856,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11843
11856
|
const candidateTypes = /* @__PURE__ */ new Set();
|
|
11844
11857
|
const startTime = Date.now();
|
|
11845
11858
|
const gatheringComplete = new Promise((resolve) => {
|
|
11846
|
-
const timer$
|
|
11859
|
+
const timer$3 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
|
|
11847
11860
|
peerConnection.onicecandidate = (event) => {
|
|
11848
11861
|
if (event.candidate) {
|
|
11849
11862
|
const candidateStr = event.candidate.candidate;
|
|
@@ -11851,7 +11864,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11851
11864
|
if (candidateStr.includes("typ srflx")) candidateTypes.add("srflx");
|
|
11852
11865
|
if (candidateStr.includes("typ relay")) candidateTypes.add("relay");
|
|
11853
11866
|
} else {
|
|
11854
|
-
clearTimeout(timer$
|
|
11867
|
+
clearTimeout(timer$3);
|
|
11855
11868
|
resolve();
|
|
11856
11869
|
}
|
|
11857
11870
|
};
|
|
@@ -11874,7 +11887,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11874
11887
|
rttMs
|
|
11875
11888
|
};
|
|
11876
11889
|
} catch (error) {
|
|
11877
|
-
logger$
|
|
11890
|
+
logger$24.warn("[PreflightRunner] ICE connectivity test failed:", error);
|
|
11878
11891
|
return {
|
|
11879
11892
|
type: "failed",
|
|
11880
11893
|
turnReachable: false,
|
|
@@ -11892,7 +11905,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11892
11905
|
audio: true,
|
|
11893
11906
|
video: false
|
|
11894
11907
|
});
|
|
11895
|
-
await (0, import_cjs$
|
|
11908
|
+
await (0, import_cjs$24.firstValueFrom)(call.status$.pipe((0, import_cjs$24.filter)((s) => s === "connected"), (0, import_cjs$24.take)(1), (0, import_cjs$24.timeout)(SIGNALING_RTT_TIMEOUT_MS)));
|
|
11896
11909
|
const durationMs = this._options.duration * 1e3;
|
|
11897
11910
|
await new Promise((resolve) => setTimeout(resolve, durationMs));
|
|
11898
11911
|
const metrics = call.networkMetrics;
|
|
@@ -11921,8 +11934,8 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11921
11934
|
|
|
11922
11935
|
//#endregion
|
|
11923
11936
|
//#region src/controllers/VisibilityController.ts
|
|
11924
|
-
var import_cjs$
|
|
11925
|
-
const logger$
|
|
11937
|
+
var import_cjs$23 = require_cjs();
|
|
11938
|
+
const logger$23 = getLogger();
|
|
11926
11939
|
/**
|
|
11927
11940
|
* Checks whether the document visibility API is available.
|
|
11928
11941
|
*/
|
|
@@ -11959,15 +11972,15 @@ var VisibilityController = class extends Destroyable {
|
|
|
11959
11972
|
this._boundHandler = this._handleVisibilityChange.bind(this);
|
|
11960
11973
|
if (this._hasVisibilityApi) {
|
|
11961
11974
|
document.addEventListener("visibilitychange", this._boundHandler);
|
|
11962
|
-
logger$
|
|
11963
|
-
} else logger$
|
|
11975
|
+
logger$23.debug("VisibilityController: listening for visibilitychange events");
|
|
11976
|
+
} else logger$23.debug("VisibilityController: document visibility API not available, defaulting to visible");
|
|
11964
11977
|
}
|
|
11965
11978
|
/**
|
|
11966
11979
|
* Observable of the current visibility state.
|
|
11967
11980
|
* Emits 'visible' or 'hidden'. Always starts with the current state.
|
|
11968
11981
|
*/
|
|
11969
11982
|
get visibility$() {
|
|
11970
|
-
return this._visibility$.pipe((0, import_cjs$
|
|
11983
|
+
return this._visibility$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
|
|
11971
11984
|
}
|
|
11972
11985
|
/**
|
|
11973
11986
|
* The current visibility state value.
|
|
@@ -11980,12 +11993,12 @@ var VisibilityController = class extends Destroyable {
|
|
|
11980
11993
|
* Each event includes the previous state, new state, and timestamp.
|
|
11981
11994
|
*/
|
|
11982
11995
|
get visibilityChange$() {
|
|
11983
|
-
return this._visibilityChange$.pipe((0, import_cjs$
|
|
11996
|
+
return this._visibilityChange$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
|
|
11984
11997
|
}
|
|
11985
11998
|
destroy() {
|
|
11986
11999
|
if (this._hasVisibilityApi) {
|
|
11987
12000
|
document.removeEventListener("visibilitychange", this._boundHandler);
|
|
11988
|
-
logger$
|
|
12001
|
+
logger$23.debug("VisibilityController: removed visibilitychange listener");
|
|
11989
12002
|
}
|
|
11990
12003
|
super.destroy();
|
|
11991
12004
|
}
|
|
@@ -12003,7 +12016,7 @@ var VisibilityController = class extends Destroyable {
|
|
|
12003
12016
|
timestamp: Date.now()
|
|
12004
12017
|
};
|
|
12005
12018
|
this._visibilityChange$.next(changeEvent);
|
|
12006
|
-
logger$
|
|
12019
|
+
logger$23.debug("VisibilityController: visibility changed", {
|
|
12007
12020
|
from: previousState,
|
|
12008
12021
|
to: newState
|
|
12009
12022
|
});
|
|
@@ -12012,13 +12025,13 @@ var VisibilityController = class extends Destroyable {
|
|
|
12012
12025
|
|
|
12013
12026
|
//#endregion
|
|
12014
12027
|
//#region src/behaviors/Fetchable.ts
|
|
12015
|
-
var import_cjs$
|
|
12028
|
+
var import_cjs$22 = require_cjs();
|
|
12016
12029
|
var Fetchable = class extends Destroyable {
|
|
12017
12030
|
constructor(fromPath, http) {
|
|
12018
12031
|
super();
|
|
12019
12032
|
this.fromPath = fromPath;
|
|
12020
12033
|
this.http = http;
|
|
12021
|
-
this.fetched$ = (0, import_cjs$
|
|
12034
|
+
this.fetched$ = (0, import_cjs$22.defer)(() => (0, import_cjs$22.from)(this.fetch())).pipe((0, import_cjs$22.shareReplay)(1), (0, import_cjs$22.takeUntil)(this.destroyed$));
|
|
12022
12035
|
}
|
|
12023
12036
|
async fetch() {
|
|
12024
12037
|
const response = await this.http.request({
|
|
@@ -12253,7 +12266,7 @@ const RPCEventAckResponse = (id) => makeRPCResponse({
|
|
|
12253
12266
|
|
|
12254
12267
|
//#endregion
|
|
12255
12268
|
//#region src/managers/AttachManager.ts
|
|
12256
|
-
const logger$
|
|
12269
|
+
const logger$22 = getLogger();
|
|
12257
12270
|
var AttachManager = class {
|
|
12258
12271
|
constructor(storage, deviceController, reconnectCallsTimeout, attachKey) {
|
|
12259
12272
|
this.storage = storage;
|
|
@@ -12265,6 +12278,7 @@ var AttachManager = class {
|
|
|
12265
12278
|
const attached = await this.readAttached();
|
|
12266
12279
|
for (const callId of Object.keys(attached)) await this.detach({
|
|
12267
12280
|
id: callId,
|
|
12281
|
+
nodeId: attached[callId].nodeId,
|
|
12268
12282
|
mediaDirections: attached[callId].mediaDirections
|
|
12269
12283
|
});
|
|
12270
12284
|
}
|
|
@@ -12275,7 +12289,7 @@ var AttachManager = class {
|
|
|
12275
12289
|
try {
|
|
12276
12290
|
return await this.storage.getItem(this.attachKey) ?? {};
|
|
12277
12291
|
} catch (error) {
|
|
12278
|
-
logger$
|
|
12292
|
+
logger$22.warn("[AttachManager] Failed to retrieve attached calls from storage", error);
|
|
12279
12293
|
return {};
|
|
12280
12294
|
}
|
|
12281
12295
|
}
|
|
@@ -12283,20 +12297,20 @@ var AttachManager = class {
|
|
|
12283
12297
|
try {
|
|
12284
12298
|
await this.storage.setItem(this.attachKey, attached);
|
|
12285
12299
|
} catch (error) {
|
|
12286
|
-
logger$
|
|
12300
|
+
logger$22.warn("[AttachManager] Failed to write attached calls to storage", error);
|
|
12287
12301
|
}
|
|
12288
12302
|
}
|
|
12289
12303
|
async attach(call) {
|
|
12290
12304
|
if (!call.to) {
|
|
12291
|
-
logger$
|
|
12305
|
+
logger$22.warn("[AttachManager] Skip attach for calls with no destination");
|
|
12292
12306
|
return;
|
|
12293
12307
|
}
|
|
12294
12308
|
const attachment = {
|
|
12309
|
+
nodeId: call.nodeId,
|
|
12295
12310
|
destination: call.to,
|
|
12296
12311
|
mediaDirections: call.mediaDirections,
|
|
12297
12312
|
audioInputDevice: call.mediaDirections.audio !== "inactive" ? this.deviceController.selectedAudioInputDevice : null,
|
|
12298
12313
|
videoInputDevice: call.mediaDirections.video !== "inactive" ? this.deviceController.selectedVideoInputDevice : null,
|
|
12299
|
-
nodeId: call.nodeId,
|
|
12300
12314
|
attachedAt: Date.now()
|
|
12301
12315
|
};
|
|
12302
12316
|
const updated = {
|
|
@@ -12339,15 +12353,15 @@ var AttachManager = class {
|
|
|
12339
12353
|
callId,
|
|
12340
12354
|
...options
|
|
12341
12355
|
});
|
|
12342
|
-
logger$
|
|
12356
|
+
logger$22.info(`[AttachManager] Reattached call ${callId} (attempt ${attempt})`);
|
|
12343
12357
|
succeeded = true;
|
|
12344
12358
|
break;
|
|
12345
12359
|
} catch (error) {
|
|
12346
|
-
logger$
|
|
12360
|
+
logger$22.warn(`[AttachManager] Reattach attempt ${attempt}/3 failed for call ${callId}:`, error);
|
|
12347
12361
|
if (attempt < 3) await new Promise((r) => setTimeout(r, (attempt + 1) * 1e3));
|
|
12348
12362
|
}
|
|
12349
12363
|
if (!succeeded) {
|
|
12350
|
-
logger$
|
|
12364
|
+
logger$22.warn(`[AttachManager] Reattach failed after 3 attempts for call ${callId}, removing reference`);
|
|
12351
12365
|
await this.detach({
|
|
12352
12366
|
id: callId,
|
|
12353
12367
|
mediaDirections: attachment.mediaDirections
|
|
@@ -12361,12 +12375,13 @@ var AttachManager = class {
|
|
|
12361
12375
|
*/
|
|
12362
12376
|
buildCallOptions(attachment) {
|
|
12363
12377
|
const { audio: audioDirection, video: videoDirection } = attachment.mediaDirections;
|
|
12364
|
-
const { audioInputDevice, videoInputDevice } = attachment;
|
|
12378
|
+
const { audioInputDevice, videoInputDevice, nodeId } = attachment;
|
|
12365
12379
|
const receiveAudio = audioDirection.includes("recv");
|
|
12366
12380
|
const receiveVideo = videoDirection.includes("recv");
|
|
12367
12381
|
const sendAudio = audioDirection.includes("send");
|
|
12368
12382
|
const sendVideo = videoDirection.includes("send");
|
|
12369
12383
|
return {
|
|
12384
|
+
nodeId,
|
|
12370
12385
|
receiveAudio,
|
|
12371
12386
|
receiveVideo,
|
|
12372
12387
|
inputAudioDeviceConstraints: sendAudio ? {
|
|
@@ -12377,7 +12392,6 @@ var AttachManager = class {
|
|
|
12377
12392
|
video: true,
|
|
12378
12393
|
...this.deviceController.deviceInfoToConstraints(videoInputDevice)
|
|
12379
12394
|
} : void 0,
|
|
12380
|
-
nodeId: attachment.nodeId ?? void 0,
|
|
12381
12395
|
reattach: true
|
|
12382
12396
|
};
|
|
12383
12397
|
}
|
|
@@ -13253,7 +13267,7 @@ var require_operators = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
13253
13267
|
//#endregion
|
|
13254
13268
|
//#region src/operators/filterNull.ts
|
|
13255
13269
|
var import_operators$1 = require_operators();
|
|
13256
|
-
var import_cjs$
|
|
13270
|
+
var import_cjs$21 = require_cjs();
|
|
13257
13271
|
/**
|
|
13258
13272
|
* RxJS operator that filters out `null` and `undefined` values with type narrowing.
|
|
13259
13273
|
*
|
|
@@ -13265,7 +13279,7 @@ var import_cjs$20 = require_cjs();
|
|
|
13265
13279
|
* ```
|
|
13266
13280
|
*/
|
|
13267
13281
|
function filterNull() {
|
|
13268
|
-
return (0, import_cjs$
|
|
13282
|
+
return (0, import_cjs$21.filter)((value) => value != null);
|
|
13269
13283
|
}
|
|
13270
13284
|
|
|
13271
13285
|
//#endregion
|
|
@@ -13393,7 +13407,7 @@ function computeCapabilities(capabilities) {
|
|
|
13393
13407
|
|
|
13394
13408
|
//#endregion
|
|
13395
13409
|
//#region src/core/capabilities/SelfCapabilities.ts
|
|
13396
|
-
var import_cjs$
|
|
13410
|
+
var import_cjs$20 = require_cjs();
|
|
13397
13411
|
/**
|
|
13398
13412
|
* SelfCapabilities manages the capability state for the self participant.
|
|
13399
13413
|
*
|
|
@@ -13429,7 +13443,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13429
13443
|
}
|
|
13430
13444
|
/** Observable for self member capabilities */
|
|
13431
13445
|
get self$() {
|
|
13432
|
-
return this.cachedObservable("self$", () => this._state$.pipe((0, import_cjs$
|
|
13446
|
+
return this.cachedObservable("self$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.self), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13433
13447
|
}
|
|
13434
13448
|
/** Current self member capabilities */
|
|
13435
13449
|
get self() {
|
|
@@ -13437,7 +13451,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13437
13451
|
}
|
|
13438
13452
|
/** Observable for other member capabilities */
|
|
13439
13453
|
get member$() {
|
|
13440
|
-
return this.cachedObservable("member$", () => this._state$.pipe((0, import_cjs$
|
|
13454
|
+
return this.cachedObservable("member$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.member), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13441
13455
|
}
|
|
13442
13456
|
/** Current other member capabilities */
|
|
13443
13457
|
get member() {
|
|
@@ -13445,7 +13459,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13445
13459
|
}
|
|
13446
13460
|
/** Observable for end call capability */
|
|
13447
13461
|
get end$() {
|
|
13448
|
-
return this.cachedObservable("end$", () => this._state$.pipe((0, import_cjs$
|
|
13462
|
+
return this.cachedObservable("end$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.end), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13449
13463
|
}
|
|
13450
13464
|
/** Current end call capability */
|
|
13451
13465
|
get end() {
|
|
@@ -13453,7 +13467,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13453
13467
|
}
|
|
13454
13468
|
/** Observable for set layout capability */
|
|
13455
13469
|
get setLayout$() {
|
|
13456
|
-
return this.cachedObservable("setLayout$", () => this._state$.pipe((0, import_cjs$
|
|
13470
|
+
return this.cachedObservable("setLayout$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.setLayout), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13457
13471
|
}
|
|
13458
13472
|
/** Current set layout capability */
|
|
13459
13473
|
get setLayout() {
|
|
@@ -13461,7 +13475,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13461
13475
|
}
|
|
13462
13476
|
/** Observable for send digit capability */
|
|
13463
13477
|
get sendDigit$() {
|
|
13464
|
-
return this.cachedObservable("sendDigit$", () => this._state$.pipe((0, import_cjs$
|
|
13478
|
+
return this.cachedObservable("sendDigit$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.sendDigit), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13465
13479
|
}
|
|
13466
13480
|
/** Current send digit capability */
|
|
13467
13481
|
get sendDigit() {
|
|
@@ -13469,7 +13483,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13469
13483
|
}
|
|
13470
13484
|
/** Observable for vmuted hide capability */
|
|
13471
13485
|
get vmutedHide$() {
|
|
13472
|
-
return this.cachedObservable("vmutedHide$", () => this._state$.pipe((0, import_cjs$
|
|
13486
|
+
return this.cachedObservable("vmutedHide$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.vmutedHide), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13473
13487
|
}
|
|
13474
13488
|
/** Current vmuted hide capability */
|
|
13475
13489
|
get vmutedHide() {
|
|
@@ -13477,7 +13491,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13477
13491
|
}
|
|
13478
13492
|
/** Observable for lock capability */
|
|
13479
13493
|
get lock$() {
|
|
13480
|
-
return this.cachedObservable("lock$", () => this._state$.pipe((0, import_cjs$
|
|
13494
|
+
return this.cachedObservable("lock$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.lock), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13481
13495
|
}
|
|
13482
13496
|
/** Current lock capability */
|
|
13483
13497
|
get lock() {
|
|
@@ -13485,7 +13499,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13485
13499
|
}
|
|
13486
13500
|
/** Observable for device capability */
|
|
13487
13501
|
get device$() {
|
|
13488
|
-
return this.cachedObservable("device$", () => this._state$.pipe((0, import_cjs$
|
|
13502
|
+
return this.cachedObservable("device$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.device), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13489
13503
|
}
|
|
13490
13504
|
/** Current device capability */
|
|
13491
13505
|
get device() {
|
|
@@ -13493,7 +13507,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13493
13507
|
}
|
|
13494
13508
|
/** Observable for screenshare capability */
|
|
13495
13509
|
get screenshare$() {
|
|
13496
|
-
return this.cachedObservable("screenshare$", () => this._state$.pipe((0, import_cjs$
|
|
13510
|
+
return this.cachedObservable("screenshare$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.screenshare), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13497
13511
|
}
|
|
13498
13512
|
/** Current screenshare capability */
|
|
13499
13513
|
get screenshare() {
|
|
@@ -13520,7 +13534,7 @@ function toggleHandraiseMethod(is) {
|
|
|
13520
13534
|
|
|
13521
13535
|
//#endregion
|
|
13522
13536
|
//#region src/core/entities/Participant.ts
|
|
13523
|
-
const logger$
|
|
13537
|
+
const logger$21 = getLogger();
|
|
13524
13538
|
const initialState = {};
|
|
13525
13539
|
/**
|
|
13526
13540
|
* Represents a participant in a call.
|
|
@@ -13898,7 +13912,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13898
13912
|
try {
|
|
13899
13913
|
await this.vertoManager.addScreenMedia();
|
|
13900
13914
|
} catch (error) {
|
|
13901
|
-
logger$
|
|
13915
|
+
logger$21.error("[Participant.startScreenShare] Screen share error:", error);
|
|
13902
13916
|
}
|
|
13903
13917
|
}
|
|
13904
13918
|
/** Observable of the current screen share status. */
|
|
@@ -13918,7 +13932,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13918
13932
|
try {
|
|
13919
13933
|
await this.vertoManager.addInputDevice(options);
|
|
13920
13934
|
} catch (error) {
|
|
13921
|
-
logger$
|
|
13935
|
+
logger$21.error("[Participant.startScreenShare] Screen share error:", error);
|
|
13922
13936
|
}
|
|
13923
13937
|
}
|
|
13924
13938
|
/** Removes an additional media input device by ID. */
|
|
@@ -13980,7 +13994,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13980
13994
|
*/
|
|
13981
13995
|
exitStudioModeIfActive() {
|
|
13982
13996
|
if (this._studioAudio$.value) {
|
|
13983
|
-
logger$
|
|
13997
|
+
logger$21.debug("[SelfParticipant] Exiting studio audio mode due to individual flag toggle");
|
|
13984
13998
|
this._studioAudio$.next(false);
|
|
13985
13999
|
}
|
|
13986
14000
|
}
|
|
@@ -14004,7 +14018,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14004
14018
|
try {
|
|
14005
14019
|
await super.mute();
|
|
14006
14020
|
} catch (error) {
|
|
14007
|
-
logger$
|
|
14021
|
+
logger$21.warn("[Participant.toggleAudioInput] Server Error while muting audio input, proceeding with local toggle anyway", error);
|
|
14008
14022
|
} finally {
|
|
14009
14023
|
this.vertoManager.muteMainAudioInputDevice();
|
|
14010
14024
|
}
|
|
@@ -14014,7 +14028,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14014
14028
|
try {
|
|
14015
14029
|
await super.unmute();
|
|
14016
14030
|
} catch (error) {
|
|
14017
|
-
logger$
|
|
14031
|
+
logger$21.warn("[Participant.toggleAudioInput] Server Error while unmuting audio input, proceeding with local toggle anyway", error);
|
|
14018
14032
|
} finally {
|
|
14019
14033
|
await this.vertoManager.unmuteMainAudioInputDevice();
|
|
14020
14034
|
}
|
|
@@ -14024,7 +14038,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14024
14038
|
try {
|
|
14025
14039
|
await super.muteVideo();
|
|
14026
14040
|
} catch (error) {
|
|
14027
|
-
logger$
|
|
14041
|
+
logger$21.warn("[Participant.toggleVideoInput] Server Error while muting video input, proceeding with local toggle anyway", error);
|
|
14028
14042
|
} finally {
|
|
14029
14043
|
this.vertoManager.muteMainVideoInputDevice();
|
|
14030
14044
|
}
|
|
@@ -14034,7 +14048,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14034
14048
|
try {
|
|
14035
14049
|
await super.unmuteVideo();
|
|
14036
14050
|
} catch (error) {
|
|
14037
|
-
logger$
|
|
14051
|
+
logger$21.warn("[Participant.toggleVideoInput] Server Error while unmuting video input, proceeding with local toggle anyway", error);
|
|
14038
14052
|
} finally {
|
|
14039
14053
|
await this.vertoManager.unmuteMainVideoInputDevice();
|
|
14040
14054
|
}
|
|
@@ -14138,7 +14152,7 @@ const getValueFrom = (obj, path, defaultValue) => {
|
|
|
14138
14152
|
|
|
14139
14153
|
//#endregion
|
|
14140
14154
|
//#region src/operators/filterEventAs.ts
|
|
14141
|
-
var import_cjs$
|
|
14155
|
+
var import_cjs$19 = require_cjs();
|
|
14142
14156
|
var import_operators = require_operators();
|
|
14143
14157
|
/**
|
|
14144
14158
|
* RxJS operator that filters events based on a predicate and maps matching events.
|
|
@@ -14172,7 +14186,7 @@ var import_operators = require_operators();
|
|
|
14172
14186
|
* ```
|
|
14173
14187
|
*/
|
|
14174
14188
|
function ifIsMap(predicate, mapFn) {
|
|
14175
|
-
return (0, import_cjs$
|
|
14189
|
+
return (0, import_cjs$19.pipe)((0, import_operators.filter)(predicate), (0, import_operators.map)(mapFn));
|
|
14176
14190
|
}
|
|
14177
14191
|
/**
|
|
14178
14192
|
* Generic RxJS operator that filters events using a type guard and extracts a property.
|
|
@@ -14214,38 +14228,38 @@ function ifIsMap(predicate, mapFn) {
|
|
|
14214
14228
|
* ```
|
|
14215
14229
|
*/
|
|
14216
14230
|
function filterAs(predicate, resultPath) {
|
|
14217
|
-
return (0, import_cjs$
|
|
14231
|
+
return (0, import_cjs$19.pipe)(ifIsMap(predicate, (event) => {
|
|
14218
14232
|
return getValueFrom(event, resultPath);
|
|
14219
14233
|
}), (0, import_operators.filter)((value) => value !== void 0));
|
|
14220
14234
|
}
|
|
14221
14235
|
|
|
14222
14236
|
//#endregion
|
|
14223
14237
|
//#region src/operators/throwOnRPCError.ts
|
|
14224
|
-
var import_cjs$
|
|
14225
|
-
const logger$
|
|
14238
|
+
var import_cjs$18 = require_cjs();
|
|
14239
|
+
const logger$20 = getLogger();
|
|
14226
14240
|
/**
|
|
14227
14241
|
* RxJS operator that throws a {@link JSONRPCError} when the RPC response contains an error.
|
|
14228
14242
|
* Passes successful responses through unchanged.
|
|
14229
14243
|
*/
|
|
14230
14244
|
function throwOnRPCError() {
|
|
14231
|
-
return (0, import_cjs$
|
|
14245
|
+
return (0, import_cjs$18.map)((response) => {
|
|
14232
14246
|
if (response.error) {
|
|
14233
|
-
logger$
|
|
14247
|
+
logger$20.error("[throwOnRPCError] RPC error response:", {
|
|
14234
14248
|
code: response.error.code,
|
|
14235
14249
|
message: response.error.message,
|
|
14236
14250
|
data: response.error.data
|
|
14237
14251
|
});
|
|
14238
14252
|
throw new JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
14239
14253
|
}
|
|
14240
|
-
logger$
|
|
14254
|
+
logger$20.debug("[throwOnRPCError] RPC successful response:", response);
|
|
14241
14255
|
return response;
|
|
14242
14256
|
});
|
|
14243
14257
|
}
|
|
14244
14258
|
|
|
14245
14259
|
//#endregion
|
|
14246
14260
|
//#region src/managers/CallEventsManager.ts
|
|
14247
|
-
var import_cjs$
|
|
14248
|
-
const logger$
|
|
14261
|
+
var import_cjs$17 = require_cjs();
|
|
14262
|
+
const logger$19 = getLogger();
|
|
14249
14263
|
const initialSessionState = {};
|
|
14250
14264
|
/** @internal */
|
|
14251
14265
|
var CallEventsManager = class extends Destroyable {
|
|
@@ -14261,7 +14275,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14261
14275
|
this.initSubscriptions();
|
|
14262
14276
|
}
|
|
14263
14277
|
get participants$() {
|
|
14264
|
-
return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$
|
|
14278
|
+
return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$17.map)((participantsRecord) => Object.values(participantsRecord))));
|
|
14265
14279
|
}
|
|
14266
14280
|
get participants() {
|
|
14267
14281
|
return Object.values(this._participants$.value);
|
|
@@ -14279,40 +14293,40 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14279
14293
|
return this.callIds.has(callId);
|
|
14280
14294
|
}
|
|
14281
14295
|
get recording$() {
|
|
14282
|
-
return this.cachedObservable("recording$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14296
|
+
return this.cachedObservable("recording$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.recording), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14283
14297
|
}
|
|
14284
14298
|
get recordings$() {
|
|
14285
|
-
return this.cachedObservable("recordings$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14299
|
+
return this.cachedObservable("recordings$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.recordings), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14286
14300
|
}
|
|
14287
14301
|
get streaming$() {
|
|
14288
|
-
return this.cachedObservable("streaming$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14302
|
+
return this.cachedObservable("streaming$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.streaming), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14289
14303
|
}
|
|
14290
14304
|
get streams$() {
|
|
14291
|
-
return this.cachedObservable("streams$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14305
|
+
return this.cachedObservable("streams$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.streams), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14292
14306
|
}
|
|
14293
14307
|
get playbacks$() {
|
|
14294
|
-
return this.cachedObservable("playbacks$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14308
|
+
return this.cachedObservable("playbacks$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.playbacks), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14295
14309
|
}
|
|
14296
14310
|
get raiseHandPriority$() {
|
|
14297
|
-
return this.cachedObservable("raiseHandPriority$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14311
|
+
return this.cachedObservable("raiseHandPriority$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.prioritize_handraise), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14298
14312
|
}
|
|
14299
14313
|
get locked$() {
|
|
14300
|
-
return this.cachedObservable("locked$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14314
|
+
return this.cachedObservable("locked$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.locked), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14301
14315
|
}
|
|
14302
14316
|
get meta$() {
|
|
14303
|
-
return this.cachedObservable("meta$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14317
|
+
return this.cachedObservable("meta$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.meta), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14304
14318
|
}
|
|
14305
14319
|
get capabilities$() {
|
|
14306
|
-
return this.cachedObservable("capabilities$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14320
|
+
return this.cachedObservable("capabilities$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.capabilities), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14307
14321
|
}
|
|
14308
14322
|
get layout$() {
|
|
14309
|
-
return this.cachedObservable("layout$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14323
|
+
return this.cachedObservable("layout$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layout_name), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14310
14324
|
}
|
|
14311
14325
|
get layouts$() {
|
|
14312
|
-
return this.cachedObservable("layouts$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14326
|
+
return this.cachedObservable("layouts$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layouts), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14313
14327
|
}
|
|
14314
14328
|
get layoutLayers$() {
|
|
14315
|
-
return this.cachedObservable("layoutLayers$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14329
|
+
return this.cachedObservable("layoutLayers$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layout_layers), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14316
14330
|
}
|
|
14317
14331
|
get self() {
|
|
14318
14332
|
return this._self$.value;
|
|
@@ -14349,7 +14363,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14349
14363
|
}
|
|
14350
14364
|
initSubscriptions() {
|
|
14351
14365
|
this.subscribeTo(this.callJoinedEvent$, (callJoinedEvent) => {
|
|
14352
|
-
logger$
|
|
14366
|
+
logger$19.debug("[CallEventsManager] Handling call.joined event for call/session IDs:", {
|
|
14353
14367
|
callId: callJoinedEvent.call_id,
|
|
14354
14368
|
roomSessionId: callJoinedEvent.room_session_id
|
|
14355
14369
|
});
|
|
@@ -14376,19 +14390,19 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14376
14390
|
if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
|
|
14377
14391
|
});
|
|
14378
14392
|
this.subscribeTo(this.memberUpdates$, (member) => {
|
|
14379
|
-
logger$
|
|
14393
|
+
logger$19.debug("[CallEventsManager] Handling member update event for member ID:", member);
|
|
14380
14394
|
this.upsertParticipant(member);
|
|
14381
14395
|
});
|
|
14382
14396
|
this.subscribeTo(this.webRtcCallSession.memberLeft$, (memberLeftEvent) => {
|
|
14383
|
-
logger$
|
|
14397
|
+
logger$19.debug("[CallEventsManager] Handling member.left event for member ID:", memberLeftEvent.member.member_id);
|
|
14384
14398
|
const participants = { ...this._participants$.value };
|
|
14385
14399
|
if (memberLeftEvent.member.member_id in participants) {
|
|
14386
14400
|
delete participants[memberLeftEvent.member.member_id];
|
|
14387
14401
|
this._participants$.next(participants);
|
|
14388
|
-
} else logger$
|
|
14402
|
+
} else logger$19.warn(`[CallEventsManager] Received member.left event for unknown member ID: ${memberLeftEvent.member.member_id}`);
|
|
14389
14403
|
});
|
|
14390
14404
|
this.subscribeTo(this.webRtcCallSession.callUpdated$, (callUpdatedEvent) => {
|
|
14391
|
-
logger$
|
|
14405
|
+
logger$19.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
|
|
14392
14406
|
const roomSession = callUpdatedEvent.room_session;
|
|
14393
14407
|
this._sessionState$.next({
|
|
14394
14408
|
...this._sessionState$.value,
|
|
@@ -14403,7 +14417,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14403
14417
|
});
|
|
14404
14418
|
});
|
|
14405
14419
|
this.subscribeTo(this.layoutChangedEvent$, (layoutChangedEvent) => {
|
|
14406
|
-
logger$
|
|
14420
|
+
logger$19.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
|
|
14407
14421
|
this._sessionState$.next({
|
|
14408
14422
|
...this._sessionState$.value,
|
|
14409
14423
|
layout_name: layoutChangedEvent.id,
|
|
@@ -14413,10 +14427,10 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14413
14427
|
});
|
|
14414
14428
|
}
|
|
14415
14429
|
updateParticipantPositions(layoutChangedEvent) {
|
|
14416
|
-
if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$
|
|
14430
|
+
if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$19.warn("[CallEventsManager] No layers with member_id found in layout.changed event. Nothing to update.");
|
|
14417
14431
|
layoutChangedEvent.layers.filter((layer) => !!layer.member_id).filter((layer) => {
|
|
14418
14432
|
if (!(layer.member_id in this._participants$.value)) {
|
|
14419
|
-
logger$
|
|
14433
|
+
logger$19.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
|
|
14420
14434
|
return false;
|
|
14421
14435
|
}
|
|
14422
14436
|
return true;
|
|
@@ -14439,7 +14453,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14439
14453
|
layouts: response.result.layouts
|
|
14440
14454
|
});
|
|
14441
14455
|
}).catch((error) => {
|
|
14442
|
-
logger$
|
|
14456
|
+
logger$19.error("[CallEventsManager] Error fetching layouts:", error);
|
|
14443
14457
|
});
|
|
14444
14458
|
}
|
|
14445
14459
|
updateParticipants(members) {
|
|
@@ -14455,7 +14469,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14455
14469
|
}
|
|
14456
14470
|
const participant = this._participants$.value[member.member_id];
|
|
14457
14471
|
const oldValue = participant.value;
|
|
14458
|
-
logger$
|
|
14472
|
+
logger$19.debug("[CallEventsManager] Updating participant:", member.member_id, {
|
|
14459
14473
|
oldValue,
|
|
14460
14474
|
newValue: member
|
|
14461
14475
|
});
|
|
@@ -14467,18 +14481,18 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14467
14481
|
this._participants$.next(this._participants$.value);
|
|
14468
14482
|
}
|
|
14469
14483
|
get callJoinedEvent$() {
|
|
14470
|
-
return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$
|
|
14471
|
-
logger$
|
|
14484
|
+
return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$17.filter)(isCallJoinedPayload), (0, import_cjs$17.tap)((event) => {
|
|
14485
|
+
logger$19.debug("[CallEventsManager] Call joined event:", event);
|
|
14472
14486
|
})));
|
|
14473
14487
|
}
|
|
14474
14488
|
get layoutChangedEvent$() {
|
|
14475
|
-
return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$
|
|
14476
|
-
logger$
|
|
14489
|
+
return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$17.tap)((event) => {
|
|
14490
|
+
logger$19.debug("[CallEventsManager] Layout changed event:", event);
|
|
14477
14491
|
})));
|
|
14478
14492
|
}
|
|
14479
14493
|
get memberUpdates$() {
|
|
14480
|
-
return this.cachedObservable("memberUpdates$", () => (0, import_cjs$
|
|
14481
|
-
logger$
|
|
14494
|
+
return this.cachedObservable("memberUpdates$", () => (0, import_cjs$17.merge)(this.webRtcCallSession.memberJoined$, this.webRtcCallSession.memberUpdated$, this.webRtcCallSession.memberTalking$).pipe((0, import_cjs$17.map)((event) => event.member), (0, import_cjs$17.tap)((event) => {
|
|
14495
|
+
logger$19.debug("[CallEventsManager] Member update event:", event);
|
|
14482
14496
|
})));
|
|
14483
14497
|
}
|
|
14484
14498
|
destroy() {
|
|
@@ -14734,8 +14748,8 @@ function appendStereoParams(fmtpLine, maxBitrate) {
|
|
|
14734
14748
|
|
|
14735
14749
|
//#endregion
|
|
14736
14750
|
//#region src/controllers/ICEGatheringController.ts
|
|
14737
|
-
var import_cjs$
|
|
14738
|
-
const logger$
|
|
14751
|
+
var import_cjs$16 = require_cjs();
|
|
14752
|
+
const logger$18 = getLogger();
|
|
14739
14753
|
var ICEGatheringController = class extends Destroyable {
|
|
14740
14754
|
constructor(peerConnection, peerConnectionControllerNegotiating$, options = {}) {
|
|
14741
14755
|
super();
|
|
@@ -14743,23 +14757,23 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14743
14757
|
this.peerConnectionControllerNegotiating$ = peerConnectionControllerNegotiating$;
|
|
14744
14758
|
this.onicegatheringstatechangeHandler = () => {
|
|
14745
14759
|
const { iceGatheringState } = this.peerConnection;
|
|
14746
|
-
logger$
|
|
14760
|
+
logger$18.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
|
|
14747
14761
|
if (iceGatheringState === "gathering") this._iceCandidatesState.next({
|
|
14748
14762
|
state: "gathering",
|
|
14749
14763
|
validSDP: false
|
|
14750
14764
|
});
|
|
14751
14765
|
};
|
|
14752
14766
|
this.onicecandidateHandler = (event) => {
|
|
14753
|
-
logger$
|
|
14767
|
+
logger$18.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
|
|
14754
14768
|
this.removeTimer("iceCandidateTimer");
|
|
14755
14769
|
if (event.candidate) this.iceCandidateTimer = setTimeout(() => {
|
|
14756
14770
|
if (this.peerConnection.iceGatheringState !== "complete") {
|
|
14757
|
-
logger$
|
|
14771
|
+
logger$18.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
|
|
14758
14772
|
this.handleICECandidateTimeout();
|
|
14759
14773
|
}
|
|
14760
14774
|
}, this.iceCandidateTimeout);
|
|
14761
14775
|
else {
|
|
14762
|
-
logger$
|
|
14776
|
+
logger$18.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
|
|
14763
14777
|
this.removeTimer("iceGatheringTimer");
|
|
14764
14778
|
this.handleICEGatheringComplete();
|
|
14765
14779
|
}
|
|
@@ -14772,12 +14786,12 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14772
14786
|
this.iceGatheringTimeout = options.iceGatheringTimeout ?? DEFAULT_ICE_GATHERING_TIMEOUT_MS;
|
|
14773
14787
|
this.relayOnly = options.relayOnly ?? false;
|
|
14774
14788
|
this.setupEventListeners();
|
|
14775
|
-
this.subscribeTo(this.peerConnectionControllerNegotiating$.pipe((0, import_cjs$
|
|
14789
|
+
this.subscribeTo(this.peerConnectionControllerNegotiating$.pipe((0, import_cjs$16.filter)((isNegotiating) => isNegotiating)), (isNegotiating) => {
|
|
14776
14790
|
if (isNegotiating) {
|
|
14777
14791
|
this.setupEventListeners();
|
|
14778
14792
|
this.iceGatheringTimer = setTimeout(() => {
|
|
14779
14793
|
if (this.peerConnection.iceGatheringState !== "complete") {
|
|
14780
|
-
logger$
|
|
14794
|
+
logger$18.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
|
|
14781
14795
|
this.handleICEGatheringTimeout();
|
|
14782
14796
|
}
|
|
14783
14797
|
}, this.iceGatheringTimeout);
|
|
@@ -14791,7 +14805,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14791
14805
|
this.peerConnection.addEventListener("icegatheringstatechange", this.onicegatheringstatechangeHandler);
|
|
14792
14806
|
}
|
|
14793
14807
|
get iceCandidatesState$() {
|
|
14794
|
-
return this._iceCandidatesState.pipe((0, import_cjs$
|
|
14808
|
+
return this._iceCandidatesState.pipe((0, import_cjs$16.withLatestFrom)(this.peerConnectionControllerNegotiating$), (0, import_cjs$16.filter)(([_, isNegotiating]) => isNegotiating), (0, import_cjs$16.map)(([state, _]) => state.state));
|
|
14795
14809
|
}
|
|
14796
14810
|
get hasValidLocalDescriptionSDP() {
|
|
14797
14811
|
const sdp = this.peerConnection.localDescription?.sdp;
|
|
@@ -14804,9 +14818,9 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14804
14818
|
this.relayOnly = value;
|
|
14805
14819
|
}
|
|
14806
14820
|
handleICEGatheringComplete() {
|
|
14807
|
-
logger$
|
|
14808
|
-
logger$
|
|
14809
|
-
logger$
|
|
14821
|
+
logger$18.debug("[ICEGatheringController] Handling ICE gathering complete");
|
|
14822
|
+
logger$18.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`);
|
|
14823
|
+
logger$18.debug("[ICEGatheringController] ICE gathering complete");
|
|
14810
14824
|
this._iceCandidatesState.next({
|
|
14811
14825
|
state: "complete",
|
|
14812
14826
|
validSDP: this.hasValidLocalDescriptionSDP
|
|
@@ -14822,21 +14836,21 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14822
14836
|
this.removeTimer("iceGatheringTimer");
|
|
14823
14837
|
const validSDP = this.hasValidLocalDescriptionSDP;
|
|
14824
14838
|
if (validSDP) {
|
|
14825
|
-
logger$
|
|
14839
|
+
logger$18.debug("[ICEGatheringController] Local SDP is valid");
|
|
14826
14840
|
this._iceCandidatesState.next({
|
|
14827
14841
|
state: "timeout",
|
|
14828
14842
|
validSDP
|
|
14829
14843
|
});
|
|
14830
14844
|
this.stopGathering();
|
|
14831
|
-
} else logger$
|
|
14845
|
+
} else logger$18.debug("### ICE gathering timeout\n", this.peerConnection.localDescription?.sdp);
|
|
14832
14846
|
}
|
|
14833
14847
|
handleICECandidateTimeout() {
|
|
14834
14848
|
if (this.iceCandidateTimer) this.removeTimer("iceCandidateTimer");
|
|
14835
|
-
logger$
|
|
14849
|
+
logger$18.warn("[ICEGatheringController] ICE candidate timeout");
|
|
14836
14850
|
const validSDP = this.hasValidLocalDescriptionSDP;
|
|
14837
14851
|
if (!validSDP && !this.relayOnly) this.restartICEGatheringWithRelayOnly();
|
|
14838
14852
|
else {
|
|
14839
|
-
logger$
|
|
14853
|
+
logger$18.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout");
|
|
14840
14854
|
this._iceCandidatesState.next({
|
|
14841
14855
|
state: "timeout",
|
|
14842
14856
|
validSDP
|
|
@@ -14845,7 +14859,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14845
14859
|
}
|
|
14846
14860
|
}
|
|
14847
14861
|
restartICEGatheringWithRelayOnly() {
|
|
14848
|
-
logger$
|
|
14862
|
+
logger$18.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
|
|
14849
14863
|
this.relayOnly = true;
|
|
14850
14864
|
this.peerConnection.setConfiguration({
|
|
14851
14865
|
...this.peerConnection.getConfiguration(),
|
|
@@ -14853,14 +14867,14 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14853
14867
|
});
|
|
14854
14868
|
if (!(this.peerConnection.connectionState === "connected")) this.peerConnection.restartIce();
|
|
14855
14869
|
}
|
|
14856
|
-
removeTimer(timer$
|
|
14857
|
-
if (this[timer$
|
|
14858
|
-
clearTimeout(this[timer$
|
|
14859
|
-
this[timer$
|
|
14870
|
+
removeTimer(timer$3) {
|
|
14871
|
+
if (this[timer$3]) {
|
|
14872
|
+
clearTimeout(this[timer$3]);
|
|
14873
|
+
this[timer$3] = void 0;
|
|
14860
14874
|
}
|
|
14861
14875
|
}
|
|
14862
14876
|
clearAllTimers() {
|
|
14863
|
-
logger$
|
|
14877
|
+
logger$18.debug("[ICEGatheringController] Clearing all timers");
|
|
14864
14878
|
this.removeTimer("iceGatheringTimer");
|
|
14865
14879
|
this.removeTimer("iceCandidateTimer");
|
|
14866
14880
|
}
|
|
@@ -14869,7 +14883,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14869
14883
|
this.peerConnection.removeEventListener("icecandidate", this.onicecandidateHandler);
|
|
14870
14884
|
}
|
|
14871
14885
|
destroy() {
|
|
14872
|
-
logger$
|
|
14886
|
+
logger$18.debug("[ICEGatheringController] Destroying ICEGatheringController");
|
|
14873
14887
|
this.clearAllTimers();
|
|
14874
14888
|
this.removeEventListeners();
|
|
14875
14889
|
super.destroy();
|
|
@@ -14878,8 +14892,8 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14878
14892
|
|
|
14879
14893
|
//#endregion
|
|
14880
14894
|
//#region src/controllers/LocalStreamController.ts
|
|
14881
|
-
var import_cjs$
|
|
14882
|
-
const logger$
|
|
14895
|
+
var import_cjs$15 = require_cjs();
|
|
14896
|
+
const logger$17 = getLogger();
|
|
14883
14897
|
var LocalStreamController = class extends Destroyable {
|
|
14884
14898
|
constructor(options) {
|
|
14885
14899
|
super();
|
|
@@ -14893,16 +14907,16 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14893
14907
|
this._mediaTrackEnded$ = this.createSubject();
|
|
14894
14908
|
}
|
|
14895
14909
|
get localStream$() {
|
|
14896
|
-
return this._localStream$.asObservable().pipe((0, import_cjs$
|
|
14910
|
+
return this._localStream$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14897
14911
|
}
|
|
14898
14912
|
get localAudioTracks$() {
|
|
14899
|
-
return this._localAudioTracks$.asObservable().pipe((0, import_cjs$
|
|
14913
|
+
return this._localAudioTracks$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14900
14914
|
}
|
|
14901
14915
|
get localVideoTracks$() {
|
|
14902
|
-
return this._localVideoTracks$.asObservable().pipe((0, import_cjs$
|
|
14916
|
+
return this._localVideoTracks$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14903
14917
|
}
|
|
14904
14918
|
get mediaTrackEnded$() {
|
|
14905
|
-
return this._mediaTrackEnded$.asObservable().pipe((0, import_cjs$
|
|
14919
|
+
return this._mediaTrackEnded$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14906
14920
|
}
|
|
14907
14921
|
get localStream() {
|
|
14908
14922
|
return this._localStream$.value;
|
|
@@ -14917,26 +14931,26 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14917
14931
|
* Build the local media stream based on the provided options.
|
|
14918
14932
|
*/
|
|
14919
14933
|
async buildLocalStream() {
|
|
14920
|
-
logger$
|
|
14934
|
+
logger$17.debug("[LocalStreamController] Building local media stream.");
|
|
14921
14935
|
let stream;
|
|
14922
14936
|
if (this.options.inputAudioStream ?? this.options.inputVideoStream) {
|
|
14923
14937
|
const tracks = [...this.options.inputAudioStream?.getTracks() ?? [], ...this.options.inputVideoStream?.getTracks() ?? []];
|
|
14924
14938
|
stream = new MediaStream(tracks);
|
|
14925
14939
|
} else if (this.options.propose === "screenshare") {
|
|
14926
|
-
logger$
|
|
14940
|
+
logger$17.debug("[LocalStreamController] Requesting display media for screen sharing with audio:", Boolean(this.options.inputAudioDeviceConstraints));
|
|
14927
14941
|
stream = await this.options.getDisplayMedia({
|
|
14928
14942
|
video: true,
|
|
14929
14943
|
audio: Boolean(this.options.inputAudioDeviceConstraints)
|
|
14930
14944
|
});
|
|
14931
|
-
logger$
|
|
14945
|
+
logger$17.debug("[LocalStreamController] Screen share media obtained:", stream);
|
|
14932
14946
|
} else {
|
|
14933
14947
|
const constraints = {
|
|
14934
14948
|
audio: this.options.inputAudioDeviceConstraints,
|
|
14935
14949
|
video: this.options.inputVideoDeviceConstraints
|
|
14936
14950
|
};
|
|
14937
|
-
logger$
|
|
14951
|
+
logger$17.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
|
|
14938
14952
|
stream = await this.options.getUserMedia(constraints);
|
|
14939
|
-
logger$
|
|
14953
|
+
logger$17.debug("[LocalStreamController] User media obtained:", stream);
|
|
14940
14954
|
}
|
|
14941
14955
|
this._localStream$.next(stream);
|
|
14942
14956
|
return stream;
|
|
@@ -14953,7 +14967,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14953
14967
|
this._localStream$.next(localStream);
|
|
14954
14968
|
if (track.kind === "video") this._localVideoTracks$.next(localStream.getVideoTracks());
|
|
14955
14969
|
else this._localAudioTracks$.next(localStream.getAudioTracks());
|
|
14956
|
-
logger$
|
|
14970
|
+
logger$17.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
|
|
14957
14971
|
return localStream;
|
|
14958
14972
|
}
|
|
14959
14973
|
/**
|
|
@@ -14965,7 +14979,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14965
14979
|
const stream = this._localStream$.value;
|
|
14966
14980
|
const track = stream?.getTracks().find((t) => t.id === trackId);
|
|
14967
14981
|
if (!track) {
|
|
14968
|
-
logger$
|
|
14982
|
+
logger$17.debug(`[LocalStreamController] track not found: ${trackId}`);
|
|
14969
14983
|
return;
|
|
14970
14984
|
}
|
|
14971
14985
|
track.removeEventListener("ended", this.mediaTrackEndedHandler);
|
|
@@ -14974,7 +14988,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14974
14988
|
this._localStream$.next(stream);
|
|
14975
14989
|
if (track.kind === "video") this._localVideoTracks$.next(stream?.getVideoTracks() ?? []);
|
|
14976
14990
|
else this._localAudioTracks$.next(stream?.getAudioTracks() ?? []);
|
|
14977
|
-
logger$
|
|
14991
|
+
logger$17.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
|
|
14978
14992
|
return track;
|
|
14979
14993
|
}
|
|
14980
14994
|
/**
|
|
@@ -15009,7 +15023,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15009
15023
|
*/
|
|
15010
15024
|
stopAllTracks() {
|
|
15011
15025
|
this._localStream$.value?.getTracks().forEach((track) => {
|
|
15012
|
-
logger$
|
|
15026
|
+
logger$17.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
|
|
15013
15027
|
track.removeEventListener("ended", this.mediaTrackEndedHandler);
|
|
15014
15028
|
track.stop();
|
|
15015
15029
|
});
|
|
@@ -15025,7 +15039,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15025
15039
|
|
|
15026
15040
|
//#endregion
|
|
15027
15041
|
//#region src/controllers/TransceiverController.ts
|
|
15028
|
-
const logger$
|
|
15042
|
+
const logger$16 = getLogger();
|
|
15029
15043
|
const getDirection = (send, recv) => {
|
|
15030
15044
|
if (send && recv) return "sendrecv";
|
|
15031
15045
|
else if (send && !recv) return "sendonly";
|
|
@@ -15127,7 +15141,7 @@ var TransceiverController = class extends Destroyable {
|
|
|
15127
15141
|
sendEncodings: isAudio ? void 0 : this.sendEncodings,
|
|
15128
15142
|
streams: direction === "recvonly" ? void 0 : [localStream]
|
|
15129
15143
|
};
|
|
15130
|
-
logger$
|
|
15144
|
+
logger$16.debug(`[TransceiverController] Setting up transceiver sender for local ${track.kind} track:`, {
|
|
15131
15145
|
transceiver,
|
|
15132
15146
|
transceiverParams
|
|
15133
15147
|
});
|
|
@@ -15135,11 +15149,11 @@ var TransceiverController = class extends Destroyable {
|
|
|
15135
15149
|
await transceiver.sender.replaceTrack(track);
|
|
15136
15150
|
transceiver.direction = transceiverParams.direction;
|
|
15137
15151
|
if (transceiverParams.streams?.some((stream) => Boolean(stream))) {
|
|
15138
|
-
logger$
|
|
15152
|
+
logger$16.debug(`[TransceiverController] Setting streams for transceiver sender for local ${track.kind} track:`, transceiverParams.streams);
|
|
15139
15153
|
transceiver.sender.setStreams(...transceiverParams.streams);
|
|
15140
15154
|
}
|
|
15141
15155
|
} else {
|
|
15142
|
-
logger$
|
|
15156
|
+
logger$16.debug(`[TransceiverController] Adding new transceiver for local ${track.kind} track:`, track.id);
|
|
15143
15157
|
this.peerConnection.addTransceiver(track, transceiverParams);
|
|
15144
15158
|
}
|
|
15145
15159
|
}
|
|
@@ -15153,13 +15167,13 @@ var TransceiverController = class extends Destroyable {
|
|
|
15153
15167
|
if (options.updateTransceiverDirection) transceiver.direction = "inactive";
|
|
15154
15168
|
}
|
|
15155
15169
|
} catch (error) {
|
|
15156
|
-
logger$
|
|
15170
|
+
logger$16.error("[TransceiverController] stopTrackSender error", kind, error);
|
|
15157
15171
|
this.options.onError?.(new MediaTrackError("stopTrackSender", kind, error));
|
|
15158
15172
|
}
|
|
15159
15173
|
}
|
|
15160
15174
|
async restoreTrackSender(kind) {
|
|
15161
15175
|
try {
|
|
15162
|
-
logger$
|
|
15176
|
+
logger$16.debug("[TransceiverController] restoreTrackSender called", kind);
|
|
15163
15177
|
const constraints = {};
|
|
15164
15178
|
const transceivers = this.transceiverByKind(kind);
|
|
15165
15179
|
for (const transceiver of transceivers) {
|
|
@@ -15169,23 +15183,23 @@ var TransceiverController = class extends Destroyable {
|
|
|
15169
15183
|
if (trackKind === "audio" || trackKind === "video") constraints[trackKind] = this.getConstraintsFor(trackKind);
|
|
15170
15184
|
}
|
|
15171
15185
|
}
|
|
15172
|
-
logger$
|
|
15186
|
+
logger$16.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
|
|
15173
15187
|
if (Object.keys(constraints).length === 0) {
|
|
15174
|
-
logger$
|
|
15188
|
+
logger$16.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
|
|
15175
15189
|
return;
|
|
15176
15190
|
}
|
|
15177
15191
|
const newTracks = (await this.options.getUserMedia(constraints)).getTracks();
|
|
15178
|
-
logger$
|
|
15192
|
+
logger$16.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
|
|
15179
15193
|
for (const newTrack of newTracks) {
|
|
15180
15194
|
this.options.localStreamController.addTrack(newTrack);
|
|
15181
15195
|
const trackKind = newTrack.kind;
|
|
15182
15196
|
const transceiverOfKind = this.transceiverByKind(trackKind)[0];
|
|
15183
15197
|
transceiverOfKind.direction = trackKind === "audio" ? this.audioDirection : this.videoDirection;
|
|
15184
|
-
logger$
|
|
15198
|
+
logger$16.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
|
|
15185
15199
|
await transceiverOfKind.sender.replaceTrack(newTrack);
|
|
15186
15200
|
}
|
|
15187
15201
|
} catch (error) {
|
|
15188
|
-
logger$
|
|
15202
|
+
logger$16.error("[TransceiverController] restoreTrackSender error", kind, error);
|
|
15189
15203
|
this.options.onError?.(new MediaTrackError("restoreTrackSender", kind, error));
|
|
15190
15204
|
}
|
|
15191
15205
|
}
|
|
@@ -15226,14 +15240,14 @@ var TransceiverController = class extends Destroyable {
|
|
|
15226
15240
|
};
|
|
15227
15241
|
try {
|
|
15228
15242
|
await track.applyConstraints(constraintsToApply);
|
|
15229
|
-
logger$
|
|
15230
|
-
logger$
|
|
15243
|
+
logger$16.debug(`[TransceiverController] Updated ${kind} sender constraints:`, constraintsToApply);
|
|
15244
|
+
logger$16.debug(`[TransceiverController] Updated ${kind} sender constraints:`, track.getConstraints());
|
|
15231
15245
|
} catch (error) {
|
|
15232
|
-
logger$
|
|
15246
|
+
logger$16.warn(`[TransceiverController] applyConstraints failed for ${kind} track ${track.id}, attempting track replacement fallback:`, error);
|
|
15233
15247
|
try {
|
|
15234
15248
|
await this.replaceTrackFallback(sender, track, kind, constraintsToApply);
|
|
15235
15249
|
} catch (fallbackError) {
|
|
15236
|
-
logger$
|
|
15250
|
+
logger$16.warn(`[TransceiverController] Track replacement fallback also failed for ${kind} track:`, fallbackError);
|
|
15237
15251
|
this.options.onError?.(new MediaTrackError("updateSendersConstraints", kind, fallbackError));
|
|
15238
15252
|
}
|
|
15239
15253
|
}
|
|
@@ -15261,7 +15275,7 @@ var TransceiverController = class extends Destroyable {
|
|
|
15261
15275
|
if (!newTrack) throw new MediaTrackError("replaceTrackFallback", kind, /* @__PURE__ */ new Error("getUserMedia returned no track of the requested kind"));
|
|
15262
15276
|
await sender.replaceTrack(newTrack);
|
|
15263
15277
|
this.options.localStreamController.addTrack(newTrack);
|
|
15264
|
-
logger$
|
|
15278
|
+
logger$16.debug(`[TransceiverController] Track replacement fallback succeeded for ${kind}. New track: ${newTrack.id}`);
|
|
15265
15279
|
}
|
|
15266
15280
|
getMediaDirections() {
|
|
15267
15281
|
if (this.peerConnection.connectionState === "connected") return this.peerConnection.getTransceivers().reduce((acc, transceiver) => {
|
|
@@ -15291,60 +15305,60 @@ var TransceiverController = class extends Destroyable {
|
|
|
15291
15305
|
|
|
15292
15306
|
//#endregion
|
|
15293
15307
|
//#region src/controllers/RTCPeerConnectionController.ts
|
|
15294
|
-
var import_cjs$
|
|
15295
|
-
const logger$
|
|
15308
|
+
var import_cjs$14 = require_cjs();
|
|
15309
|
+
const logger$15 = getLogger();
|
|
15296
15310
|
var RTCPeerConnectionController = class extends Destroyable {
|
|
15297
15311
|
constructor(options = {}, remoteSessionDescription, deviceController) {
|
|
15298
15312
|
super();
|
|
15299
15313
|
this.options = options;
|
|
15300
15314
|
this.firstSDPExchangeCompleted = false;
|
|
15301
15315
|
this.negotiationNeeded$ = this.createSubject();
|
|
15302
|
-
this.localDescription$ = (0, import_cjs$
|
|
15316
|
+
this.localDescription$ = (0, import_cjs$14.defer)(() => (0, import_cjs$14.from)(this.init())).pipe((0, import_cjs$14.switchMap)(() => this.iceGatheringController.iceCandidatesState$.pipe((0, import_cjs$14.filter)((iceCandidateState) => !["new", "gathering"].includes(iceCandidateState)), (0, import_cjs$14.tap)(() => {
|
|
15303
15317
|
this.negotiationEnded();
|
|
15304
|
-
}), (0, import_cjs$
|
|
15318
|
+
}), (0, import_cjs$14.filter)(() => this.shouldEmitLocalDescription), (0, import_cjs$14.map)(() => this.peerConnection?.localDescription), filterNull(), (0, import_cjs$14.tap)((desc) => {
|
|
15305
15319
|
if (desc.type === "answer") this._type = "offer";
|
|
15306
|
-
}))), (0, import_cjs$
|
|
15320
|
+
}))), (0, import_cjs$14.shareReplay)(1), (0, import_cjs$14.takeUntil)(this.destroyed$));
|
|
15307
15321
|
this.connectionTimeout = 3e3;
|
|
15308
15322
|
this.oniceconnectionstatechangeHandler = () => {
|
|
15309
15323
|
if (this.peerConnection) {
|
|
15310
15324
|
const { iceConnectionState } = this.peerConnection;
|
|
15311
|
-
logger$
|
|
15325
|
+
logger$15.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
|
|
15312
15326
|
this._iceConnectionState$.next(this.peerConnection.iceConnectionState);
|
|
15313
15327
|
}
|
|
15314
15328
|
};
|
|
15315
15329
|
this.onconnectionstatechangeHandler = () => {
|
|
15316
15330
|
if (this.peerConnection) {
|
|
15317
15331
|
const { connectionState } = this.peerConnection;
|
|
15318
|
-
logger$
|
|
15332
|
+
logger$15.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
|
|
15319
15333
|
if (connectionState === "connected") this.removeConnectionTimer();
|
|
15320
15334
|
this._connectionState$.next(this.peerConnection.connectionState);
|
|
15321
15335
|
}
|
|
15322
15336
|
};
|
|
15323
15337
|
this.onsignalingstatechangeHandler = () => {
|
|
15324
|
-
logger$
|
|
15338
|
+
logger$15.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
|
|
15325
15339
|
};
|
|
15326
15340
|
this.onicegatheringstatechangeHandler = () => {
|
|
15327
15341
|
if (this.peerConnection) this._iceGatheringState$.next(this.peerConnection.iceGatheringState);
|
|
15328
15342
|
};
|
|
15329
15343
|
this.onnegotiationneededHandler = (event) => {
|
|
15330
|
-
logger$
|
|
15344
|
+
logger$15.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
|
|
15331
15345
|
this.negotiationNeeded$.next();
|
|
15332
15346
|
};
|
|
15333
15347
|
this.updateSelectedInputDevice = async (kind, deviceInfo) => {
|
|
15334
15348
|
try {
|
|
15335
15349
|
const { localStream } = this;
|
|
15336
15350
|
if (!localStream) {
|
|
15337
|
-
logger$
|
|
15351
|
+
logger$15.warn("[RTCPeerConnectionController] No local stream available to update input device.");
|
|
15338
15352
|
return;
|
|
15339
15353
|
}
|
|
15340
|
-
logger$
|
|
15354
|
+
logger$15.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
|
|
15341
15355
|
const track = localStream.getTracks().find((track$1) => track$1.kind === kind);
|
|
15342
15356
|
if (track) {
|
|
15343
15357
|
this.transceiverController?.stopTrackSender(kind);
|
|
15344
15358
|
this.localStream?.removeTrack(track);
|
|
15345
|
-
logger$
|
|
15359
|
+
logger$15.debug(`[RTCPeerConnectionController] Stopped existing ${kind} track: ${track.id}`, localStream.getTracks());
|
|
15346
15360
|
if (!deviceInfo) {
|
|
15347
|
-
logger$
|
|
15361
|
+
logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
|
|
15348
15362
|
return;
|
|
15349
15363
|
}
|
|
15350
15364
|
const streamTrack = (await this.getUserMedia({ [kind]: {
|
|
@@ -15352,15 +15366,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15352
15366
|
...this.deviceController.deviceInfoToConstraints(deviceInfo)
|
|
15353
15367
|
} })).getTracks().find((t) => t.kind === kind);
|
|
15354
15368
|
if (streamTrack) {
|
|
15355
|
-
logger$
|
|
15369
|
+
logger$15.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
|
|
15356
15370
|
this.localStream?.addTrack(streamTrack);
|
|
15357
15371
|
await this.transceiverController?.replaceSenderTrack(kind, streamTrack);
|
|
15358
|
-
logger$
|
|
15372
|
+
logger$15.debug(`[RTCPeerConnectionController] Added new ${kind} track: ${streamTrack.id}`, this.localStream?.getTracks());
|
|
15359
15373
|
}
|
|
15360
15374
|
}
|
|
15361
|
-
logger$
|
|
15375
|
+
logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
|
|
15362
15376
|
} catch (error) {
|
|
15363
|
-
logger$
|
|
15377
|
+
logger$15.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
|
|
15364
15378
|
this._errors$.next(error);
|
|
15365
15379
|
throw error;
|
|
15366
15380
|
}
|
|
@@ -15446,43 +15460,43 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15446
15460
|
};
|
|
15447
15461
|
}
|
|
15448
15462
|
get iceGatheringState$() {
|
|
15449
|
-
return this.cachedObservable("iceGatheringState$", () => this._iceGatheringState$.asObservable().pipe((0, import_cjs$
|
|
15463
|
+
return this.cachedObservable("iceGatheringState$", () => this._iceGatheringState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15450
15464
|
}
|
|
15451
15465
|
get mediaTrackEnded$() {
|
|
15452
|
-
return this.cachedObservable("mediaTrackEnded$", () => this.localStreamController.mediaTrackEnded$.pipe((0, import_cjs$
|
|
15466
|
+
return this.cachedObservable("mediaTrackEnded$", () => this.localStreamController.mediaTrackEnded$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15453
15467
|
}
|
|
15454
15468
|
get errors$() {
|
|
15455
|
-
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$
|
|
15469
|
+
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15456
15470
|
}
|
|
15457
15471
|
get iceCandidates$() {
|
|
15458
|
-
return this.cachedObservable("iceCandidates$", () => this._iceCandidates$.asObservable().pipe((0, import_cjs$
|
|
15472
|
+
return this.cachedObservable("iceCandidates$", () => this._iceCandidates$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15459
15473
|
}
|
|
15460
15474
|
get initialized$() {
|
|
15461
|
-
return this.cachedObservable("initialized$", () => this._initialized$.asObservable().pipe((0, import_cjs$
|
|
15475
|
+
return this.cachedObservable("initialized$", () => this._initialized$.asObservable().pipe((0, import_cjs$14.filter)((initialized) => initialized), (0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15462
15476
|
}
|
|
15463
15477
|
get remoteDescription$() {
|
|
15464
|
-
return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, import_cjs$
|
|
15478
|
+
return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15465
15479
|
}
|
|
15466
15480
|
get localStream$() {
|
|
15467
|
-
return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, import_cjs$
|
|
15481
|
+
return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15468
15482
|
}
|
|
15469
15483
|
get remoteStream$() {
|
|
15470
|
-
return this.cachedObservable("remoteStream$", () => this._remoteStream$.asObservable().pipe((0, import_cjs$
|
|
15484
|
+
return this.cachedObservable("remoteStream$", () => this._remoteStream$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15471
15485
|
}
|
|
15472
15486
|
get localAudioTracks$() {
|
|
15473
|
-
return this.cachedObservable("localAudioTracks$", () => this.localStreamController.localAudioTracks$.pipe((0, import_cjs$
|
|
15487
|
+
return this.cachedObservable("localAudioTracks$", () => this.localStreamController.localAudioTracks$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15474
15488
|
}
|
|
15475
15489
|
get localVideoTracks$() {
|
|
15476
|
-
return this.cachedObservable("localVideoTracks$", () => this.localStreamController.localVideoTracks$.pipe((0, import_cjs$
|
|
15490
|
+
return this.cachedObservable("localVideoTracks$", () => this.localStreamController.localVideoTracks$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15477
15491
|
}
|
|
15478
15492
|
get iceConnectionState$() {
|
|
15479
|
-
return this.cachedObservable("iceConnectionState$", () => this._iceConnectionState$.asObservable().pipe((0, import_cjs$
|
|
15493
|
+
return this.cachedObservable("iceConnectionState$", () => this._iceConnectionState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15480
15494
|
}
|
|
15481
15495
|
get connectionState$() {
|
|
15482
|
-
return this.cachedObservable("connectionState$", () => this._connectionState$.asObservable().pipe((0, import_cjs$
|
|
15496
|
+
return this.cachedObservable("connectionState$", () => this._connectionState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15483
15497
|
}
|
|
15484
15498
|
get signalingState$() {
|
|
15485
|
-
return this.cachedObservable("signalingState$", () => this._signalingState$.asObservable().pipe((0, import_cjs$
|
|
15499
|
+
return this.cachedObservable("signalingState$", () => this._signalingState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15486
15500
|
}
|
|
15487
15501
|
get type() {
|
|
15488
15502
|
return this._type;
|
|
@@ -15595,17 +15609,17 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15595
15609
|
async doInit() {
|
|
15596
15610
|
try {
|
|
15597
15611
|
this.setupPeerConnection();
|
|
15598
|
-
this.subscribeTo(this.negotiationNeeded$.pipe((0, import_cjs$
|
|
15612
|
+
this.subscribeTo(this.negotiationNeeded$.pipe((0, import_cjs$14.auditTime)(0), (0, import_cjs$14.exhaustMap)(async () => this.startNegotiation())), {
|
|
15599
15613
|
next: () => {
|
|
15600
|
-
logger$
|
|
15614
|
+
logger$15.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
|
|
15601
15615
|
},
|
|
15602
15616
|
error: (error) => {
|
|
15603
|
-
logger$
|
|
15617
|
+
logger$15.error("[RTCPeerConnectionController] Start Negotiation error:", error);
|
|
15604
15618
|
this._errors$.next(error);
|
|
15605
15619
|
}
|
|
15606
15620
|
});
|
|
15607
|
-
this.subscribeTo((0, import_cjs$
|
|
15608
|
-
logger$
|
|
15621
|
+
this.subscribeTo((0, import_cjs$14.merge)(this.deviceController.selectedAudioInputDevice$.pipe((0, import_cjs$14.map)((deviceInfo) => ["audio", deviceInfo])), this.deviceController.selectedVideoInputDevice$.pipe((0, import_cjs$14.map)((deviceInfo) => ["video", deviceInfo]))).pipe((0, import_cjs$14.skipWhile)(() => !this.localStreamController.localStream)), async ([kind, deviceInfo]) => {
|
|
15622
|
+
logger$15.debug(`[RTCPeerConnectionController] Selected input device changed for:`, {
|
|
15609
15623
|
kind,
|
|
15610
15624
|
deviceInfo
|
|
15611
15625
|
});
|
|
@@ -15622,7 +15636,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15622
15636
|
this._initialized$.next(true);
|
|
15623
15637
|
}
|
|
15624
15638
|
} catch (error) {
|
|
15625
|
-
logger$
|
|
15639
|
+
logger$15.error("[RTCPeerConnectionController] Initialization error:", error);
|
|
15626
15640
|
this._errors$.next(error);
|
|
15627
15641
|
this.destroy();
|
|
15628
15642
|
}
|
|
@@ -15654,22 +15668,22 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15654
15668
|
}
|
|
15655
15669
|
async startNegotiation() {
|
|
15656
15670
|
if (this.isNegotiating) {
|
|
15657
|
-
logger$
|
|
15671
|
+
logger$15.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
|
|
15658
15672
|
return;
|
|
15659
15673
|
}
|
|
15660
15674
|
this.setupEventListeners();
|
|
15661
15675
|
if (this.type === "answer") {
|
|
15662
|
-
logger$
|
|
15676
|
+
logger$15.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");
|
|
15663
15677
|
return;
|
|
15664
15678
|
}
|
|
15665
15679
|
this._isNegotiating$.next(true);
|
|
15666
|
-
logger$
|
|
15680
|
+
logger$15.debug("[RTCPeerConnectionController] Starting negotiation.");
|
|
15667
15681
|
try {
|
|
15668
15682
|
const { offerOptions } = this;
|
|
15669
|
-
logger$
|
|
15683
|
+
logger$15.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
|
|
15670
15684
|
await this.createOffer(offerOptions);
|
|
15671
15685
|
} catch (error) {
|
|
15672
|
-
logger$
|
|
15686
|
+
logger$15.error("[RTCPeerConnectionController] Error during negotiation:", error);
|
|
15673
15687
|
this._errors$.next(error);
|
|
15674
15688
|
}
|
|
15675
15689
|
}
|
|
@@ -15685,14 +15699,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15685
15699
|
let readyToConnect = status !== "failed";
|
|
15686
15700
|
try {
|
|
15687
15701
|
if (status === "received" && sdp) {
|
|
15688
|
-
logger$
|
|
15702
|
+
logger$15.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
|
|
15689
15703
|
await this._setRemoteDescription({
|
|
15690
15704
|
type: "answer",
|
|
15691
15705
|
sdp
|
|
15692
15706
|
});
|
|
15693
15707
|
}
|
|
15694
15708
|
} catch (error) {
|
|
15695
|
-
logger$
|
|
15709
|
+
logger$15.error("[RTCPeerConnectionController] Error updating answer status:", error);
|
|
15696
15710
|
this._errors$.next(error);
|
|
15697
15711
|
readyToConnect = false;
|
|
15698
15712
|
} finally {
|
|
@@ -15711,7 +15725,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15711
15725
|
await this.handleOfferReceived();
|
|
15712
15726
|
break;
|
|
15713
15727
|
case "failed":
|
|
15714
|
-
logger$
|
|
15728
|
+
logger$15.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
|
|
15715
15729
|
break;
|
|
15716
15730
|
case "sent":
|
|
15717
15731
|
default:
|
|
@@ -15743,7 +15757,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15743
15757
|
}
|
|
15744
15758
|
await this.setupLocalTracks();
|
|
15745
15759
|
const { answerOptions } = this;
|
|
15746
|
-
logger$
|
|
15760
|
+
logger$15.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
|
|
15747
15761
|
await this.createAnswer(answerOptions);
|
|
15748
15762
|
}
|
|
15749
15763
|
async handleOfferReceived() {
|
|
@@ -15751,7 +15765,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15751
15765
|
this._isNegotiating$.next(true);
|
|
15752
15766
|
await this._setRemoteDescription(this.sdpInit);
|
|
15753
15767
|
const { answerOptions } = this;
|
|
15754
|
-
logger$
|
|
15768
|
+
logger$15.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
|
|
15755
15769
|
await this.createAnswer(answerOptions);
|
|
15756
15770
|
}
|
|
15757
15771
|
readyToConnect() {
|
|
@@ -15759,7 +15773,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15759
15773
|
this.connectionTimer = setTimeout(() => {
|
|
15760
15774
|
this.removeConnectionTimer();
|
|
15761
15775
|
if (this.peerConnection?.connectionState !== "connected") {
|
|
15762
|
-
logger$
|
|
15776
|
+
logger$15.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only.");
|
|
15763
15777
|
this.iceGatheringController.restartICEGatheringWithRelayOnly();
|
|
15764
15778
|
}
|
|
15765
15779
|
}, this.connectionTimeout);
|
|
@@ -15781,14 +15795,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15781
15795
|
const stereo = this.options.stereo ?? PreferencesContainer.instance.stereoAudio;
|
|
15782
15796
|
if (preferredAudioCodecs.length > 0 || preferredVideoCodecs.length > 0) {
|
|
15783
15797
|
result = setCodecPreferences(result, preferredAudioCodecs, preferredVideoCodecs);
|
|
15784
|
-
logger$
|
|
15798
|
+
logger$15.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
|
|
15785
15799
|
preferredAudioCodecs,
|
|
15786
15800
|
preferredVideoCodecs
|
|
15787
15801
|
});
|
|
15788
15802
|
}
|
|
15789
15803
|
if (stereo) {
|
|
15790
15804
|
result = enableStereoOpus(result);
|
|
15791
|
-
logger$
|
|
15805
|
+
logger$15.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP");
|
|
15792
15806
|
}
|
|
15793
15807
|
return Promise.resolve(result);
|
|
15794
15808
|
}
|
|
@@ -15847,18 +15861,18 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15847
15861
|
...this.peerConnection.getConfiguration(),
|
|
15848
15862
|
iceTransportPolicy: "relay"
|
|
15849
15863
|
});
|
|
15850
|
-
logger$
|
|
15864
|
+
logger$15.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only");
|
|
15851
15865
|
} catch (error) {
|
|
15852
|
-
logger$
|
|
15866
|
+
logger$15.warn("[RTCPeerConnectionController] Failed to set relay-only policy:", error);
|
|
15853
15867
|
}
|
|
15854
15868
|
this.setupEventListeners();
|
|
15855
15869
|
this._isNegotiating$.next(true);
|
|
15856
|
-
logger$
|
|
15870
|
+
logger$15.debug(`[RTCPeerConnectionController] Triggering ICE restart${relayOnly ? " (relay-only)" : ""}.`);
|
|
15857
15871
|
try {
|
|
15858
15872
|
const offer = await this.peerConnection.createOffer({ iceRestart: true });
|
|
15859
15873
|
await this.setLocalDescription(offer);
|
|
15860
15874
|
} catch (error) {
|
|
15861
|
-
logger$
|
|
15875
|
+
logger$15.error("[RTCPeerConnectionController] ICE restart offer failed:", error);
|
|
15862
15876
|
this._errors$.next(error);
|
|
15863
15877
|
this.negotiationEnded();
|
|
15864
15878
|
if (policyChanged) this.restoreIceTransportPolicy();
|
|
@@ -15872,9 +15886,9 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15872
15886
|
...this.peerConnection.getConfiguration(),
|
|
15873
15887
|
iceTransportPolicy: this.options.relayOnly ? "relay" : "all"
|
|
15874
15888
|
});
|
|
15875
|
-
logger$
|
|
15889
|
+
logger$15.debug("[RTCPeerConnectionController] ICE transport policy restored");
|
|
15876
15890
|
} catch (error) {
|
|
15877
|
-
logger$
|
|
15891
|
+
logger$15.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:", error);
|
|
15878
15892
|
}
|
|
15879
15893
|
}
|
|
15880
15894
|
/**
|
|
@@ -15886,13 +15900,13 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15886
15900
|
await this.setupRemoteTracks();
|
|
15887
15901
|
}
|
|
15888
15902
|
async setupLocalTracks() {
|
|
15889
|
-
logger$
|
|
15903
|
+
logger$15.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
15890
15904
|
const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
15891
15905
|
if (this.transceiverController?.useAddStream ?? false) {
|
|
15892
|
-
logger$
|
|
15906
|
+
logger$15.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
15893
15907
|
this.peerConnection?.addStream(localStream);
|
|
15894
15908
|
if (!this.isNegotiating) {
|
|
15895
|
-
logger$
|
|
15909
|
+
logger$15.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
15896
15910
|
this.negotiationNeeded$.next();
|
|
15897
15911
|
}
|
|
15898
15912
|
return;
|
|
@@ -15908,7 +15922,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15908
15922
|
const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
|
|
15909
15923
|
await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
|
|
15910
15924
|
} else {
|
|
15911
|
-
logger$
|
|
15925
|
+
logger$15.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
|
|
15912
15926
|
this.peerConnection?.addTrack(track, localStream);
|
|
15913
15927
|
}
|
|
15914
15928
|
}
|
|
@@ -15925,7 +15939,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15925
15939
|
async setupRemoteTracks() {
|
|
15926
15940
|
if (!this.peerConnection) throw new DependencyError("RTCPeerConnection is not initialized");
|
|
15927
15941
|
this.peerConnection.ontrack = (event) => {
|
|
15928
|
-
logger$
|
|
15942
|
+
logger$15.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
|
|
15929
15943
|
if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
|
|
15930
15944
|
else {
|
|
15931
15945
|
const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
|
|
@@ -15951,9 +15965,9 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15951
15965
|
try {
|
|
15952
15966
|
const localStream = this.localStreamController.addTrack(track);
|
|
15953
15967
|
this.peerConnection.addTrack(track, localStream);
|
|
15954
|
-
logger$
|
|
15968
|
+
logger$15.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
|
|
15955
15969
|
} catch (error) {
|
|
15956
|
-
logger$
|
|
15970
|
+
logger$15.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
|
|
15957
15971
|
this._errors$.next(error);
|
|
15958
15972
|
throw error;
|
|
15959
15973
|
}
|
|
@@ -15970,15 +15984,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15970
15984
|
}
|
|
15971
15985
|
const sender = this.peerConnection.getSenders().find((sender$1) => sender$1.track?.id === trackId);
|
|
15972
15986
|
if (!sender) {
|
|
15973
|
-
logger$
|
|
15987
|
+
logger$15.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
|
|
15974
15988
|
return;
|
|
15975
15989
|
}
|
|
15976
15990
|
try {
|
|
15977
15991
|
this.peerConnection.removeTrack(sender);
|
|
15978
15992
|
this.localStreamController.removeTrack(trackId);
|
|
15979
|
-
logger$
|
|
15993
|
+
logger$15.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
|
|
15980
15994
|
} catch (error) {
|
|
15981
|
-
logger$
|
|
15995
|
+
logger$15.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
|
|
15982
15996
|
this._errors$.next(error);
|
|
15983
15997
|
throw error;
|
|
15984
15998
|
}
|
|
@@ -16005,7 +16019,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16005
16019
|
async replaceAudioTrackWithConstraints(constraints) {
|
|
16006
16020
|
const senders = this.peerConnection?.getSenders().filter((s) => s.track?.kind === "audio" && s.track.readyState === "live");
|
|
16007
16021
|
if (!senders || senders.length === 0) {
|
|
16008
|
-
logger$
|
|
16022
|
+
logger$15.warn("[RTCPeerConnectionController] No live audio sender to replace");
|
|
16009
16023
|
return;
|
|
16010
16024
|
}
|
|
16011
16025
|
for (const sender of senders) {
|
|
@@ -16023,7 +16037,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16023
16037
|
const newTrack = (await this.getUserMedia({ audio: mergedConstraints })).getAudioTracks()[0];
|
|
16024
16038
|
await sender.replaceTrack(newTrack);
|
|
16025
16039
|
this.localStreamController.addTrack(newTrack);
|
|
16026
|
-
logger$
|
|
16040
|
+
logger$15.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
|
|
16027
16041
|
}
|
|
16028
16042
|
}
|
|
16029
16043
|
/**
|
|
@@ -16031,7 +16045,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16031
16045
|
* Completes all observables to prevent memory leaks.
|
|
16032
16046
|
*/
|
|
16033
16047
|
destroy() {
|
|
16034
|
-
logger$
|
|
16048
|
+
logger$15.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
|
|
16035
16049
|
this.removeConnectionTimer();
|
|
16036
16050
|
this._iceGatheringController?.destroy();
|
|
16037
16051
|
this.localStreamController.destroy();
|
|
@@ -16055,7 +16069,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16055
16069
|
}
|
|
16056
16070
|
stopRemoteTracks() {
|
|
16057
16071
|
this._remoteStream$.value?.getTracks().forEach((track) => {
|
|
16058
|
-
logger$
|
|
16072
|
+
logger$15.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
|
|
16059
16073
|
track.stop();
|
|
16060
16074
|
});
|
|
16061
16075
|
}
|
|
@@ -16072,7 +16086,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16072
16086
|
...params,
|
|
16073
16087
|
sdp: finalRemote
|
|
16074
16088
|
};
|
|
16075
|
-
logger$
|
|
16089
|
+
logger$15.debug("[RTCPeerConnectionController] Setting remote description:", answer);
|
|
16076
16090
|
return this.peerConnection.setRemoteDescription(answer);
|
|
16077
16091
|
}
|
|
16078
16092
|
};
|
|
@@ -16110,8 +16124,8 @@ function isVertoPingInnerParams(value) {
|
|
|
16110
16124
|
|
|
16111
16125
|
//#endregion
|
|
16112
16126
|
//#region src/managers/VertoManager.ts
|
|
16113
|
-
var import_cjs$
|
|
16114
|
-
const logger$
|
|
16127
|
+
var import_cjs$13 = require_cjs();
|
|
16128
|
+
const logger$14 = getLogger();
|
|
16115
16129
|
var VertoManager = class extends Destroyable {
|
|
16116
16130
|
constructor(callSession) {
|
|
16117
16131
|
super();
|
|
@@ -16137,6 +16151,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16137
16151
|
this._screenShareTimeoutMs = 5e4;
|
|
16138
16152
|
this._nodeId$ = this.createBehaviorSubject(options.nodeId ?? null);
|
|
16139
16153
|
this.onError = options.onError;
|
|
16154
|
+
this.onModifyFailed = options.onModifyFailed;
|
|
16140
16155
|
this.initSubscriptions();
|
|
16141
16156
|
this.initMainPeerConnection();
|
|
16142
16157
|
}
|
|
@@ -16149,7 +16164,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16149
16164
|
try {
|
|
16150
16165
|
await this.executeVerto(vertoModifyMessage);
|
|
16151
16166
|
} catch (error) {
|
|
16152
|
-
logger$
|
|
16167
|
+
logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:", error);
|
|
16153
16168
|
throw error;
|
|
16154
16169
|
}
|
|
16155
16170
|
}
|
|
@@ -16162,7 +16177,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16162
16177
|
try {
|
|
16163
16178
|
await this.executeVerto(vertoModifyMessage);
|
|
16164
16179
|
} catch (error) {
|
|
16165
|
-
logger$
|
|
16180
|
+
logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:", error);
|
|
16166
16181
|
throw error;
|
|
16167
16182
|
}
|
|
16168
16183
|
}
|
|
@@ -16202,7 +16217,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16202
16217
|
return rtcPeerConnection;
|
|
16203
16218
|
}
|
|
16204
16219
|
get signalingStatus$() {
|
|
16205
|
-
return this.cachedObservable("signalingStatus$", () => (0, import_cjs$
|
|
16220
|
+
return this.cachedObservable("signalingStatus$", () => (0, import_cjs$13.merge)(this._signalingStatus$.pipe(filterNull()), this.mainPeerConnection.connectionState$.pipe((0, import_cjs$13.filter)((connectionState) => [
|
|
16206
16221
|
"connected",
|
|
16207
16222
|
"disconnected",
|
|
16208
16223
|
"failed"
|
|
@@ -16215,7 +16230,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16215
16230
|
if (event.member_id) this.setSelfIdIfNull(event.member_id);
|
|
16216
16231
|
});
|
|
16217
16232
|
this.subscribeTo(this.vertoMedia$, (event) => {
|
|
16218
|
-
logger$
|
|
16233
|
+
logger$14.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
|
|
16219
16234
|
this._signalingStatus$.next("ringing");
|
|
16220
16235
|
const { sdp, callID } = event;
|
|
16221
16236
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
@@ -16224,7 +16239,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16224
16239
|
});
|
|
16225
16240
|
});
|
|
16226
16241
|
this.subscribeTo(this.vertoAnswer$, (event) => {
|
|
16227
|
-
logger$
|
|
16242
|
+
logger$14.debug("[WebRTCManager] Received Verto answer event:", event);
|
|
16228
16243
|
this._signalingStatus$.next("connecting");
|
|
16229
16244
|
const { sdp, callID } = event;
|
|
16230
16245
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
@@ -16233,7 +16248,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16233
16248
|
});
|
|
16234
16249
|
});
|
|
16235
16250
|
this.subscribeTo(this.vertoMediaParams$, (event) => {
|
|
16236
|
-
logger$
|
|
16251
|
+
logger$14.debug("[WebRTCManager] Received Verto mediaParams event:", event);
|
|
16237
16252
|
const { mediaParams, callID } = event;
|
|
16238
16253
|
const rtcPeerConnController = this._rtcPeerConnectionsMap.get(callID);
|
|
16239
16254
|
const { audio, video } = mediaParams;
|
|
@@ -16247,13 +16262,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16247
16262
|
timestamp: Date.now()
|
|
16248
16263
|
});
|
|
16249
16264
|
} catch (error) {
|
|
16250
|
-
logger$
|
|
16265
|
+
logger$14.warn("[WebRTCManager] Error applying server-pushed media params:", error);
|
|
16251
16266
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16252
16267
|
}
|
|
16253
16268
|
})();
|
|
16254
16269
|
});
|
|
16255
16270
|
this.subscribeTo(this.vertoPing$, (vertoPing) => {
|
|
16256
|
-
this.attachManager.attach(this.
|
|
16271
|
+
this.attachManager.attach(this.buildAttachableCall());
|
|
16257
16272
|
this.sendVertoPong(vertoPing);
|
|
16258
16273
|
});
|
|
16259
16274
|
}
|
|
@@ -16269,13 +16284,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16269
16284
|
*/
|
|
16270
16285
|
setNodeIdIfNull(nodeId) {
|
|
16271
16286
|
if (!this._nodeId$.value && nodeId) {
|
|
16272
|
-
logger$
|
|
16287
|
+
logger$14.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
|
|
16273
16288
|
this._nodeId$.next(nodeId);
|
|
16274
16289
|
}
|
|
16275
16290
|
}
|
|
16276
16291
|
setSelfIdIfNull(selfId) {
|
|
16277
16292
|
if (!this._selfId$.value && selfId) {
|
|
16278
|
-
logger$
|
|
16293
|
+
logger$14.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
|
|
16279
16294
|
this._selfId$.next(selfId);
|
|
16280
16295
|
}
|
|
16281
16296
|
}
|
|
@@ -16284,7 +16299,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16284
16299
|
const vertoPongMessage = VertoPong({ ...vertoPing });
|
|
16285
16300
|
await this.executeVerto(vertoPongMessage);
|
|
16286
16301
|
} catch (error) {
|
|
16287
|
-
logger$
|
|
16302
|
+
logger$14.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:", error);
|
|
16288
16303
|
this.onError?.(new VertoPongError(error));
|
|
16289
16304
|
}
|
|
16290
16305
|
}
|
|
@@ -16294,7 +16309,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16294
16309
|
if (audio) await this.mainPeerConnection.updateSendersConstraints("audio", audio);
|
|
16295
16310
|
if (video) await this.mainPeerConnection.updateSendersConstraints("video", video);
|
|
16296
16311
|
} catch (error) {
|
|
16297
|
-
logger$
|
|
16312
|
+
logger$14.warn("[WebRTCManager] Error updating media constraints:", error);
|
|
16298
16313
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16299
16314
|
throw error;
|
|
16300
16315
|
}
|
|
@@ -16302,6 +16317,15 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16302
16317
|
get selfId() {
|
|
16303
16318
|
return this._selfId$.value;
|
|
16304
16319
|
}
|
|
16320
|
+
/** Build an AttachableCall from the current call state. */
|
|
16321
|
+
buildAttachableCall(idOverride) {
|
|
16322
|
+
return {
|
|
16323
|
+
nodeId: this.nodeId ?? void 0,
|
|
16324
|
+
id: idOverride ?? this.webRtcCallSession.id,
|
|
16325
|
+
to: this.webRtcCallSession.to,
|
|
16326
|
+
mediaDirections: this.webRtcCallSession.mediaDirections
|
|
16327
|
+
};
|
|
16328
|
+
}
|
|
16305
16329
|
/**
|
|
16306
16330
|
* Request a video keyframe via RTCP PLI/FIR.
|
|
16307
16331
|
*
|
|
@@ -16315,20 +16339,20 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16315
16339
|
try {
|
|
16316
16340
|
const pc = this.mainPeerConnection.peerConnection;
|
|
16317
16341
|
if (!pc) {
|
|
16318
|
-
logger$
|
|
16342
|
+
logger$14.warn("[WebRTCManager] No peer connection for keyframe request");
|
|
16319
16343
|
return;
|
|
16320
16344
|
}
|
|
16321
16345
|
const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
|
|
16322
16346
|
if (!videoReceiver) {
|
|
16323
|
-
logger$
|
|
16347
|
+
logger$14.warn("[WebRTCManager] No video receiver for keyframe request");
|
|
16324
16348
|
return;
|
|
16325
16349
|
}
|
|
16326
16350
|
if (typeof videoReceiver.requestKeyFrame === "function") {
|
|
16327
16351
|
videoReceiver.requestKeyFrame();
|
|
16328
|
-
logger$
|
|
16329
|
-
} else logger$
|
|
16352
|
+
logger$14.debug("[WebRTCManager] Keyframe requested via RTCRtpReceiver.requestKeyFrame()");
|
|
16353
|
+
} else logger$14.debug("[WebRTCManager] requestKeyFrame() not supported, skipping");
|
|
16330
16354
|
} catch (error) {
|
|
16331
|
-
logger$
|
|
16355
|
+
logger$14.warn("[WebRTCManager] Keyframe request failed (non-fatal):", error);
|
|
16332
16356
|
}
|
|
16333
16357
|
}
|
|
16334
16358
|
/**
|
|
@@ -16346,13 +16370,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16346
16370
|
try {
|
|
16347
16371
|
const controller = this.mainPeerConnection;
|
|
16348
16372
|
if (!controller.peerConnection) {
|
|
16349
|
-
logger$
|
|
16373
|
+
logger$14.warn("[WebRTCManager] No peer connection for ICE restart");
|
|
16350
16374
|
return;
|
|
16351
16375
|
}
|
|
16352
16376
|
await controller.triggerIceRestart(relayOnly);
|
|
16353
|
-
logger$
|
|
16377
|
+
logger$14.info(`[WebRTCManager] ICE restart initiated${relayOnly ? " (relay-only)" : ""}`);
|
|
16354
16378
|
} catch (error) {
|
|
16355
|
-
logger$
|
|
16379
|
+
logger$14.error("[WebRTCManager] ICE restart failed:", error);
|
|
16356
16380
|
throw error;
|
|
16357
16381
|
}
|
|
16358
16382
|
}
|
|
@@ -16370,13 +16394,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16370
16394
|
const entries = Array.from(this._rtcPeerConnectionsMap.entries());
|
|
16371
16395
|
for (const [id, controller] of entries) try {
|
|
16372
16396
|
if (!controller.peerConnection) {
|
|
16373
|
-
logger$
|
|
16397
|
+
logger$14.debug(`[WebRTCManager] No peer connection for leg ${id}, skipping ICE restart`);
|
|
16374
16398
|
continue;
|
|
16375
16399
|
}
|
|
16376
16400
|
await controller.triggerIceRestart(relayOnly);
|
|
16377
|
-
logger$
|
|
16401
|
+
logger$14.info(`[WebRTCManager] ICE restart initiated for leg ${id}${relayOnly ? " (relay-only)" : ""}`);
|
|
16378
16402
|
} catch (error) {
|
|
16379
|
-
logger$
|
|
16403
|
+
logger$14.warn(`[WebRTCManager] ICE restart failed for leg ${id}:`, error);
|
|
16380
16404
|
}
|
|
16381
16405
|
}
|
|
16382
16406
|
/**
|
|
@@ -16388,7 +16412,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16388
16412
|
requestKeyframeAll() {
|
|
16389
16413
|
for (const [id, controller] of this._rtcPeerConnectionsMap) {
|
|
16390
16414
|
if (controller.isScreenShare) {
|
|
16391
|
-
logger$
|
|
16415
|
+
logger$14.debug(`[WebRTCManager] Skipping keyframe for send-only screen share leg ${id}`);
|
|
16392
16416
|
continue;
|
|
16393
16417
|
}
|
|
16394
16418
|
try {
|
|
@@ -16398,33 +16422,33 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16398
16422
|
if (!videoReceiver) continue;
|
|
16399
16423
|
if (typeof videoReceiver.requestKeyFrame === "function") {
|
|
16400
16424
|
videoReceiver.requestKeyFrame();
|
|
16401
|
-
logger$
|
|
16425
|
+
logger$14.debug(`[WebRTCManager] Keyframe requested for leg ${id}`);
|
|
16402
16426
|
}
|
|
16403
16427
|
} catch (error) {
|
|
16404
|
-
logger$
|
|
16428
|
+
logger$14.warn(`[WebRTCManager] Keyframe request failed for leg ${id} (non-fatal):`, error);
|
|
16405
16429
|
}
|
|
16406
16430
|
}
|
|
16407
16431
|
}
|
|
16408
16432
|
get callJoinedEvent$() {
|
|
16409
|
-
return this.webRtcCallSession.callEvent$.pipe((0, import_cjs$
|
|
16433
|
+
return this.webRtcCallSession.callEvent$.pipe((0, import_cjs$13.filter)(isCallJoinedPayload), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16410
16434
|
}
|
|
16411
16435
|
get vertoMedia$() {
|
|
16412
|
-
return this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaInnerParams, "params"), (0, import_cjs$
|
|
16436
|
+
return this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16413
16437
|
}
|
|
16414
16438
|
get vertoAnswer$() {
|
|
16415
|
-
return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAnswerInnerParams, "params"), (0, import_cjs$
|
|
16439
|
+
return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAnswerInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16416
16440
|
}
|
|
16417
16441
|
get vertoMediaParams$() {
|
|
16418
|
-
return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$
|
|
16442
|
+
return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16419
16443
|
}
|
|
16420
16444
|
get vertoBye$() {
|
|
16421
|
-
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeMessage, "params"), (0, import_cjs$
|
|
16445
|
+
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeMessage, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16422
16446
|
}
|
|
16423
16447
|
get vertoAttach$() {
|
|
16424
|
-
return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$
|
|
16448
|
+
return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16425
16449
|
}
|
|
16426
16450
|
get vertoPing$() {
|
|
16427
|
-
return this.cachedObservable("vertoPing$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoPingInnerParams, "params"), (0, import_cjs$
|
|
16451
|
+
return this.cachedObservable("vertoPing$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoPingInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16428
16452
|
}
|
|
16429
16453
|
async executeVerto(message, optionals = {}) {
|
|
16430
16454
|
const webrtcVertoMessage = WebrtcVerto({
|
|
@@ -16449,7 +16473,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16449
16473
|
}
|
|
16450
16474
|
async sendLocalDescription(message, rtcPeerConnController) {
|
|
16451
16475
|
const vertoMethod = message.method;
|
|
16452
|
-
const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController,
|
|
16476
|
+
const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController, message);
|
|
16453
16477
|
try {
|
|
16454
16478
|
const response = await this.executeVerto(message, optionalsParams);
|
|
16455
16479
|
switch (vertoMethod) {
|
|
@@ -16462,8 +16486,9 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16462
16486
|
default:
|
|
16463
16487
|
}
|
|
16464
16488
|
} catch (error) {
|
|
16465
|
-
logger$
|
|
16489
|
+
logger$14.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
|
|
16466
16490
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16491
|
+
if (vertoMethod === "verto.modify") this.onModifyFailed?.();
|
|
16467
16492
|
}
|
|
16468
16493
|
}
|
|
16469
16494
|
async processModifyResponse(response, rtcPeerConnController) {
|
|
@@ -16476,7 +16501,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16476
16501
|
sdp
|
|
16477
16502
|
});
|
|
16478
16503
|
} catch (error) {
|
|
16479
|
-
logger$
|
|
16504
|
+
logger$14.warn("[WebRTCManager] Error processing modify response:", error);
|
|
16480
16505
|
const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
16481
16506
|
this.onError?.(modifyError);
|
|
16482
16507
|
}
|
|
@@ -16488,19 +16513,24 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16488
16513
|
this._nodeId$.next(getValueFrom(response, "result.node_id") ?? null);
|
|
16489
16514
|
const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
|
|
16490
16515
|
const callId = getValueFrom(response, "result.result.result.callID") ?? null;
|
|
16491
|
-
logger$
|
|
16516
|
+
logger$14.debug("[WebRTCManager] Verto invite response:", {
|
|
16492
16517
|
callId,
|
|
16493
16518
|
memberId,
|
|
16494
16519
|
response
|
|
16495
16520
|
});
|
|
16496
16521
|
this._selfId$.next(memberId);
|
|
16497
16522
|
rtcPeerConnController.setMemberId(memberId);
|
|
16498
|
-
if (callId)
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
logger$
|
|
16523
|
+
if (callId) {
|
|
16524
|
+
this.webRtcCallSession.addCallId(callId);
|
|
16525
|
+
this.attachManager.attach(this.buildAttachableCall(callId));
|
|
16526
|
+
} else logger$14.warn("[WebRTCManager] Cannot attach call, missing callId:", {
|
|
16527
|
+
nodeId: this.nodeId,
|
|
16528
|
+
callId
|
|
16529
|
+
});
|
|
16530
|
+
logger$14.info("[WebRTCManager] Verto invite successful");
|
|
16531
|
+
logger$14.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
|
|
16502
16532
|
} else {
|
|
16503
|
-
logger$
|
|
16533
|
+
logger$14.error("[WebRTCManager] Verto invite failed:", response);
|
|
16504
16534
|
const inviteError = response.error ? new JSONRPCError(response.error.code, response.error.message, response.error.data) : /* @__PURE__ */ new Error("Verto invite failed: unexpected response");
|
|
16505
16535
|
this.onError?.(inviteError);
|
|
16506
16536
|
}
|
|
@@ -16545,17 +16575,17 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16545
16575
|
if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
|
|
16546
16576
|
}
|
|
16547
16577
|
async handleInboundAnswer(rtcPeerConnController) {
|
|
16548
|
-
logger$
|
|
16549
|
-
const vertoByeOrAccepted = await (0, import_cjs$
|
|
16578
|
+
logger$14.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
|
|
16579
|
+
const vertoByeOrAccepted = await (0, import_cjs$13.firstValueFrom)((0, import_cjs$13.race)(this.vertoBye$, this.webRtcCallSession.answered$).pipe((0, import_cjs$13.takeUntil)(this.destroyed$))).catch(() => null);
|
|
16550
16580
|
if (vertoByeOrAccepted === null) {
|
|
16551
|
-
logger$
|
|
16581
|
+
logger$14.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
|
|
16552
16582
|
return;
|
|
16553
16583
|
}
|
|
16554
16584
|
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
16555
|
-
logger$
|
|
16585
|
+
logger$14.info("[WebRTCManager] Inbound call ended by remote before answer.");
|
|
16556
16586
|
this.callSession?.destroy();
|
|
16557
16587
|
} else if (!vertoByeOrAccepted) {
|
|
16558
|
-
logger$
|
|
16588
|
+
logger$14.info("[WebRTCManager] Inbound call rejected by user.");
|
|
16559
16589
|
try {
|
|
16560
16590
|
await this.bye("USER_BUSY");
|
|
16561
16591
|
} finally {
|
|
@@ -16563,21 +16593,22 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16563
16593
|
this.callSession?.destroy();
|
|
16564
16594
|
}
|
|
16565
16595
|
} else {
|
|
16566
|
-
logger$
|
|
16596
|
+
logger$14.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
|
|
16567
16597
|
const answerOptions = this.webRtcCallSession.answerMediaOptions;
|
|
16568
16598
|
try {
|
|
16569
16599
|
await rtcPeerConnController.acceptInbound(answerOptions);
|
|
16570
16600
|
} catch (error) {
|
|
16571
|
-
logger$
|
|
16601
|
+
logger$14.error("[WebRTCManager] Error creating inbound answer:", error);
|
|
16572
16602
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16573
16603
|
}
|
|
16574
16604
|
}
|
|
16575
16605
|
}
|
|
16576
16606
|
setupVertoAttachHandler() {
|
|
16577
16607
|
this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
|
|
16578
|
-
logger$
|
|
16608
|
+
logger$14.debug("[WebRTCManager] Received Verto attach event for existing call:", vertoAttach);
|
|
16579
16609
|
const { callID } = vertoAttach;
|
|
16580
16610
|
await this.attachManager.attach({
|
|
16611
|
+
nodeId: this.nodeId ?? void 0,
|
|
16581
16612
|
id: callID,
|
|
16582
16613
|
to: vertoAttach.callee_id_number,
|
|
16583
16614
|
mediaDirections: {
|
|
@@ -16588,12 +16619,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16588
16619
|
});
|
|
16589
16620
|
}
|
|
16590
16621
|
initObservables(rtcPeerConnController) {
|
|
16591
|
-
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$
|
|
16592
|
-
this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$
|
|
16593
|
-
this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$
|
|
16622
|
+
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$13.filter)((state) => state === "connected"), (0, import_cjs$13.map)(() => rtcPeerConnController.mediaDirections), (0, import_cjs$13.startWith)(rtcPeerConnController.mediaDirections), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16623
|
+
this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16624
|
+
this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16594
16625
|
}
|
|
16595
16626
|
setupLocalDescriptionHandler(rtcPeerConnController) {
|
|
16596
|
-
this.subscribeTo(rtcPeerConnController.localDescription$.pipe((0, import_cjs$
|
|
16627
|
+
this.subscribeTo(rtcPeerConnController.localDescription$.pipe((0, import_cjs$13.filter)((description) => description !== null), (0, import_cjs$13.takeUntil)(this.destroyed$)), (description) => {
|
|
16597
16628
|
const { type, sdp } = description;
|
|
16598
16629
|
const dialogParams = this.dialogParams(rtcPeerConnController);
|
|
16599
16630
|
const initial = !rtcPeerConnController.firstSDPExchangeCompleted;
|
|
@@ -16622,11 +16653,11 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16622
16653
|
setupVertoByeHandler() {
|
|
16623
16654
|
this.subscribeTo(this.vertoBye$, () => {
|
|
16624
16655
|
this._signalingStatus$.next("disconnected");
|
|
16625
|
-
this.attachManager.detach(this.
|
|
16656
|
+
this.attachManager.detach(this.buildAttachableCall());
|
|
16626
16657
|
this.callSession?.destroy();
|
|
16627
16658
|
});
|
|
16628
16659
|
}
|
|
16629
|
-
getSendLocalSDPOptionalParams(rtcPeerConnController,
|
|
16660
|
+
getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMessage) {
|
|
16630
16661
|
let subscribe = void 0;
|
|
16631
16662
|
if (!rtcPeerConnController.firstSDPExchangeCompleted) {
|
|
16632
16663
|
subscribe = [];
|
|
@@ -16634,7 +16665,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16634
16665
|
else if (rtcPeerConnController.isAdditionalDevice) subscribe.push(...PreferencesContainer.instance.inviteSubscribeAdditionalDevice);
|
|
16635
16666
|
else if (rtcPeerConnController.isScreenShare) subscribe.push(...PreferencesContainer.instance.inviteSubscribeScreenshare);
|
|
16636
16667
|
}
|
|
16637
|
-
const isInvite =
|
|
16668
|
+
const isInvite = isVertoInviteMessage(vertoMessage);
|
|
16638
16669
|
const isReattach = isInvite && this.webRtcCallSession.options.reattach;
|
|
16639
16670
|
return {
|
|
16640
16671
|
callID: rtcPeerConnController.id,
|
|
@@ -16643,13 +16674,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16643
16674
|
};
|
|
16644
16675
|
}
|
|
16645
16676
|
async sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnectionController) {
|
|
16646
|
-
logger$
|
|
16647
|
-
const vertoByeOrAccepted = await (0, import_cjs$
|
|
16677
|
+
logger$14.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");
|
|
16678
|
+
const vertoByeOrAccepted = await (0, import_cjs$13.firstValueFrom)((0, import_cjs$13.race)(this.vertoBye$, this.webRtcCallSession.answered$));
|
|
16648
16679
|
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
16649
|
-
logger$
|
|
16680
|
+
logger$14.info("[WebRTCManager] Call ended before answer was sent.");
|
|
16650
16681
|
this.callSession?.destroy();
|
|
16651
16682
|
} else if (!vertoByeOrAccepted) {
|
|
16652
|
-
logger$
|
|
16683
|
+
logger$14.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
|
|
16653
16684
|
try {
|
|
16654
16685
|
await this.bye("USER_BUSY");
|
|
16655
16686
|
} finally {
|
|
@@ -16657,14 +16688,14 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16657
16688
|
this.callSession?.destroy();
|
|
16658
16689
|
}
|
|
16659
16690
|
} else {
|
|
16660
|
-
logger$
|
|
16691
|
+
logger$14.debug("[WebRTCManager] Call accepted, sending answer");
|
|
16661
16692
|
try {
|
|
16662
16693
|
this._signalingStatus$.next("connecting");
|
|
16663
16694
|
await this.sendLocalDescription(vertoMessageRequest, rtcPeerConnectionController);
|
|
16664
16695
|
await rtcPeerConnectionController.updateAnswerStatus({ status: "sent" });
|
|
16665
|
-
await this.attachManager.attach(this.
|
|
16696
|
+
await this.attachManager.attach(this.buildAttachableCall());
|
|
16666
16697
|
} catch (error) {
|
|
16667
|
-
logger$
|
|
16698
|
+
logger$14.error("[WebRTCManager] Error sending Verto answer:", error);
|
|
16668
16699
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16669
16700
|
await rtcPeerConnectionController.updateAnswerStatus({ status: "failed" });
|
|
16670
16701
|
}
|
|
@@ -16753,12 +16784,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16753
16784
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
16754
16785
|
this.onError?.(error);
|
|
16755
16786
|
});
|
|
16756
|
-
await (0, import_cjs$
|
|
16787
|
+
await (0, import_cjs$13.firstValueFrom)(rtcPeerConnController.connectionState$.pipe((0, import_cjs$13.filter)((state) => state === "connected"), (0, import_cjs$13.take)(1), (0, import_cjs$13.timeout)(this._screenShareTimeoutMs)));
|
|
16757
16788
|
this._screenShareStatus$.next("started");
|
|
16758
|
-
logger$
|
|
16789
|
+
logger$14.info("[WebRTCManager] Screen share started successfully.");
|
|
16759
16790
|
return rtcPeerConnController.id;
|
|
16760
16791
|
} catch (error) {
|
|
16761
|
-
logger$
|
|
16792
|
+
logger$14.warn("[WebRTCManager] Error initializing additional peer connection:", error);
|
|
16762
16793
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16763
16794
|
if (rtcPeerConnController) rtcPeerConnController.destroy();
|
|
16764
16795
|
this._screenShareStatus$.next("none");
|
|
@@ -16777,9 +16808,9 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16777
16808
|
if (removeTrack) return this.mainPeerConnection.stopTrackSender(removeTrack, { updateTransceiverDirection: true });
|
|
16778
16809
|
}
|
|
16779
16810
|
async removeScreenMedia() {
|
|
16780
|
-
if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$
|
|
16811
|
+
if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$14.warn("[WebRTCManager] No active screen share to stop.");
|
|
16781
16812
|
if (!this._screenShareId) {
|
|
16782
|
-
logger$
|
|
16813
|
+
logger$14.debug("[WebRTCManager] No screen share peer connection found.");
|
|
16783
16814
|
return;
|
|
16784
16815
|
}
|
|
16785
16816
|
this._screenShareStatus$.next("stopping");
|
|
@@ -16808,12 +16839,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16808
16839
|
dialogParams: this.dialogParams(rtcPeerConnController)
|
|
16809
16840
|
}));
|
|
16810
16841
|
} catch (error) {
|
|
16811
|
-
logger$
|
|
16842
|
+
logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:", error);
|
|
16812
16843
|
throw error;
|
|
16813
16844
|
}
|
|
16814
16845
|
}
|
|
16815
16846
|
async bye(cause) {
|
|
16816
|
-
this.attachManager.detach(this.
|
|
16847
|
+
this.attachManager.detach(this.buildAttachableCall());
|
|
16817
16848
|
const rtcPeerConnController = this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id);
|
|
16818
16849
|
if (rtcPeerConnController) await this.executeVertoBye(rtcPeerConnController, cause);
|
|
16819
16850
|
}
|
|
@@ -16826,7 +16857,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16826
16857
|
try {
|
|
16827
16858
|
await this.executeVerto(vertoInfoMessage);
|
|
16828
16859
|
} catch (error) {
|
|
16829
|
-
logger$
|
|
16860
|
+
logger$14.warn("[WebRTCManager] Error sending DTMF digits:", error);
|
|
16830
16861
|
throw error;
|
|
16831
16862
|
}
|
|
16832
16863
|
}
|
|
@@ -16837,10 +16868,10 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16837
16868
|
action: "transfer"
|
|
16838
16869
|
});
|
|
16839
16870
|
try {
|
|
16840
|
-
logger$
|
|
16871
|
+
logger$14.debug("[WebRTCManager] Transferring call with options:", options);
|
|
16841
16872
|
await this.executeVerto(message);
|
|
16842
16873
|
} catch (error) {
|
|
16843
|
-
logger$
|
|
16874
|
+
logger$14.error("[WebRTCManager] Error transferring call:", error);
|
|
16844
16875
|
throw error;
|
|
16845
16876
|
}
|
|
16846
16877
|
}
|
|
@@ -16856,8 +16887,8 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16856
16887
|
|
|
16857
16888
|
//#endregion
|
|
16858
16889
|
//#region src/controllers/RTCStatsMonitor.ts
|
|
16859
|
-
var import_cjs$
|
|
16860
|
-
const logger$
|
|
16890
|
+
var import_cjs$12 = require_cjs();
|
|
16891
|
+
const logger$13 = getLogger();
|
|
16861
16892
|
const DEFAULT_POLLING_INTERVAL_MS = 1e3;
|
|
16862
16893
|
const DEFAULT_BASELINE_SAMPLES = 10;
|
|
16863
16894
|
const DEFAULT_NO_AUDIO_PACKET_THRESHOLD_MS = 2e3;
|
|
@@ -16919,7 +16950,7 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16919
16950
|
}
|
|
16920
16951
|
/** Simple boolean health indicator. */
|
|
16921
16952
|
get isNetworkHealthy$() {
|
|
16922
|
-
return this.cachedObservable("isNetworkHealthy$", () => this._networkIssues$.pipe((0, import_cjs$
|
|
16953
|
+
return this.cachedObservable("isNetworkHealthy$", () => this._networkIssues$.pipe((0, import_cjs$12.map)((issues) => issues.length === 0), (0, import_cjs$12.distinctUntilChanged)(), (0, import_cjs$12.takeUntil)(this.destroyed$)));
|
|
16923
16954
|
}
|
|
16924
16955
|
/** Whether the network is currently healthy. */
|
|
16925
16956
|
get isNetworkHealthy() {
|
|
@@ -16935,7 +16966,7 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16935
16966
|
}
|
|
16936
16967
|
/** Emits individual critical issues for the recovery pipeline. */
|
|
16937
16968
|
get criticalIssue$() {
|
|
16938
|
-
return this.cachedObservable("criticalIssue$", () => this._networkIssues$.pipe((0, import_cjs$
|
|
16969
|
+
return this.cachedObservable("criticalIssue$", () => this._networkIssues$.pipe((0, import_cjs$12.mergeMap)((issues) => (0, import_cjs$12.from)(issues.filter((i) => i.severity === "critical"))), (0, import_cjs$12.takeUntil)(this.destroyed$)));
|
|
16939
16970
|
}
|
|
16940
16971
|
/** Emits each raw stats sample extracted from the peer connection. */
|
|
16941
16972
|
get sample$() {
|
|
@@ -16947,32 +16978,32 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16947
16978
|
const now = Date.now();
|
|
16948
16979
|
this.lastAudioPacketChangeTime = now;
|
|
16949
16980
|
this.lastVideoPacketChangeTime = now;
|
|
16950
|
-
logger$
|
|
16951
|
-
this.subscribeTo((0, import_cjs$
|
|
16952
|
-
logger$
|
|
16953
|
-
return import_cjs$
|
|
16954
|
-
}))), (0, import_cjs$
|
|
16955
|
-
this.subscribeTo(this._sample$.pipe((0, import_cjs$
|
|
16981
|
+
logger$13.debug("[RTCStatsMonitor] Starting stats monitoring");
|
|
16982
|
+
this.subscribeTo((0, import_cjs$12.interval)(this.pollingIntervalMs).pipe((0, import_cjs$12.filter)(() => this.running), (0, import_cjs$12.switchMap)(() => (0, import_cjs$12.from)(this.peerConnection.getStats()).pipe((0, import_cjs$12.catchError)((err) => {
|
|
16983
|
+
logger$13.warn("[RTCStatsMonitor] Failed to get stats:", err);
|
|
16984
|
+
return import_cjs$12.EMPTY;
|
|
16985
|
+
}))), (0, import_cjs$12.filter)(() => this.running), (0, import_cjs$12.map)((report) => this.extractSample(report))), (sample$1) => this._sample$.next(sample$1));
|
|
16986
|
+
this.subscribeTo(this._sample$.pipe((0, import_cjs$12.take)(this.baselineSampleCount), (0, import_cjs$12.toArray)(), (0, import_cjs$12.map)((samples) => ({
|
|
16956
16987
|
rtt: samples.reduce((s, b) => s + b.roundTripTime, 0) / samples.length,
|
|
16957
16988
|
jitter: samples.reduce((s, b) => s + b.audioJitter, 0) / samples.length,
|
|
16958
16989
|
ready: true
|
|
16959
16990
|
}))), (baseline) => {
|
|
16960
|
-
logger$
|
|
16991
|
+
logger$13.debug(`[RTCStatsMonitor] Baseline established: rtt=${baseline.rtt.toFixed(1)}ms, jitter=${baseline.jitter.toFixed(1)}ms`);
|
|
16961
16992
|
this._baseline$.next(baseline);
|
|
16962
16993
|
});
|
|
16963
|
-
this.subscribeTo(this._sample$.pipe((0, import_cjs$
|
|
16994
|
+
this.subscribeTo(this._sample$.pipe((0, import_cjs$12.scan)((acc, sample$1) => ({
|
|
16964
16995
|
prev: acc.current,
|
|
16965
16996
|
current: sample$1
|
|
16966
16997
|
}), {
|
|
16967
16998
|
prev: null,
|
|
16968
16999
|
current: null
|
|
16969
|
-
}), (0, import_cjs$
|
|
17000
|
+
}), (0, import_cjs$12.filter)((pair) => pair.current !== null)), ({ prev, current }) => {
|
|
16970
17001
|
const now$1 = current.timestamp;
|
|
16971
17002
|
this.updatePacketTracking(current, now$1);
|
|
16972
17003
|
const issues = this.detectIssues(current, prev, now$1);
|
|
16973
17004
|
this._networkIssues$.next(issues);
|
|
16974
17005
|
});
|
|
16975
|
-
this.subscribeTo(this._sample$.pipe((0, import_cjs$
|
|
17006
|
+
this.subscribeTo(this._sample$.pipe((0, import_cjs$12.scan)((history, sample$1) => {
|
|
16976
17007
|
const cutoff = sample$1.timestamp - this.historyWindowSeconds * 1e3;
|
|
16977
17008
|
const metrics = {
|
|
16978
17009
|
timestamp: sample$1.timestamp,
|
|
@@ -16994,10 +17025,10 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16994
17025
|
stop() {
|
|
16995
17026
|
if (!this.running) return;
|
|
16996
17027
|
this.running = false;
|
|
16997
|
-
logger$
|
|
17028
|
+
logger$13.debug("[RTCStatsMonitor] Stopping stats monitoring");
|
|
16998
17029
|
}
|
|
16999
17030
|
destroy() {
|
|
17000
|
-
logger$
|
|
17031
|
+
logger$13.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor");
|
|
17001
17032
|
this.stop();
|
|
17002
17033
|
super.destroy();
|
|
17003
17034
|
}
|
|
@@ -17125,8 +17156,8 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
17125
17156
|
|
|
17126
17157
|
//#endregion
|
|
17127
17158
|
//#region src/managers/CallRecoveryManager.ts
|
|
17128
|
-
var import_cjs$
|
|
17129
|
-
const logger$
|
|
17159
|
+
var import_cjs$11 = require_cjs();
|
|
17160
|
+
const logger$12 = getLogger();
|
|
17130
17161
|
const DEFAULT_DEBOUNCE_TIME_MS = 2e3;
|
|
17131
17162
|
const DEFAULT_COOLDOWN_MS = 1e4;
|
|
17132
17163
|
const DEFAULT_ICE_GRACE_PERIOD_MS = 3e3;
|
|
@@ -17162,7 +17193,7 @@ const DEGRADATION_ONLY_ISSUES = new Set([
|
|
|
17162
17193
|
* A state machine tracks the pipeline: IDLE -> DEBOUNCING -> RECOVERING -> COOLDOWN.
|
|
17163
17194
|
*/
|
|
17164
17195
|
var CallRecoveryManager = class extends Destroyable {
|
|
17165
|
-
constructor(callbacks, config = {}) {
|
|
17196
|
+
constructor(callbacks, inputs, config = {}) {
|
|
17166
17197
|
super();
|
|
17167
17198
|
this._recoveryState$ = this.createBehaviorSubject("idle");
|
|
17168
17199
|
this._recoveryEvent$ = this.createSubject();
|
|
@@ -17176,6 +17207,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17176
17207
|
this._cooldownUntil = 0;
|
|
17177
17208
|
this._pipelineStop$ = this.createSubject();
|
|
17178
17209
|
this._callbacks = callbacks;
|
|
17210
|
+
this._inputs = inputs;
|
|
17179
17211
|
this._config = {
|
|
17180
17212
|
debounceTimeMs: config.debounceTimeMs ?? DEFAULT_DEBOUNCE_TIME_MS,
|
|
17181
17213
|
cooldownMs: config.cooldownMs ?? DEFAULT_COOLDOWN_MS,
|
|
@@ -17195,16 +17227,16 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17195
17227
|
this.initDegradationRecoveryPipeline();
|
|
17196
17228
|
}
|
|
17197
17229
|
get recoveryState$() {
|
|
17198
|
-
return this._recoveryState$.asObservable().pipe((0, import_cjs$
|
|
17230
|
+
return this._recoveryState$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
|
|
17199
17231
|
}
|
|
17200
17232
|
get recoveryState() {
|
|
17201
17233
|
return this._recoveryState$.value;
|
|
17202
17234
|
}
|
|
17203
17235
|
get recoveryEvent$() {
|
|
17204
|
-
return this._recoveryEvent$.asObservable().pipe((0, import_cjs$
|
|
17236
|
+
return this._recoveryEvent$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
|
|
17205
17237
|
}
|
|
17206
17238
|
get bandwidthConstrained$() {
|
|
17207
|
-
return this._bandwidthConstrained$.asObservable().pipe((0, import_cjs$
|
|
17239
|
+
return this._bandwidthConstrained$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
|
|
17208
17240
|
}
|
|
17209
17241
|
get bandwidthConstrained() {
|
|
17210
17242
|
return this._bandwidthConstrained$.value;
|
|
@@ -17222,10 +17254,10 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17222
17254
|
*/
|
|
17223
17255
|
async requestIceRestart() {
|
|
17224
17256
|
if (this._recoveryState$.value === "recovering") {
|
|
17225
|
-
logger$
|
|
17257
|
+
logger$12.info("CallRecoveryManager: manual ICE restart skipped — recovery already in progress");
|
|
17226
17258
|
return;
|
|
17227
17259
|
}
|
|
17228
|
-
logger$
|
|
17260
|
+
logger$12.info("CallRecoveryManager: manual ICE restart requested");
|
|
17229
17261
|
this.transitionTo("recovering");
|
|
17230
17262
|
await this.executeIceRestart(false);
|
|
17231
17263
|
this.startCooldown();
|
|
@@ -17241,7 +17273,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17241
17273
|
* WebSocket reconnect or call state recovers to 'connected'.
|
|
17242
17274
|
*/
|
|
17243
17275
|
reset() {
|
|
17244
|
-
logger$
|
|
17276
|
+
logger$12.info("CallRecoveryManager: resetting counters");
|
|
17245
17277
|
this._attemptCount = 0;
|
|
17246
17278
|
this._keyframeBurstCount = 0;
|
|
17247
17279
|
this._keyframeBurstStart = 0;
|
|
@@ -17250,6 +17282,22 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17250
17282
|
this.transitionTo("idle");
|
|
17251
17283
|
}
|
|
17252
17284
|
/**
|
|
17285
|
+
* Notify the recovery manager that a verto.modify (ICE restart SDP exchange)
|
|
17286
|
+
* failed at the signaling layer. Resets cooldown and pushes a new trigger
|
|
17287
|
+
* so recovery can re-attempt.
|
|
17288
|
+
*/
|
|
17289
|
+
notifyModifyFailed() {
|
|
17290
|
+
if (this._recoveryState$.value === "cooldown" || this._recoveryState$.value === "idle") {
|
|
17291
|
+
logger$12.info("CallRecoveryManager: verto.modify failed — re-entering recovery");
|
|
17292
|
+
this._cooldownUntil = 0;
|
|
17293
|
+
this.transitionTo("idle");
|
|
17294
|
+
this.pushTrigger({
|
|
17295
|
+
source: "network",
|
|
17296
|
+
detail: "modify_failed_during_recovery"
|
|
17297
|
+
});
|
|
17298
|
+
}
|
|
17299
|
+
}
|
|
17300
|
+
/**
|
|
17253
17301
|
* Feed bandwidth information for graceful degradation (Section 22).
|
|
17254
17302
|
* Call this from the stats monitor with current available outgoing bitrate.
|
|
17255
17303
|
*/
|
|
@@ -17264,7 +17312,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17264
17312
|
reason: `bandwidth ${bitrateKbps}kbps below threshold ${this._config.degradationBitrateThreshold}kbps`,
|
|
17265
17313
|
timestamp: Date.now()
|
|
17266
17314
|
});
|
|
17267
|
-
logger$
|
|
17315
|
+
logger$12.warn(`CallRecoveryManager: disabling video — bandwidth ${bitrateKbps}kbps < ${this._config.degradationBitrateThreshold}kbps`);
|
|
17268
17316
|
} else if (wasConstrained && bitrateKbps >= this._config.degradationRecoveryThreshold) {
|
|
17269
17317
|
this._bandwidthConstrained$.next(false);
|
|
17270
17318
|
this._callbacks.enableVideo();
|
|
@@ -17273,7 +17321,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17273
17321
|
reason: `bandwidth ${bitrateKbps}kbps recovered above ${this._config.degradationRecoveryThreshold}kbps`,
|
|
17274
17322
|
timestamp: Date.now()
|
|
17275
17323
|
});
|
|
17276
|
-
logger$
|
|
17324
|
+
logger$12.info(`CallRecoveryManager: restoring video — bandwidth ${bitrateKbps}kbps >= ${this._config.degradationRecoveryThreshold}kbps`);
|
|
17277
17325
|
}
|
|
17278
17326
|
}
|
|
17279
17327
|
/**
|
|
@@ -17292,14 +17340,14 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17292
17340
|
handleWebSocketReconnect() {
|
|
17293
17341
|
const pcState = this._callbacks.getPeerConnectionState();
|
|
17294
17342
|
if (pcState === "connected" || pcState === "completed") {
|
|
17295
|
-
logger$
|
|
17343
|
+
logger$12.info("CallRecoveryManager: signal-only reconnect — peer connection still alive");
|
|
17296
17344
|
this.emitEvent({
|
|
17297
17345
|
action: "signal_reconnect",
|
|
17298
17346
|
reason: "WebSocket reconnected, peer connection still connected",
|
|
17299
17347
|
timestamp: Date.now()
|
|
17300
17348
|
});
|
|
17301
17349
|
} else {
|
|
17302
|
-
logger$
|
|
17350
|
+
logger$12.info("CallRecoveryManager: full reconnect — peer connection also down");
|
|
17303
17351
|
this.emitEvent({
|
|
17304
17352
|
action: "full_reconnect",
|
|
17305
17353
|
reason: "WebSocket reconnected, peer connection not connected — ICE restart needed",
|
|
@@ -17318,12 +17366,12 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17318
17366
|
super.destroy();
|
|
17319
17367
|
}
|
|
17320
17368
|
initPipeline() {
|
|
17321
|
-
this.subscribeTo(this._trigger$.pipe((0, import_cjs$
|
|
17369
|
+
this.subscribeTo(this._trigger$.pipe((0, import_cjs$11.tap)(() => {
|
|
17322
17370
|
if (this._recoveryState$.value === "idle") this.transitionTo("debouncing");
|
|
17323
|
-
}), (0, import_cjs$
|
|
17371
|
+
}), (0, import_cjs$11.debounceTime)(this._config.debounceTimeMs), (0, import_cjs$11.withLatestFrom)(this._inputs.signalingReady$), (0, import_cjs$11.filter)(([, signalingReady]) => this.passGateChecks(signalingReady)), (0, import_cjs$11.map)(([trigger]) => trigger), (0, import_cjs$11.exhaustMap)((trigger) => this.executeTieredRecovery(trigger)), (0, import_cjs$11.takeUntil)((0, import_cjs$11.merge)(this._destroyed$, this._pipelineStop$))), {
|
|
17324
17372
|
next: () => {},
|
|
17325
17373
|
error: (err) => {
|
|
17326
|
-
logger$
|
|
17374
|
+
logger$12.error("CallRecoveryManager: pipeline error", err);
|
|
17327
17375
|
this.transitionTo("idle");
|
|
17328
17376
|
}
|
|
17329
17377
|
});
|
|
@@ -17339,10 +17387,10 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17339
17387
|
initDegradationRecoveryPipeline() {
|
|
17340
17388
|
if (!this._config.enableAutoDegradation) return;
|
|
17341
17389
|
const delayMs = this._config.packetLossRecoveryDelaySec * 1e3;
|
|
17342
|
-
this.subscribeTo((0, import_cjs$
|
|
17343
|
-
if (constrained && !hasPacketLoss) return (0, import_cjs$
|
|
17344
|
-
return import_cjs$
|
|
17345
|
-
}), (0, import_cjs$
|
|
17390
|
+
this.subscribeTo((0, import_cjs$11.combineLatest)([this._bandwidthConstrained$, this._hasPacketLoss$]).pipe((0, import_cjs$11.switchMap)(([constrained, hasPacketLoss]) => {
|
|
17391
|
+
if (constrained && !hasPacketLoss) return (0, import_cjs$11.timer)(delayMs);
|
|
17392
|
+
return import_cjs$11.EMPTY;
|
|
17393
|
+
}), (0, import_cjs$11.takeUntil)(this._destroyed$)), () => {
|
|
17346
17394
|
this._bandwidthConstrained$.next(false);
|
|
17347
17395
|
this._callbacks.enableVideo();
|
|
17348
17396
|
this.emitEvent({
|
|
@@ -17350,27 +17398,27 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17350
17398
|
reason: `no packet loss for ${this._config.packetLossRecoveryDelaySec}s — restoring video`,
|
|
17351
17399
|
timestamp: Date.now()
|
|
17352
17400
|
});
|
|
17353
|
-
logger$
|
|
17401
|
+
logger$12.info(`CallRecoveryManager: restoring video — no packet loss for ${this._config.packetLossRecoveryDelaySec}s`);
|
|
17354
17402
|
});
|
|
17355
17403
|
}
|
|
17356
|
-
passGateChecks() {
|
|
17404
|
+
passGateChecks(signalingReady) {
|
|
17357
17405
|
if (this._callbacks.isNegotiating()) {
|
|
17358
|
-
logger$
|
|
17406
|
+
logger$12.debug("CallRecoveryManager: gate blocked — negotiation in progress");
|
|
17359
17407
|
this.transitionTo("idle");
|
|
17360
17408
|
return false;
|
|
17361
17409
|
}
|
|
17362
|
-
if (!
|
|
17363
|
-
logger$
|
|
17410
|
+
if (!signalingReady) {
|
|
17411
|
+
logger$12.debug("CallRecoveryManager: gate blocked — signaling not ready");
|
|
17364
17412
|
this.transitionTo("idle");
|
|
17365
17413
|
return false;
|
|
17366
17414
|
}
|
|
17367
17415
|
if (!this._callbacks.isCallConnected()) {
|
|
17368
|
-
logger$
|
|
17416
|
+
logger$12.debug("CallRecoveryManager: gate blocked — call not connected");
|
|
17369
17417
|
this.transitionTo("idle");
|
|
17370
17418
|
return false;
|
|
17371
17419
|
}
|
|
17372
17420
|
if (this.isCooldownActive()) {
|
|
17373
|
-
logger$
|
|
17421
|
+
logger$12.debug("CallRecoveryManager: gate blocked — cooldown active");
|
|
17374
17422
|
this.transitionTo("cooldown");
|
|
17375
17423
|
return false;
|
|
17376
17424
|
}
|
|
@@ -17381,17 +17429,17 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17381
17429
|
}
|
|
17382
17430
|
executeTieredRecovery(trigger) {
|
|
17383
17431
|
this.transitionTo("recovering");
|
|
17384
|
-
logger$
|
|
17385
|
-
return (0, import_cjs$
|
|
17386
|
-
logger$
|
|
17432
|
+
logger$12.info(`CallRecoveryManager: starting tiered recovery — source=${trigger.source} detail=${trigger.detail}`);
|
|
17433
|
+
return (0, import_cjs$11.from)(this.runTiers(trigger)).pipe((0, import_cjs$11.tap)(() => this.startCooldown()), (0, import_cjs$11.catchError)((err) => {
|
|
17434
|
+
logger$12.error("CallRecoveryManager: tiered recovery failed", err);
|
|
17387
17435
|
this.startCooldown();
|
|
17388
|
-
return import_cjs$
|
|
17436
|
+
return import_cjs$11.EMPTY;
|
|
17389
17437
|
}));
|
|
17390
17438
|
}
|
|
17391
17439
|
async runTiers(trigger) {
|
|
17392
17440
|
this.executeKeyframe(trigger.detail);
|
|
17393
17441
|
if (trigger.issueType && DEGRADATION_ONLY_ISSUES.has(trigger.issueType)) {
|
|
17394
|
-
logger$
|
|
17442
|
+
logger$12.debug(`CallRecoveryManager: degradation-only issue (${trigger.issueType}) — Tier 1 only, skipping ICE restart`);
|
|
17395
17443
|
return;
|
|
17396
17444
|
}
|
|
17397
17445
|
if (this._attemptCount < this._config.maxAttempts) {
|
|
@@ -17408,13 +17456,13 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17408
17456
|
maxAttempts: this._config.maxAttempts,
|
|
17409
17457
|
timestamp: Date.now()
|
|
17410
17458
|
});
|
|
17411
|
-
logger$
|
|
17459
|
+
logger$12.warn("CallRecoveryManager: max recovery attempts reached");
|
|
17412
17460
|
}
|
|
17413
17461
|
}
|
|
17414
17462
|
executeKeyframe(reason) {
|
|
17415
17463
|
const now = Date.now();
|
|
17416
17464
|
if (now < this._keyframeCooldownUntil) {
|
|
17417
|
-
logger$
|
|
17465
|
+
logger$12.debug("CallRecoveryManager: keyframe request skipped — cooldown active");
|
|
17418
17466
|
return;
|
|
17419
17467
|
}
|
|
17420
17468
|
if (now - this._keyframeBurstStart > this._config.keyframeBurstWindowMs) {
|
|
@@ -17423,7 +17471,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17423
17471
|
}
|
|
17424
17472
|
if (this._keyframeBurstCount >= this._config.keyframeMaxBurst) {
|
|
17425
17473
|
this._keyframeCooldownUntil = now + this._config.keyframeCooldownMs;
|
|
17426
|
-
logger$
|
|
17474
|
+
logger$12.debug(`CallRecoveryManager: keyframe burst limit reached (${this._config.keyframeMaxBurst}), cooldown until ${this._keyframeCooldownUntil}`);
|
|
17427
17475
|
return;
|
|
17428
17476
|
}
|
|
17429
17477
|
this._keyframeBurstCount += 1;
|
|
@@ -17433,12 +17481,12 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17433
17481
|
reason,
|
|
17434
17482
|
timestamp: now
|
|
17435
17483
|
});
|
|
17436
|
-
logger$
|
|
17484
|
+
logger$12.debug(`CallRecoveryManager: keyframe requested (burst ${this._keyframeBurstCount}/${this._config.keyframeMaxBurst})`);
|
|
17437
17485
|
}
|
|
17438
17486
|
async executeIceRestart(relayOnly) {
|
|
17439
17487
|
this._attemptCount += 1;
|
|
17440
17488
|
const tier = relayOnly ? "Tier 3 (relay-only)" : "Tier 2 (standard)";
|
|
17441
|
-
logger$
|
|
17489
|
+
logger$12.info(`CallRecoveryManager: ${tier} ICE restart — attempt ${this._attemptCount}/${this._config.maxAttempts}`);
|
|
17442
17490
|
this.emitEvent({
|
|
17443
17491
|
action: "reinvite_started",
|
|
17444
17492
|
reason: `${tier} ICE restart`,
|
|
@@ -17455,7 +17503,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17455
17503
|
maxAttempts: this._config.maxAttempts,
|
|
17456
17504
|
timestamp: Date.now()
|
|
17457
17505
|
});
|
|
17458
|
-
logger$
|
|
17506
|
+
logger$12.info(`CallRecoveryManager: ${tier} ICE restart succeeded`);
|
|
17459
17507
|
this._attemptCount = 0;
|
|
17460
17508
|
return true;
|
|
17461
17509
|
}
|
|
@@ -17466,7 +17514,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17466
17514
|
maxAttempts: this._config.maxAttempts,
|
|
17467
17515
|
timestamp: Date.now()
|
|
17468
17516
|
});
|
|
17469
|
-
logger$
|
|
17517
|
+
logger$12.warn(`CallRecoveryManager: ${tier} ICE restart failed`);
|
|
17470
17518
|
return false;
|
|
17471
17519
|
} catch {
|
|
17472
17520
|
this.emitEvent({
|
|
@@ -17476,7 +17524,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17476
17524
|
maxAttempts: this._config.maxAttempts,
|
|
17477
17525
|
timestamp: Date.now()
|
|
17478
17526
|
});
|
|
17479
|
-
logger$
|
|
17527
|
+
logger$12.warn(`CallRecoveryManager: ${tier} ICE restart timed out`);
|
|
17480
17528
|
return false;
|
|
17481
17529
|
}
|
|
17482
17530
|
}
|
|
@@ -17497,7 +17545,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17497
17545
|
transitionTo(state) {
|
|
17498
17546
|
const prev = this._recoveryState$.value;
|
|
17499
17547
|
if (prev !== state) {
|
|
17500
|
-
logger$
|
|
17548
|
+
logger$12.debug(`CallRecoveryManager: state ${prev} -> ${state}`);
|
|
17501
17549
|
this._recoveryState$.next(state);
|
|
17502
17550
|
}
|
|
17503
17551
|
}
|
|
@@ -17505,7 +17553,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17505
17553
|
this._cooldownUntil = Date.now() + this._config.cooldownMs;
|
|
17506
17554
|
this.transitionTo("cooldown");
|
|
17507
17555
|
if (this._cooldownSubscription) this._cooldownSubscription.unsubscribe();
|
|
17508
|
-
this._cooldownSubscription = (0, import_cjs$
|
|
17556
|
+
this._cooldownSubscription = (0, import_cjs$11.timer)(this._config.cooldownMs).pipe((0, import_cjs$11.take)(1), (0, import_cjs$11.takeUntil)(this._destroyed$), (0, import_cjs$11.filter)(() => this._recoveryState$.value === "cooldown")).subscribe(() => this.transitionTo("idle"));
|
|
17509
17557
|
}
|
|
17510
17558
|
emitEvent(event) {
|
|
17511
17559
|
this._recoveryEvent$.next(event);
|
|
@@ -17599,8 +17647,8 @@ function mosToQualityLevel(mos) {
|
|
|
17599
17647
|
|
|
17600
17648
|
//#endregion
|
|
17601
17649
|
//#region src/core/entities/Call.ts
|
|
17602
|
-
var import_cjs$
|
|
17603
|
-
const logger$
|
|
17650
|
+
var import_cjs$10 = require_cjs();
|
|
17651
|
+
const logger$11 = getLogger();
|
|
17604
17652
|
/**
|
|
17605
17653
|
* Ratio between the critical and warning RTT spike multipliers.
|
|
17606
17654
|
* Warning threshold = baseline * warningMultiplier (default 3x)
|
|
@@ -17618,7 +17666,7 @@ const fromDestinationParams = (destination) => {
|
|
|
17618
17666
|
});
|
|
17619
17667
|
return params;
|
|
17620
17668
|
} catch (error) {
|
|
17621
|
-
logger$
|
|
17669
|
+
logger$11.warn(`Failed to parse destination URI: ${destination}`, error);
|
|
17622
17670
|
return {};
|
|
17623
17671
|
}
|
|
17624
17672
|
};
|
|
@@ -17674,10 +17722,13 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17674
17722
|
const { deviceController, networkChange$ } = initialization;
|
|
17675
17723
|
this._networkChange$ = networkChange$;
|
|
17676
17724
|
this.participantFactory = new ParticipantFactory(this.executeMethod.bind(this), this.vertoManager, deviceController);
|
|
17677
|
-
this.subscribeTo((0, import_cjs$
|
|
17725
|
+
this.subscribeTo((0, import_cjs$10.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$10.distinctUntilChanged)(), (0, import_cjs$10.takeUntil)(this._destroyed$)), (status) => {
|
|
17678
17726
|
this._lastMergedStatus = status;
|
|
17679
17727
|
if (status === "connected" && !this._statsMonitor) this.initResilienceSubsystems();
|
|
17680
|
-
else if (status === "disconnected"
|
|
17728
|
+
else if (status === "disconnected") {
|
|
17729
|
+
this._statsMonitor?.destroy();
|
|
17730
|
+
this._statsMonitor = void 0;
|
|
17731
|
+
} else if (status === "destroyed" || status === "failed") this.stopResilienceSubsystems();
|
|
17681
17732
|
});
|
|
17682
17733
|
}
|
|
17683
17734
|
/** Observable stream of errors from media, signaling, and peer connection layers. */
|
|
@@ -17696,13 +17747,17 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17696
17747
|
this.destroy();
|
|
17697
17748
|
}
|
|
17698
17749
|
}
|
|
17750
|
+
/** Notify the recovery manager that a verto.modify signaling exchange failed. */
|
|
17751
|
+
notifyModifyFailed() {
|
|
17752
|
+
this._recoveryManager?.notifyModifyFailed();
|
|
17753
|
+
}
|
|
17699
17754
|
/** Whether this call is `'inbound'` or `'outbound'`. */
|
|
17700
17755
|
get direction() {
|
|
17701
17756
|
return this.options.initOffer ? "inbound" : "outbound";
|
|
17702
17757
|
}
|
|
17703
17758
|
/** Observable of the address associated with this call. */
|
|
17704
17759
|
get address$() {
|
|
17705
|
-
return this.deferEmission((0, import_cjs$
|
|
17760
|
+
return this.deferEmission((0, import_cjs$10.from)([this.address])).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17706
17761
|
}
|
|
17707
17762
|
/** Display name of the caller. */
|
|
17708
17763
|
get fromName() {
|
|
@@ -17781,7 +17836,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17781
17836
|
}
|
|
17782
17837
|
/** Observable of layout layer positions for all participants. */
|
|
17783
17838
|
get layoutLayers$() {
|
|
17784
|
-
return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, import_cjs$
|
|
17839
|
+
return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17785
17840
|
}
|
|
17786
17841
|
/** Current snapshot of layout layers. */
|
|
17787
17842
|
get layoutLayers() {
|
|
@@ -17809,7 +17864,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17809
17864
|
if (isJSONRPCErrorResponse(response)) throw new JSONRPCError(parseInt(response.result?.code ?? "0"), `Error response from method ${method}: ${response.result?.code} ${response.result?.message}`, void 0, void 0, request.id);
|
|
17810
17865
|
return response;
|
|
17811
17866
|
} catch (error) {
|
|
17812
|
-
logger$
|
|
17867
|
+
logger$11.error(`[Call] Error executing method ${method} with params`, params, error);
|
|
17813
17868
|
throw error;
|
|
17814
17869
|
}
|
|
17815
17870
|
}
|
|
@@ -17836,45 +17891,45 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17836
17891
|
}
|
|
17837
17892
|
/** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
|
|
17838
17893
|
get status$() {
|
|
17839
|
-
return this.publicCachedObservable("status$", () => (0, import_cjs$
|
|
17894
|
+
return this.publicCachedObservable("status$", () => (0, import_cjs$10.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$10.distinctUntilChanged)(), (0, import_cjs$10.tap)((status) => {
|
|
17840
17895
|
this._lastMergedStatus = status;
|
|
17841
17896
|
})));
|
|
17842
17897
|
}
|
|
17843
17898
|
/** Observable of the participants list, emits on join/leave/update. */
|
|
17844
17899
|
get participants$() {
|
|
17845
|
-
return this.deferEmission(this.callEventsManager.participants$).pipe((0, import_cjs$
|
|
17900
|
+
return this.deferEmission(this.callEventsManager.participants$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17846
17901
|
}
|
|
17847
17902
|
/** Observable of the local (self) participant. */
|
|
17848
17903
|
get self$() {
|
|
17849
|
-
return this.deferEmission(this.callEventsManager.self$).pipe((0, import_cjs$
|
|
17904
|
+
return this.deferEmission(this.callEventsManager.self$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17850
17905
|
}
|
|
17851
17906
|
/** Observable indicating whether the call is being recorded. */
|
|
17852
17907
|
get recording$() {
|
|
17853
|
-
return this.deferEmission(this.callEventsManager.recording$).pipe((0, import_cjs$
|
|
17908
|
+
return this.deferEmission(this.callEventsManager.recording$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17854
17909
|
}
|
|
17855
17910
|
/** Observable indicating whether the call is being streamed. */
|
|
17856
17911
|
get streaming$() {
|
|
17857
|
-
return this.deferEmission(this.callEventsManager.streaming$).pipe((0, import_cjs$
|
|
17912
|
+
return this.deferEmission(this.callEventsManager.streaming$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17858
17913
|
}
|
|
17859
17914
|
/** Observable indicating whether raise-hand priority is active. */
|
|
17860
17915
|
get raiseHandPriority$() {
|
|
17861
|
-
return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, import_cjs$
|
|
17916
|
+
return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17862
17917
|
}
|
|
17863
17918
|
/** Observable indicating whether the call room is locked. */
|
|
17864
17919
|
get locked$() {
|
|
17865
|
-
return this.deferEmission(this.callEventsManager.locked$).pipe((0, import_cjs$
|
|
17920
|
+
return this.deferEmission(this.callEventsManager.locked$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17866
17921
|
}
|
|
17867
17922
|
/** Observable of custom metadata associated with the call. */
|
|
17868
17923
|
get meta$() {
|
|
17869
|
-
return this.deferEmission(this.callEventsManager.meta$).pipe((0, import_cjs$
|
|
17924
|
+
return this.deferEmission(this.callEventsManager.meta$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17870
17925
|
}
|
|
17871
17926
|
/** Observable of the call's capability flags. */
|
|
17872
17927
|
get capabilities$() {
|
|
17873
|
-
return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, import_cjs$
|
|
17928
|
+
return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17874
17929
|
}
|
|
17875
17930
|
/** Observable of the current layout name. */
|
|
17876
17931
|
get layout$() {
|
|
17877
|
-
return this.deferEmission(this.callEventsManager.layout$).pipe((0, import_cjs$
|
|
17932
|
+
return this.deferEmission(this.callEventsManager.layout$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17878
17933
|
}
|
|
17879
17934
|
/** Current call status. */
|
|
17880
17935
|
get status() {
|
|
@@ -17906,7 +17961,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17906
17961
|
}
|
|
17907
17962
|
/** Observable of available layout names. */
|
|
17908
17963
|
get layouts$() {
|
|
17909
|
-
return this.deferEmission(this.callEventsManager.layouts$).pipe((0, import_cjs$
|
|
17964
|
+
return this.deferEmission(this.callEventsManager.layouts$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17910
17965
|
}
|
|
17911
17966
|
/** Current snapshot of available layout names. */
|
|
17912
17967
|
get layouts() {
|
|
@@ -17914,7 +17969,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17914
17969
|
}
|
|
17915
17970
|
/** Observable of the local media stream (camera/microphone). */
|
|
17916
17971
|
get localStream$() {
|
|
17917
|
-
return this.deferEmission(this.vertoManager.localStream$).pipe((0, import_cjs$
|
|
17972
|
+
return this.deferEmission(this.vertoManager.localStream$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17918
17973
|
}
|
|
17919
17974
|
/** Current local media stream, or `null` if not available. */
|
|
17920
17975
|
get localStream() {
|
|
@@ -17922,7 +17977,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17922
17977
|
}
|
|
17923
17978
|
/** Observable of the remote media stream from the far end. */
|
|
17924
17979
|
get remoteStream$() {
|
|
17925
|
-
return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, import_cjs$
|
|
17980
|
+
return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17926
17981
|
}
|
|
17927
17982
|
/** Current remote media stream, or `null` if not available. */
|
|
17928
17983
|
get remoteStream() {
|
|
@@ -18012,9 +18067,9 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18012
18067
|
*/
|
|
18013
18068
|
initResilienceSubsystems() {
|
|
18014
18069
|
const pc = this.rtcPeerConnection;
|
|
18015
|
-
logger$
|
|
18070
|
+
logger$11.debug(`[Call] initResilienceSubsystems: pc=${pc ? "exists" : "undefined"}, connectionState=${pc?.connectionState}`);
|
|
18016
18071
|
if (!pc) {
|
|
18017
|
-
logger$
|
|
18072
|
+
logger$11.warn("[Call] No peer connection available, skipping resilience init");
|
|
18018
18073
|
return;
|
|
18019
18074
|
}
|
|
18020
18075
|
try {
|
|
@@ -18049,21 +18104,20 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18049
18104
|
disableVideo: () => {
|
|
18050
18105
|
try {
|
|
18051
18106
|
this.vertoManager.muteMainVideoInputDevice();
|
|
18052
|
-
logger$
|
|
18107
|
+
logger$11.debug("[Call] Recovery manager disabled video");
|
|
18053
18108
|
} catch {
|
|
18054
|
-
logger$
|
|
18109
|
+
logger$11.debug("[Call] Recovery manager failed to disable video");
|
|
18055
18110
|
}
|
|
18056
18111
|
},
|
|
18057
18112
|
enableVideo: () => {
|
|
18058
18113
|
this.vertoManager.unmuteMainVideoInputDevice().catch(() => {
|
|
18059
|
-
logger$
|
|
18114
|
+
logger$11.debug("[Call] Recovery manager failed to enable video");
|
|
18060
18115
|
});
|
|
18061
18116
|
},
|
|
18062
18117
|
isNegotiating: () => this.vertoManager.mainPeerConnection.isNegotiating,
|
|
18063
|
-
isWebSocketConnected: () => this._lastMergedStatus !== "disconnected",
|
|
18064
18118
|
isCallConnected: () => this._lastMergedStatus === "connected",
|
|
18065
18119
|
getPeerConnectionState: () => pc.connectionState
|
|
18066
|
-
}, {
|
|
18120
|
+
}, { signalingReady$: this.clientSession.authenticated$ }, {
|
|
18067
18121
|
debounceTimeMs: prefs.recoveryDebounceTime,
|
|
18068
18122
|
cooldownMs: prefs.recoveryCooldown,
|
|
18069
18123
|
iceGracePeriodMs: prefs.iceDisconnectedGracePeriod,
|
|
@@ -18106,6 +18160,15 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18106
18160
|
});
|
|
18107
18161
|
this.subscribeTo(this._recoveryManager.recoveryEvent$, (event) => {
|
|
18108
18162
|
this._recoveryEvent$.next(event);
|
|
18163
|
+
if (event.action === "max_attempts_reached") {
|
|
18164
|
+
logger$11.warn("[Call] All recovery attempts exhausted, terminating call");
|
|
18165
|
+
this.emitError({
|
|
18166
|
+
kind: "network",
|
|
18167
|
+
fatal: true,
|
|
18168
|
+
error: /* @__PURE__ */ new Error("Call recovery failed: all attempts exhausted"),
|
|
18169
|
+
callId: this.id
|
|
18170
|
+
});
|
|
18171
|
+
}
|
|
18109
18172
|
});
|
|
18110
18173
|
this.subscribeTo(this._recoveryManager.bandwidthConstrained$, (constrained) => {
|
|
18111
18174
|
this._bandwidthConstrained$.next(constrained);
|
|
@@ -18117,14 +18180,14 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18117
18180
|
});
|
|
18118
18181
|
else if (event.type === "online") this._recoveryManager?.handleWebSocketReconnect();
|
|
18119
18182
|
});
|
|
18120
|
-
this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$
|
|
18121
|
-
logger$
|
|
18183
|
+
this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$10.skip)(1), (0, import_cjs$10.filter)(Boolean)), () => {
|
|
18184
|
+
logger$11.debug("[Call] WebSocket reconnected — notifying recovery manager");
|
|
18122
18185
|
this._recoveryManager?.handleWebSocketReconnect();
|
|
18123
18186
|
});
|
|
18124
18187
|
this._statsMonitor.start();
|
|
18125
|
-
logger$
|
|
18188
|
+
logger$11.debug("[Call] Resilience subsystems initialized for call", this.id);
|
|
18126
18189
|
} catch (error) {
|
|
18127
|
-
logger$
|
|
18190
|
+
logger$11.warn("[Call] Failed to initialize resilience subsystems:", error);
|
|
18128
18191
|
}
|
|
18129
18192
|
}
|
|
18130
18193
|
/**
|
|
@@ -18146,14 +18209,14 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18146
18209
|
}
|
|
18147
18210
|
/** Observable of the current audio/video send/receive directions. */
|
|
18148
18211
|
get mediaDirections$() {
|
|
18149
|
-
return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, import_cjs$
|
|
18212
|
+
return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
18150
18213
|
}
|
|
18151
18214
|
/** Current audio/video send/receive directions. */
|
|
18152
18215
|
get mediaDirections() {
|
|
18153
18216
|
return this.vertoManager.mediaDirections;
|
|
18154
18217
|
}
|
|
18155
18218
|
get participantsId$() {
|
|
18156
|
-
return this.cachedObservable("participantsId$", () => this.participants$.pipe((0, import_cjs$
|
|
18219
|
+
return this.cachedObservable("participantsId$", () => this.participants$.pipe((0, import_cjs$10.map)((participants) => participants.map((participant) => participant.id))));
|
|
18157
18220
|
}
|
|
18158
18221
|
/**
|
|
18159
18222
|
* Executes a raw JSON-RPC request on the client session.
|
|
@@ -18186,48 +18249,48 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18186
18249
|
}
|
|
18187
18250
|
isCallSessionEvent(event) {
|
|
18188
18251
|
try {
|
|
18189
|
-
logger$
|
|
18252
|
+
logger$11.debug("[Call] Checking if event is for this call session:", event);
|
|
18190
18253
|
const callId = getValueFrom(event, "params.params.callID") ?? getValueFrom(event, "params.call_id");
|
|
18191
18254
|
const roomSessionId = getValueFrom(event, "params.room_session_id");
|
|
18192
|
-
logger$
|
|
18255
|
+
logger$11.debug(`[Call] Extracted session identifiers callID: ${callId} and roomSessionID: ${roomSessionId} from event:`);
|
|
18193
18256
|
return callId === this.id || !!callId && this.callEventsManager.isCallIdValid(callId) || !!roomSessionId && this.callEventsManager.isRoomSessionIdValid(roomSessionId);
|
|
18194
18257
|
} catch (error) {
|
|
18195
|
-
logger$
|
|
18258
|
+
logger$11.error("[Call] Error checking if event is for this call session:", error);
|
|
18196
18259
|
return false;
|
|
18197
18260
|
}
|
|
18198
18261
|
}
|
|
18199
18262
|
get callSessionEvents$() {
|
|
18200
|
-
return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$
|
|
18201
|
-
logger$
|
|
18202
|
-
}), (0, import_cjs$
|
|
18263
|
+
return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$10.filter)((event) => this.isCallSessionEvent(event)), (0, import_cjs$10.tap)((event) => {
|
|
18264
|
+
logger$11.debug("[Call] Received call session event:", event);
|
|
18265
|
+
}), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
|
|
18203
18266
|
}
|
|
18204
18267
|
/** Observable of call-updated events. */
|
|
18205
18268
|
get callUpdated$() {
|
|
18206
|
-
return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(filterAs(isCallUpdatedMetadata, "params"), (0, import_cjs$
|
|
18269
|
+
return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(filterAs(isCallUpdatedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18207
18270
|
}
|
|
18208
18271
|
/** Observable of member-joined events, emitted when a remote participant joins the call. */
|
|
18209
18272
|
get memberJoined$() {
|
|
18210
|
-
return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(filterAs(isMemberJoinedMetadata, "params"), (0, import_cjs$
|
|
18273
|
+
return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(filterAs(isMemberJoinedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18211
18274
|
}
|
|
18212
18275
|
/** Observable of member-left events, emitted when a participant leaves the call. */
|
|
18213
18276
|
get memberLeft$() {
|
|
18214
|
-
return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(filterAs(isMemberLeftMetadata, "params"), (0, import_cjs$
|
|
18277
|
+
return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(filterAs(isMemberLeftMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18215
18278
|
}
|
|
18216
18279
|
/** Observable of member-updated events (mute, volume, etc.). */
|
|
18217
18280
|
get memberUpdated$() {
|
|
18218
|
-
return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(filterAs(isMemberUpdatedMetadata, "params"), (0, import_cjs$
|
|
18281
|
+
return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(filterAs(isMemberUpdatedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18219
18282
|
}
|
|
18220
18283
|
/** Observable of member-talking events (speech start/stop). */
|
|
18221
18284
|
get memberTalking$() {
|
|
18222
|
-
return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(filterAs(isMemberTalkingMetadata, "params"), (0, import_cjs$
|
|
18285
|
+
return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(filterAs(isMemberTalkingMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18223
18286
|
}
|
|
18224
18287
|
/** Observable of call state-change events. */
|
|
18225
18288
|
get callStates$() {
|
|
18226
|
-
return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(filterAs(isCallStateMetadata, "params"), (0, import_cjs$
|
|
18289
|
+
return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(filterAs(isCallStateMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18227
18290
|
}
|
|
18228
18291
|
/** Observable of layout-changed events. */
|
|
18229
18292
|
get layoutUpdates$() {
|
|
18230
|
-
return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(filterAs(isLayoutChangedMetadata, "params"), (0, import_cjs$
|
|
18293
|
+
return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(filterAs(isLayoutChangedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18231
18294
|
}
|
|
18232
18295
|
/** Underlying `RTCPeerConnection`, for advanced use cases. */
|
|
18233
18296
|
get rtcPeerConnection() {
|
|
@@ -18235,7 +18298,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18235
18298
|
}
|
|
18236
18299
|
/** Observable of raw signaling events as plain objects. */
|
|
18237
18300
|
get signalingEvent$() {
|
|
18238
|
-
return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, import_cjs$
|
|
18301
|
+
return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, import_cjs$10.map)((event) => JSON.parse(JSON.stringify(event)))));
|
|
18239
18302
|
}
|
|
18240
18303
|
/**
|
|
18241
18304
|
* Subscribe to a custom signaling event type on this call.
|
|
@@ -18263,16 +18326,16 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18263
18326
|
subscribe(eventType) {
|
|
18264
18327
|
const cached = this._customSubscriptions.get(eventType);
|
|
18265
18328
|
if (cached) return cached;
|
|
18266
|
-
const filtered$ = this.callSessionEvents$.pipe((0, import_cjs$
|
|
18329
|
+
const filtered$ = this.callSessionEvents$.pipe((0, import_cjs$10.filter)((event) => event.event_type === eventType), (0, import_cjs$10.map)((event) => JSON.parse(JSON.stringify(event))), (0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
18267
18330
|
this._customSubscriptions.set(eventType, filtered$);
|
|
18268
18331
|
this._sendVertoSubscribe(eventType);
|
|
18269
18332
|
return filtered$;
|
|
18270
18333
|
}
|
|
18271
18334
|
get webrtcMessages$() {
|
|
18272
|
-
return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(filterAs(isWebrtcMessageMetadata, "params"), (0, import_cjs$
|
|
18335
|
+
return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(filterAs(isWebrtcMessageMetadata, "params"), (0, import_cjs$10.tap)((event) => logger$11.debug("[Call] Event is a WebRTC message event:", event)), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
|
|
18273
18336
|
}
|
|
18274
18337
|
get callEvent$() {
|
|
18275
|
-
return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(filterAs(isSignalwireCallMetadata, "params"), (0, import_cjs$
|
|
18338
|
+
return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(filterAs(isSignalwireCallMetadata, "params"), (0, import_cjs$10.tap)((event) => logger$11.debug("[Call] Event is a call event:", event)), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
|
|
18276
18339
|
}
|
|
18277
18340
|
get layoutEvent$() {
|
|
18278
18341
|
return this.cachedObservable("layoutEvent$", () => this.callEvent$.pipe(filterAs(isLayoutChangedMetadata, "params")));
|
|
@@ -18365,7 +18428,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18365
18428
|
*/
|
|
18366
18429
|
async setLayout(layout, positions) {
|
|
18367
18430
|
if (!this.layouts.includes(layout)) throw new InvalidParams(`Layout ${layout} is not available in the current call layouts: ${this.layouts.join(", ")}`);
|
|
18368
|
-
const selfId = await (0, import_cjs$
|
|
18431
|
+
const selfId = await (0, import_cjs$10.firstValueFrom)(this.selfId$.pipe((0, import_cjs$10.filter)((id) => id !== null)));
|
|
18369
18432
|
await this.executeMethod(selfId, "call.layout.set", {
|
|
18370
18433
|
layout,
|
|
18371
18434
|
positions
|
|
@@ -18406,10 +18469,10 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18406
18469
|
message
|
|
18407
18470
|
};
|
|
18408
18471
|
this.clientSession.execute(WebrtcVerto(params)).catch((error) => {
|
|
18409
|
-
logger$
|
|
18472
|
+
logger$11.warn(`[Call] verto.subscribe for '${eventType}' failed (non-fatal):`, error);
|
|
18410
18473
|
});
|
|
18411
18474
|
} catch (error) {
|
|
18412
|
-
logger$
|
|
18475
|
+
logger$11.warn(`[Call] Failed to send verto.subscribe for '${eventType}':`, error);
|
|
18413
18476
|
}
|
|
18414
18477
|
}
|
|
18415
18478
|
};
|
|
@@ -18431,6 +18494,7 @@ function inferCallErrorKind(error) {
|
|
|
18431
18494
|
function isFatalError(error) {
|
|
18432
18495
|
if (error instanceof VertoPongError) return false;
|
|
18433
18496
|
if (error instanceof MediaTrackError) return false;
|
|
18497
|
+
if (error instanceof RPCTimeoutError) return false;
|
|
18434
18498
|
return true;
|
|
18435
18499
|
}
|
|
18436
18500
|
/**
|
|
@@ -18462,6 +18526,9 @@ var CallFactory = class {
|
|
|
18462
18526
|
callId: callInstance.id
|
|
18463
18527
|
};
|
|
18464
18528
|
callInstance.emitError(callError);
|
|
18529
|
+
},
|
|
18530
|
+
onModifyFailed: () => {
|
|
18531
|
+
callInstance.notifyModifyFailed();
|
|
18465
18532
|
}
|
|
18466
18533
|
}),
|
|
18467
18534
|
callEventsManager: new CallEventsManager(callInstance)
|
|
@@ -18475,8 +18542,8 @@ var CallFactory = class {
|
|
|
18475
18542
|
|
|
18476
18543
|
//#endregion
|
|
18477
18544
|
//#region src/behaviors/Collection.ts
|
|
18478
|
-
var import_cjs$
|
|
18479
|
-
const logger$
|
|
18545
|
+
var import_cjs$9 = require_cjs();
|
|
18546
|
+
const logger$10 = getLogger();
|
|
18480
18547
|
var Fetcher = class {
|
|
18481
18548
|
constructor(endpoint, params, http) {
|
|
18482
18549
|
this.endpoint = endpoint;
|
|
@@ -18500,7 +18567,7 @@ var Fetcher = class {
|
|
|
18500
18567
|
this.hasMore = !!this.nextUrl;
|
|
18501
18568
|
return result.data.filter(this.filter).map(this.mapper);
|
|
18502
18569
|
}
|
|
18503
|
-
logger$
|
|
18570
|
+
logger$10.error("Failed to fetch entity");
|
|
18504
18571
|
return [];
|
|
18505
18572
|
}
|
|
18506
18573
|
async id(v) {
|
|
@@ -18541,10 +18608,10 @@ var EntityCollection = class extends Destroyable {
|
|
|
18541
18608
|
this.values$.next(Array.from(this.collectionData.values()));
|
|
18542
18609
|
};
|
|
18543
18610
|
this._hasMore$ = this.createBehaviorSubject(true);
|
|
18544
|
-
this._destroy$ = new import_cjs$
|
|
18611
|
+
this._destroy$ = new import_cjs$9.Subject();
|
|
18545
18612
|
this.updateSubscription = this.update$.subscribe(this.upsertData);
|
|
18546
18613
|
this.loading$.next(false);
|
|
18547
|
-
this.hasMore$ = (0, import_cjs$
|
|
18614
|
+
this.hasMore$ = (0, import_cjs$9.defer)(() => (0, import_cjs$9.from)(this.init())).pipe((0, import_cjs$9.switchMap)(() => this._hasMore$), (0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.shareReplay)(1), (0, import_cjs$9.takeUntil)(this._destroy$));
|
|
18548
18615
|
}
|
|
18549
18616
|
get loading() {
|
|
18550
18617
|
return this.loading$.value;
|
|
@@ -18553,7 +18620,7 @@ var EntityCollection = class extends Destroyable {
|
|
|
18553
18620
|
return this.fetchController.hasMore ?? true;
|
|
18554
18621
|
}
|
|
18555
18622
|
get updated$() {
|
|
18556
|
-
return this.cachedObservable("updated$", () => this.loading$.pipe((0, import_cjs$
|
|
18623
|
+
return this.cachedObservable("updated$", () => this.loading$.pipe((0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.skip)(1), (0, import_cjs$9.filter)((loading) => !loading), (0, import_cjs$9.map)(() => void 0), (0, import_cjs$9.takeUntil)(this._destroy$)));
|
|
18557
18624
|
}
|
|
18558
18625
|
get values() {
|
|
18559
18626
|
return Array.from(this.collectionData.values());
|
|
@@ -18572,7 +18639,7 @@ var EntityCollection = class extends Destroyable {
|
|
|
18572
18639
|
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
18573
18640
|
this.loading$.next(false);
|
|
18574
18641
|
} catch (error) {
|
|
18575
|
-
logger$
|
|
18642
|
+
logger$10.error(`Failed to fetch initial collection data`, error);
|
|
18576
18643
|
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
18577
18644
|
this.loading$.next(false);
|
|
18578
18645
|
this.onError?.(new CollectionFetchError("fetchMore", error));
|
|
@@ -18586,14 +18653,14 @@ var EntityCollection = class extends Destroyable {
|
|
|
18586
18653
|
if (data) this.upsertData(data);
|
|
18587
18654
|
return data;
|
|
18588
18655
|
} catch (error) {
|
|
18589
|
-
logger$
|
|
18656
|
+
logger$10.error(`Failed to fetch data for (${String(key)}:${String(value)}) :`, error);
|
|
18590
18657
|
this.loading$.next(false);
|
|
18591
18658
|
this.onError?.(new CollectionFetchError(`tryFetch(${String(key)})`, error));
|
|
18592
18659
|
}
|
|
18593
18660
|
}
|
|
18594
18661
|
get$(id) {
|
|
18595
18662
|
if (!this.observablesRegistry.has(id)) {
|
|
18596
|
-
this.observablesRegistry.set(id, new import_cjs$
|
|
18663
|
+
this.observablesRegistry.set(id, new import_cjs$9.ReplaySubject(1));
|
|
18597
18664
|
const data = this.collectionData.get(id);
|
|
18598
18665
|
if (data) this.observablesRegistry.get(id)?.next(data);
|
|
18599
18666
|
else this.tryFetch("id", id);
|
|
@@ -18617,9 +18684,9 @@ var EntityCollection = class extends Destroyable {
|
|
|
18617
18684
|
}
|
|
18618
18685
|
};
|
|
18619
18686
|
var EntityCollectionTransformed = class {
|
|
18620
|
-
constructor(originalCollection, filter$
|
|
18687
|
+
constructor(originalCollection, filter$17 = (i) => !!i, mapper = (item) => item) {
|
|
18621
18688
|
this.originalCollection = originalCollection;
|
|
18622
|
-
this.filter = filter$
|
|
18689
|
+
this.filter = filter$17;
|
|
18623
18690
|
this.mapper = mapper;
|
|
18624
18691
|
}
|
|
18625
18692
|
get loading$() {
|
|
@@ -18638,15 +18705,15 @@ var EntityCollectionTransformed = class {
|
|
|
18638
18705
|
return this.originalCollection.values.filter(this.filter).map(this.mapper);
|
|
18639
18706
|
}
|
|
18640
18707
|
get values$() {
|
|
18641
|
-
return this._values$ ??= this.originalCollection.values$.pipe((0, import_cjs$
|
|
18708
|
+
return this._values$ ??= this.originalCollection.values$.pipe((0, import_cjs$9.map)((values) => values.filter(this.filter).map(this.mapper)));
|
|
18642
18709
|
}
|
|
18643
18710
|
get$(id) {
|
|
18644
18711
|
const original$ = this.originalCollection.get$(id);
|
|
18645
|
-
return !original$ ? original$ : original$.pipe((0, import_cjs$
|
|
18712
|
+
return !original$ ? original$ : original$.pipe((0, import_cjs$9.pipe)((0, import_cjs$9.filter)(this.filter), (0, import_cjs$9.map)(this.mapper)));
|
|
18646
18713
|
}
|
|
18647
18714
|
async find$(key, value) {
|
|
18648
18715
|
const original$ = await this.originalCollection.find$(key, value);
|
|
18649
|
-
return !original$ ? original$ : original$.pipe((0, import_cjs$
|
|
18716
|
+
return !original$ ? original$ : original$.pipe((0, import_cjs$9.pipe)((0, import_cjs$9.filter)(this.filter), (0, import_cjs$9.map)(this.mapper)));
|
|
18650
18717
|
}
|
|
18651
18718
|
loadMore() {
|
|
18652
18719
|
this.originalCollection.loadMore();
|
|
@@ -18658,7 +18725,7 @@ var EntityCollectionTransformed = class {
|
|
|
18658
18725
|
|
|
18659
18726
|
//#endregion
|
|
18660
18727
|
//#region src/core/entities/Address.ts
|
|
18661
|
-
var import_cjs$
|
|
18728
|
+
var import_cjs$8 = require_cjs();
|
|
18662
18729
|
/**
|
|
18663
18730
|
* Represents a contact or room in the directory.
|
|
18664
18731
|
*
|
|
@@ -18676,8 +18743,8 @@ var Address = class extends Destroyable {
|
|
|
18676
18743
|
if (this._conversationMessages.hasMore) this._conversationMessages.loadMore();
|
|
18677
18744
|
return this._conversationMessages;
|
|
18678
18745
|
};
|
|
18679
|
-
this.textMessages$ = (0, import_cjs$
|
|
18680
|
-
this.history$ = (0, import_cjs$
|
|
18746
|
+
this.textMessages$ = (0, import_cjs$8.defer)(this.initConversationMessages).pipe((0, import_cjs$8.map)(() => this.textMessage), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.takeUntil)(this.destroyed$));
|
|
18747
|
+
this.history$ = (0, import_cjs$8.defer)(this.initConversationMessages).pipe((0, import_cjs$8.map)(() => this.history), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.takeUntil)(this.destroyed$));
|
|
18681
18748
|
this._state$ = this.createBehaviorSubject(null);
|
|
18682
18749
|
}
|
|
18683
18750
|
/** @internal */
|
|
@@ -18712,7 +18779,7 @@ var Address = class extends Destroyable {
|
|
|
18712
18779
|
}
|
|
18713
18780
|
/** Observable of the human-readable display name. */
|
|
18714
18781
|
get displayName$() {
|
|
18715
|
-
return this.cachedObservable("displayName$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18782
|
+
return this.cachedObservable("displayName$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.map)((state) => state.display_name), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18716
18783
|
}
|
|
18717
18784
|
/** Human-readable display name. */
|
|
18718
18785
|
get displayName() {
|
|
@@ -18721,7 +18788,7 @@ var Address = class extends Destroyable {
|
|
|
18721
18788
|
}
|
|
18722
18789
|
/** Observable of the preview image URL. */
|
|
18723
18790
|
get previewUrl$() {
|
|
18724
|
-
return this.cachedObservable("previewUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18791
|
+
return this.cachedObservable("previewUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.map)((state) => state.preview_url), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18725
18792
|
}
|
|
18726
18793
|
/** Preview image URL. */
|
|
18727
18794
|
get previewUrl() {
|
|
@@ -18730,7 +18797,7 @@ var Address = class extends Destroyable {
|
|
|
18730
18797
|
}
|
|
18731
18798
|
/** Observable of the cover image URL. */
|
|
18732
18799
|
get coverUrl$() {
|
|
18733
|
-
return this.cachedObservable("coverUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18800
|
+
return this.cachedObservable("coverUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.cover_url), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18734
18801
|
}
|
|
18735
18802
|
/** Cover image URL. */
|
|
18736
18803
|
get coverUrl() {
|
|
@@ -18739,7 +18806,7 @@ var Address = class extends Destroyable {
|
|
|
18739
18806
|
}
|
|
18740
18807
|
/** Observable of the underlying resource ID. */
|
|
18741
18808
|
get resourceId$() {
|
|
18742
|
-
return this.cachedObservable("resourceId$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18809
|
+
return this.cachedObservable("resourceId$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.resource_id), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18743
18810
|
}
|
|
18744
18811
|
/** Underlying resource ID. */
|
|
18745
18812
|
get resourceId() {
|
|
@@ -18748,7 +18815,7 @@ var Address = class extends Destroyable {
|
|
|
18748
18815
|
}
|
|
18749
18816
|
/** Observable of the resource type (e.g. `'room'`, `'subscriber'`). */
|
|
18750
18817
|
get type$() {
|
|
18751
|
-
return this.cachedObservable("type$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18818
|
+
return this.cachedObservable("type$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.type), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18752
18819
|
}
|
|
18753
18820
|
/** Resource type (e.g. `'room'`, `'subscriber'`). */
|
|
18754
18821
|
get type() {
|
|
@@ -18757,7 +18824,7 @@ var Address = class extends Destroyable {
|
|
|
18757
18824
|
}
|
|
18758
18825
|
/** Observable of available communication channels (audio, video, messaging). */
|
|
18759
18826
|
get channels$() {
|
|
18760
|
-
return this.cachedObservable("channels$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18827
|
+
return this.cachedObservable("channels$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.channels), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18761
18828
|
}
|
|
18762
18829
|
/** Available communication channels. */
|
|
18763
18830
|
get channels() {
|
|
@@ -18771,7 +18838,7 @@ var Address = class extends Destroyable {
|
|
|
18771
18838
|
}
|
|
18772
18839
|
/** Observable indicating whether the address (room) is locked. */
|
|
18773
18840
|
get locked$() {
|
|
18774
|
-
return this.cachedObservable("locked$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18841
|
+
return this.cachedObservable("locked$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.locked), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18775
18842
|
}
|
|
18776
18843
|
/**
|
|
18777
18844
|
* Sends a text message to this address.
|
|
@@ -18837,14 +18904,14 @@ var Address = class extends Destroyable {
|
|
|
18837
18904
|
|
|
18838
18905
|
//#endregion
|
|
18839
18906
|
//#region src/core/utils.ts
|
|
18840
|
-
var import_cjs$
|
|
18841
|
-
const logger$
|
|
18907
|
+
var import_cjs$7 = require_cjs();
|
|
18908
|
+
const logger$9 = getLogger();
|
|
18842
18909
|
const isRPCConnectResult = (e) => {
|
|
18843
|
-
logger$
|
|
18910
|
+
logger$9.debug("isRPCConnectResult check:", e);
|
|
18844
18911
|
if (!e || typeof e !== "object") return false;
|
|
18845
18912
|
const result = e;
|
|
18846
18913
|
const is = typeof result.identity === "string" && typeof result.protocol === "string" && typeof result.authorization === "object" && typeof result.authorization.jti === "string" && typeof result.authorization.project_id === "string" && typeof result.authorization.fabric_subscriber === "object";
|
|
18847
|
-
logger$
|
|
18914
|
+
logger$9.debug("isRPCConnectResult check result:", is);
|
|
18848
18915
|
return is;
|
|
18849
18916
|
};
|
|
18850
18917
|
var PendingRPC = class PendingRPC {
|
|
@@ -18853,7 +18920,7 @@ var PendingRPC = class PendingRPC {
|
|
|
18853
18920
|
}
|
|
18854
18921
|
constructor(request, responses$, options) {
|
|
18855
18922
|
this.id = v4_default();
|
|
18856
|
-
logger$
|
|
18923
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}: method:${request.method}] Creating PendingRPC`);
|
|
18857
18924
|
this.request = request;
|
|
18858
18925
|
const timeoutMs = options?.timeoutMs ?? PendingRPC.defaultTimeoutMs;
|
|
18859
18926
|
const signal = options?.signal;
|
|
@@ -18863,38 +18930,38 @@ var PendingRPC = class PendingRPC {
|
|
|
18863
18930
|
return;
|
|
18864
18931
|
}
|
|
18865
18932
|
let isSettled = false;
|
|
18866
|
-
const subscription = (0, import_cjs$
|
|
18867
|
-
const timer$
|
|
18933
|
+
const subscription = (0, import_cjs$7.race)(responses$.pipe((0, import_cjs$7.filter)((result) => result.id === request.id), (0, import_cjs$7.take)(1)), new import_cjs$7.Observable((subscriber) => {
|
|
18934
|
+
const timer$3 = setTimeout(() => {
|
|
18868
18935
|
subscriber.error(new RPCTimeoutError(request.id, timeoutMs));
|
|
18869
18936
|
}, timeoutMs);
|
|
18870
|
-
return () => clearTimeout(timer$
|
|
18871
|
-
}), signal ? new import_cjs$
|
|
18937
|
+
return () => clearTimeout(timer$3);
|
|
18938
|
+
}), signal ? new import_cjs$7.Observable((subscriber) => {
|
|
18872
18939
|
const abortHandler = () => {
|
|
18873
18940
|
subscriber.error(new DOMException("The operation was aborted", "AbortError"));
|
|
18874
18941
|
};
|
|
18875
18942
|
signal.addEventListener("abort", abortHandler);
|
|
18876
18943
|
return () => signal.removeEventListener("abort", abortHandler);
|
|
18877
|
-
}) : import_cjs$
|
|
18944
|
+
}) : import_cjs$7.NEVER).subscribe({
|
|
18878
18945
|
next: (response) => {
|
|
18879
18946
|
isSettled = true;
|
|
18880
18947
|
if (response.error) {
|
|
18881
18948
|
const rpcError = new JSONRPCError(response.error.code, response.error.message, response.error.data, void 0, request.id);
|
|
18882
|
-
logger$
|
|
18949
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
|
|
18883
18950
|
reject(rpcError);
|
|
18884
18951
|
} else {
|
|
18885
|
-
logger$
|
|
18952
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
18886
18953
|
resolve(response);
|
|
18887
18954
|
}
|
|
18888
18955
|
subscription.unsubscribe();
|
|
18889
18956
|
},
|
|
18890
18957
|
error: (error) => {
|
|
18891
|
-
logger$
|
|
18958
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with error:`, error);
|
|
18892
18959
|
isSettled = true;
|
|
18893
18960
|
reject(error);
|
|
18894
18961
|
subscription.unsubscribe();
|
|
18895
18962
|
},
|
|
18896
18963
|
complete: () => {
|
|
18897
|
-
logger$
|
|
18964
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
|
|
18898
18965
|
if (!isSettled) reject(new RPCTimeoutError(request.id, timeoutMs));
|
|
18899
18966
|
subscription.unsubscribe();
|
|
18900
18967
|
}
|
|
@@ -18914,8 +18981,8 @@ var PendingRPC = class PendingRPC {
|
|
|
18914
18981
|
|
|
18915
18982
|
//#endregion
|
|
18916
18983
|
//#region src/managers/ClientSessionManager.ts
|
|
18917
|
-
var import_cjs$
|
|
18918
|
-
const logger$
|
|
18984
|
+
var import_cjs$6 = require_cjs();
|
|
18985
|
+
const logger$8 = getLogger();
|
|
18919
18986
|
const getAddressSearchURI = (options) => {
|
|
18920
18987
|
const to = options.to?.split("?")[0];
|
|
18921
18988
|
const from$9 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
|
|
@@ -18950,10 +19017,10 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
18950
19017
|
this._iceServers$ = this.createBehaviorSubject([]);
|
|
18951
19018
|
attachManager.setSession(this);
|
|
18952
19019
|
this.callFactory = new CallFactory(this, deviceController, attachManager, webRTCApiProvider, networkChange$);
|
|
18953
|
-
this.initialized$ = (0, import_cjs$
|
|
19020
|
+
this.initialized$ = (0, import_cjs$6.defer)(() => (0, import_cjs$6.from)(this.init())).pipe((0, import_cjs$6.shareReplay)(1), (0, import_cjs$6.takeUntil)(this.destroyed$));
|
|
18954
19021
|
}
|
|
18955
19022
|
get incomingCalls$() {
|
|
18956
|
-
return this.cachedObservable("incomingCalls$", () => this.calls$.pipe((0, import_cjs$
|
|
19023
|
+
return this.cachedObservable("incomingCalls$", () => this.calls$.pipe((0, import_cjs$6.map)((calls) => calls.filter((call) => call.direction === "inbound"))));
|
|
18957
19024
|
}
|
|
18958
19025
|
get incomingCalls() {
|
|
18959
19026
|
return Object.values(this._calls$.value).filter((call) => call.direction === "inbound");
|
|
@@ -18965,7 +19032,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
18965
19032
|
return this._subscriberInfo$.value;
|
|
18966
19033
|
}
|
|
18967
19034
|
get calls$() {
|
|
18968
|
-
return this.cachedObservable("calls$", () => this._calls$.pipe((0, import_cjs$
|
|
19035
|
+
return this.cachedObservable("calls$", () => this._calls$.pipe((0, import_cjs$6.map)((calls) => Object.values(calls))));
|
|
18969
19036
|
}
|
|
18970
19037
|
get calls() {
|
|
18971
19038
|
return Object.values(this._calls$.value);
|
|
@@ -19009,7 +19076,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19009
19076
|
try {
|
|
19010
19077
|
return await this.transport.execute(request, options);
|
|
19011
19078
|
} catch (error) {
|
|
19012
|
-
logger$
|
|
19079
|
+
logger$8.debug("[Session] Execute Error", error);
|
|
19013
19080
|
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
19014
19081
|
throw error;
|
|
19015
19082
|
}
|
|
@@ -19023,40 +19090,40 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19023
19090
|
return true;
|
|
19024
19091
|
}
|
|
19025
19092
|
setupMessageHandlers() {
|
|
19026
|
-
logger$
|
|
19093
|
+
logger$8.debug("[Session] Setting up message handlers");
|
|
19027
19094
|
this.subscribeTo(this.authStateEvent$, async (authStateEvent) => {
|
|
19028
|
-
logger$
|
|
19095
|
+
logger$8.debug("[Session] Authorization state event received:", authStateEvent);
|
|
19029
19096
|
try {
|
|
19030
19097
|
await this.updateAuthorizationStateInStorage(authStateEvent.authorization_state);
|
|
19031
19098
|
} catch (error) {
|
|
19032
|
-
logger$
|
|
19099
|
+
logger$8.error("[Session] Failed to handle authorization state update:", error);
|
|
19033
19100
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19034
19101
|
}
|
|
19035
19102
|
});
|
|
19036
|
-
this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$
|
|
19037
|
-
logger$
|
|
19038
|
-
return (0, import_cjs$
|
|
19103
|
+
this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$6.filter)((status) => status === "connected"), (0, import_cjs$6.exhaustMap)(() => {
|
|
19104
|
+
logger$8.debug("[Session] Connection established, initiating authentication");
|
|
19105
|
+
return (0, import_cjs$6.from)(this.authenticate()).pipe((0, import_cjs$6.catchError)((error) => {
|
|
19039
19106
|
this.handleAuthenticationError(error).catch((err) => {
|
|
19040
|
-
logger$
|
|
19107
|
+
logger$8.error("[Session] Error handling authentication failure:", err);
|
|
19041
19108
|
});
|
|
19042
|
-
return import_cjs$
|
|
19109
|
+
return import_cjs$6.EMPTY;
|
|
19043
19110
|
}));
|
|
19044
19111
|
})), void 0);
|
|
19045
19112
|
this.subscribeTo(this.vertoInvite$, async (invite) => {
|
|
19046
|
-
logger$
|
|
19113
|
+
logger$8.debug("[Session] Verto invite received:", invite);
|
|
19047
19114
|
try {
|
|
19048
19115
|
await this.createInboundCall(invite);
|
|
19049
19116
|
} catch (error) {
|
|
19050
|
-
logger$
|
|
19117
|
+
logger$8.error("[Session] Error handling Verto invite:", error);
|
|
19051
19118
|
this._errors$.next(new VertoInviteHandlerError(error));
|
|
19052
19119
|
}
|
|
19053
19120
|
});
|
|
19054
19121
|
this.subscribeTo(this.vertoAttach$, async (attach) => {
|
|
19055
|
-
logger$
|
|
19122
|
+
logger$8.debug("[Session] Verto attach received:", attach);
|
|
19056
19123
|
try {
|
|
19057
19124
|
await this.handleVertoAttach(attach);
|
|
19058
19125
|
} catch (error) {
|
|
19059
|
-
logger$
|
|
19126
|
+
logger$8.error("[Session] Error handling Verto attach:", error);
|
|
19060
19127
|
this._errors$.next(new VertoAttachHandlerError(error));
|
|
19061
19128
|
}
|
|
19062
19129
|
});
|
|
@@ -19066,49 +19133,49 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19066
19133
|
const storedState = await this.storage.getItem(this.authorizationStateKey);
|
|
19067
19134
|
this.authorizationState$.next(storedState ?? void 0);
|
|
19068
19135
|
} catch (error) {
|
|
19069
|
-
logger$
|
|
19136
|
+
logger$8.error("Failed to retrieve authorization state from storage:", error);
|
|
19070
19137
|
this.authorizationState$.next(void 0);
|
|
19071
19138
|
}
|
|
19072
19139
|
}
|
|
19073
19140
|
async updateAuthorizationStateInStorage(authorizationState) {
|
|
19074
19141
|
if (!authorizationState) {
|
|
19075
|
-
logger$
|
|
19142
|
+
logger$8.debug("[Session] Removing authorization state from storage");
|
|
19076
19143
|
try {
|
|
19077
19144
|
await this.storage.removeItem(this.authorizationStateKey);
|
|
19078
19145
|
this.authorizationState$.next(void 0);
|
|
19079
19146
|
} catch (error) {
|
|
19080
|
-
logger$
|
|
19147
|
+
logger$8.error("Failed to remove authorization state from storage:", error);
|
|
19081
19148
|
throw error;
|
|
19082
19149
|
}
|
|
19083
19150
|
return;
|
|
19084
19151
|
}
|
|
19085
19152
|
try {
|
|
19086
|
-
logger$
|
|
19153
|
+
logger$8.debug("[Session] Updating authorization state in storage");
|
|
19087
19154
|
await this.storage.setItem(this.authorizationStateKey, authorizationState);
|
|
19088
19155
|
this.authorizationState$.next(authorizationState);
|
|
19089
19156
|
} catch (error) {
|
|
19090
|
-
logger$
|
|
19157
|
+
logger$8.error("Failed to retrieve authorization state from storage:", error);
|
|
19091
19158
|
throw error;
|
|
19092
19159
|
}
|
|
19093
19160
|
}
|
|
19094
19161
|
get authStateEvent$() {
|
|
19095
|
-
return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$
|
|
19096
|
-
logger$
|
|
19097
|
-
}), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$
|
|
19098
|
-
logger$
|
|
19162
|
+
return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$6.tap)((msg) => {
|
|
19163
|
+
logger$8.debug("[Session] Received incoming message:", msg);
|
|
19164
|
+
}), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$6.tap)((event) => {
|
|
19165
|
+
logger$8.debug("[Session] Authorization state event received:", event.authorization_state);
|
|
19099
19166
|
})));
|
|
19100
19167
|
}
|
|
19101
19168
|
get signalingEvent$() {
|
|
19102
|
-
return this.cachedObservable("signalingEvent$", () => this.transport.incomingEvent$.pipe(filterAs(isSignalwireRequest, "params"), (0, import_cjs$
|
|
19169
|
+
return this.cachedObservable("signalingEvent$", () => this.transport.incomingEvent$.pipe(filterAs(isSignalwireRequest, "params"), (0, import_cjs$6.share)()));
|
|
19103
19170
|
}
|
|
19104
19171
|
get vertoInvite$() {
|
|
19105
|
-
return this.cachedObservable("vertoInvite$", () => this.signalingEvent$.pipe((0, import_cjs$
|
|
19172
|
+
return this.cachedObservable("vertoInvite$", () => this.signalingEvent$.pipe((0, import_cjs$6.filter)(isWebrtcMessageMetadata), (0, import_cjs$6.filter)((event) => isVertoInviteMessage(event.params)), (0, import_cjs$6.map)((event) => ({
|
|
19106
19173
|
node_id: event.node_id,
|
|
19107
19174
|
...event.params.params
|
|
19108
19175
|
}))));
|
|
19109
19176
|
}
|
|
19110
19177
|
get vertoAttach$() {
|
|
19111
|
-
return this.cachedObservable("vertoAttach$", () => this.signalingEvent$.pipe((0, import_cjs$
|
|
19178
|
+
return this.cachedObservable("vertoAttach$", () => this.signalingEvent$.pipe((0, import_cjs$6.filter)(isWebrtcMessageMetadata), (0, import_cjs$6.filter)((event) => isVertoAttachMessage(event.params)), (0, import_cjs$6.map)((event) => ({
|
|
19112
19179
|
node_id: event.node_id,
|
|
19113
19180
|
...event.params.params
|
|
19114
19181
|
}))));
|
|
@@ -19128,20 +19195,20 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19128
19195
|
return { jwt_token: credential.token };
|
|
19129
19196
|
}
|
|
19130
19197
|
async connect() {
|
|
19131
|
-
await (0, import_cjs$
|
|
19198
|
+
await (0, import_cjs$6.firstValueFrom)(this.initialized$);
|
|
19132
19199
|
await this.transport.connect();
|
|
19133
|
-
await (0, import_cjs$
|
|
19200
|
+
await (0, import_cjs$6.firstValueFrom)(this.authenticated$.pipe((0, import_cjs$6.takeUntil)(this.destroyed$), (0, import_cjs$6.filter)(Boolean), (0, import_cjs$6.take)(1), (0, import_cjs$6.timeout)({ first: 15e3 })));
|
|
19134
19201
|
}
|
|
19135
19202
|
async handleAuthenticationError(error) {
|
|
19136
|
-
logger$
|
|
19203
|
+
logger$8.error("Authentication error:", error);
|
|
19137
19204
|
const isRecoverableAuthError = error instanceof JSONRPCError && (error.code === RPC_ERROR_REQUESTER_VALIDATION_FAILED || error.code === RPC_ERROR_INVALID_PARAMS || error.code === RPC_ERROR_AUTHENTICATION_FAILED);
|
|
19138
|
-
const hasStoredState = await (0, import_cjs$
|
|
19205
|
+
const hasStoredState = await (0, import_cjs$6.firstValueFrom)(this.authorizationState$.pipe((0, import_cjs$6.take)(1))) !== void 0;
|
|
19139
19206
|
if (isRecoverableAuthError && hasStoredState) {
|
|
19140
|
-
logger$
|
|
19207
|
+
logger$8.debug("[Session] Recoverable auth error — cleaning up stored state and reconnecting fresh");
|
|
19141
19208
|
try {
|
|
19142
19209
|
await this.cleanupStoredConnectionParams();
|
|
19143
19210
|
} catch (cleanupError) {
|
|
19144
|
-
logger$
|
|
19211
|
+
logger$8.error("Failed to cleanup stored connection params:", cleanupError);
|
|
19145
19212
|
} finally {
|
|
19146
19213
|
this.transport.reconnect();
|
|
19147
19214
|
}
|
|
@@ -19156,44 +19223,44 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19156
19223
|
try {
|
|
19157
19224
|
await this.storage.setItem(this.authorizationStateKey, authorization_state);
|
|
19158
19225
|
} catch (error) {
|
|
19159
|
-
logger$
|
|
19226
|
+
logger$8.error("Failed to update authorization state in storage:", error);
|
|
19160
19227
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19161
19228
|
}
|
|
19162
19229
|
}
|
|
19163
19230
|
async reauthenticate(token, dpopToken, options) {
|
|
19164
|
-
logger$
|
|
19231
|
+
logger$8.debug("[Session] Re-authenticating session");
|
|
19165
19232
|
try {
|
|
19166
19233
|
let resolvedDpopToken = dpopToken;
|
|
19167
19234
|
if (!resolvedDpopToken && this.dpopManager?.initialized) try {
|
|
19168
19235
|
resolvedDpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19169
19236
|
} catch (error) {
|
|
19170
19237
|
if (this._clientBound) throw error;
|
|
19171
|
-
logger$
|
|
19238
|
+
logger$8.warn("[Session] Failed to create DPoP proof for reauthenticate:", error);
|
|
19172
19239
|
}
|
|
19173
19240
|
const request = RPCReauthenticate({
|
|
19174
19241
|
project: this._authorization$.value?.project_id ?? "",
|
|
19175
19242
|
jwt_token: token,
|
|
19176
19243
|
...resolvedDpopToken ? { dpop_token: resolvedDpopToken } : {}
|
|
19177
19244
|
});
|
|
19178
|
-
await (0, import_cjs$
|
|
19179
|
-
logger$
|
|
19245
|
+
await (0, import_cjs$6.lastValueFrom)((0, import_cjs$6.from)(this.transport.execute(request)).pipe(throwOnRPCError(), (0, import_cjs$6.take)(1), (0, import_cjs$6.catchError)((err) => {
|
|
19246
|
+
logger$8.error("[Session] Re-authentication RPC failed:", err);
|
|
19180
19247
|
throw err;
|
|
19181
19248
|
})));
|
|
19182
19249
|
if (options?.clientBound) this._clientBound = true;
|
|
19183
|
-
logger$
|
|
19250
|
+
logger$8.debug("[Session] Re-authentication successful, updating stored auth state");
|
|
19184
19251
|
} catch (error) {
|
|
19185
|
-
logger$
|
|
19252
|
+
logger$8.error("[Session] Re-authentication failed:", error);
|
|
19186
19253
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19187
19254
|
throw error;
|
|
19188
19255
|
}
|
|
19189
19256
|
}
|
|
19190
19257
|
async authenticate() {
|
|
19191
|
-
logger$
|
|
19192
|
-
const persistedParams = await (0, import_cjs$
|
|
19258
|
+
logger$8.debug("[Session] Starting authentication process");
|
|
19259
|
+
const persistedParams = await (0, import_cjs$6.firstValueFrom)((0, import_cjs$6.combineLatest)({
|
|
19193
19260
|
protocol: this.transport.protocol$,
|
|
19194
19261
|
authorization_state: this.authorizationState$
|
|
19195
|
-
}).pipe((0, import_cjs$
|
|
19196
|
-
logger$
|
|
19262
|
+
}).pipe((0, import_cjs$6.take)(1)));
|
|
19263
|
+
logger$8.debug("[Session] Persisted params:\n", {
|
|
19197
19264
|
protocol: persistedParams.protocol,
|
|
19198
19265
|
authStateLength: persistedParams.authorization_state?.length
|
|
19199
19266
|
});
|
|
@@ -19201,16 +19268,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19201
19268
|
const storedToken = this.getCredential().token;
|
|
19202
19269
|
const isReconnect = hasReconnectState && storedToken;
|
|
19203
19270
|
let dpopToken;
|
|
19204
|
-
if (isReconnect) logger$
|
|
19271
|
+
if (isReconnect) logger$8.debug("[Session] Reconnecting with stored jwt_token + authorization_state");
|
|
19205
19272
|
else if (this.onBeforeReconnect && this._clientBound) {
|
|
19206
|
-
logger$
|
|
19273
|
+
logger$8.debug("[Session] Refreshing credentials before fresh connect");
|
|
19207
19274
|
await this.onBeforeReconnect();
|
|
19208
19275
|
}
|
|
19209
19276
|
if ((!isReconnect || this._clientBound) && this.dpopManager?.initialized) try {
|
|
19210
19277
|
dpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.connect" });
|
|
19211
19278
|
} catch (error) {
|
|
19212
19279
|
if (this._clientBound) throw error;
|
|
19213
|
-
logger$
|
|
19280
|
+
logger$8.warn("[Session] Failed to create DPoP proof for connect, proceeding without:", error);
|
|
19214
19281
|
}
|
|
19215
19282
|
const rpcConnectRequest = RPCConnect({
|
|
19216
19283
|
authentication: isReconnect ? { jwt_token: storedToken } : this.authentication,
|
|
@@ -19226,13 +19293,13 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19226
19293
|
protocol: persistedParams.protocol
|
|
19227
19294
|
} : {}
|
|
19228
19295
|
});
|
|
19229
|
-
const response = await (0, import_cjs$
|
|
19230
|
-
logger$
|
|
19231
|
-
}), (0, import_cjs$
|
|
19232
|
-
logger$
|
|
19296
|
+
const response = await (0, import_cjs$6.lastValueFrom)((0, import_cjs$6.from)(this.transport.execute(rpcConnectRequest)).pipe(throwOnRPCError(), (0, import_cjs$6.map)((res) => res.result), (0, import_cjs$6.filter)(isRPCConnectResult), (0, import_cjs$6.tap)(() => {
|
|
19297
|
+
logger$8.debug("[Session] Response passed filter, processing authentication result");
|
|
19298
|
+
}), (0, import_cjs$6.take)(1), (0, import_cjs$6.catchError)((err) => {
|
|
19299
|
+
logger$8.error("[Session] Authentication RPC failed:", err);
|
|
19233
19300
|
throw err;
|
|
19234
19301
|
})));
|
|
19235
|
-
logger$
|
|
19302
|
+
logger$8.debug("[Session] Processing authentication result:", {
|
|
19236
19303
|
hasProtocol: !!response.protocol,
|
|
19237
19304
|
hasAuthorization: !!response.authorization,
|
|
19238
19305
|
hasIceServers: !!response.ice_servers
|
|
@@ -19241,7 +19308,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19241
19308
|
this._authorization$.next(response.authorization);
|
|
19242
19309
|
this._iceServers$.next(response.ice_servers ?? []);
|
|
19243
19310
|
this._authenticated$.next(true);
|
|
19244
|
-
logger$
|
|
19311
|
+
logger$8.debug("[Session] Authentication completed successfully");
|
|
19245
19312
|
}
|
|
19246
19313
|
async disconnect() {
|
|
19247
19314
|
this.transport.disconnect();
|
|
@@ -19260,7 +19327,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19260
19327
|
displayDirection: invite.display_direction,
|
|
19261
19328
|
userVariables: invite.userVariables
|
|
19262
19329
|
});
|
|
19263
|
-
await (0, import_cjs$
|
|
19330
|
+
await (0, import_cjs$6.firstValueFrom)(callSession.status$);
|
|
19264
19331
|
this._calls$.next({
|
|
19265
19332
|
[`${callSession.id}`]: callSession,
|
|
19266
19333
|
...this._calls$.value
|
|
@@ -19278,11 +19345,11 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19278
19345
|
async handleVertoAttach(attach) {
|
|
19279
19346
|
const { callID } = attach;
|
|
19280
19347
|
if (callID in this._calls$.value) {
|
|
19281
|
-
logger$
|
|
19348
|
+
logger$8.debug(`[Session] Verto attach for existing call ${callID}, deferring to per-call handler`);
|
|
19282
19349
|
return;
|
|
19283
19350
|
}
|
|
19284
19351
|
const storedOptions = this.attachManager.consumePendingAttachment(callID);
|
|
19285
|
-
logger$
|
|
19352
|
+
logger$8.debug(`[Session] Creating reattached call for callID: ${callID}`);
|
|
19286
19353
|
const callSession = await this.createCall({
|
|
19287
19354
|
nodeId: attach.node_id,
|
|
19288
19355
|
callId: callID,
|
|
@@ -19293,7 +19360,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19293
19360
|
reattach: true,
|
|
19294
19361
|
...storedOptions
|
|
19295
19362
|
});
|
|
19296
|
-
await (0, import_cjs$
|
|
19363
|
+
await (0, import_cjs$6.firstValueFrom)(callSession.status$);
|
|
19297
19364
|
this._calls$.next({
|
|
19298
19365
|
[`${callSession.id}`]: callSession,
|
|
19299
19366
|
...this._calls$.value
|
|
@@ -19307,16 +19374,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19307
19374
|
to: destinationURI,
|
|
19308
19375
|
...options
|
|
19309
19376
|
});
|
|
19310
|
-
await (0, import_cjs$
|
|
19377
|
+
await (0, import_cjs$6.firstValueFrom)((0, import_cjs$6.race)(callSession.selfId$.pipe((0, import_cjs$6.filter)((id) => Boolean(id)), (0, import_cjs$6.take)(1), (0, import_cjs$6.timeout)(this.callCreateTimeout)), callSession.errors$.pipe((0, import_cjs$6.take)(1), (0, import_cjs$6.switchMap)((callError) => (0, import_cjs$6.throwError)(() => callError.error)))));
|
|
19311
19378
|
this._calls$.next({
|
|
19312
19379
|
[`${callSession.id}`]: callSession,
|
|
19313
19380
|
...this._calls$.value
|
|
19314
19381
|
});
|
|
19315
19382
|
return callSession;
|
|
19316
19383
|
} catch (error) {
|
|
19317
|
-
logger$
|
|
19384
|
+
logger$8.error("[Session] Error creating outbound call:", error);
|
|
19318
19385
|
callSession?.destroy();
|
|
19319
|
-
const callError = new CallCreateError(error instanceof import_cjs$
|
|
19386
|
+
const callError = new CallCreateError(error instanceof import_cjs$6.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
|
|
19320
19387
|
this._errors$.next(callError);
|
|
19321
19388
|
throw callError;
|
|
19322
19389
|
}
|
|
@@ -19332,16 +19399,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19332
19399
|
address = this._directory.get(addressId);
|
|
19333
19400
|
if (!address) throw new DependencyError(`Address ID: ${addressId} not found`);
|
|
19334
19401
|
} catch {
|
|
19335
|
-
logger$
|
|
19402
|
+
logger$8.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
|
|
19336
19403
|
}
|
|
19337
19404
|
const callSession = this.callFactory.createCall(address, { ...options });
|
|
19338
|
-
this.subscribeTo(callSession.status$.pipe((0, import_cjs$
|
|
19405
|
+
this.subscribeTo(callSession.status$.pipe((0, import_cjs$6.filter)((status) => status === "destroyed"), (0, import_cjs$6.take)(1)), () => {
|
|
19339
19406
|
const { [`${callSession.id}`]: _, ...remainingCalls } = this._calls$.value;
|
|
19340
19407
|
this._calls$.next(remainingCalls);
|
|
19341
19408
|
});
|
|
19342
19409
|
return callSession;
|
|
19343
19410
|
} catch (error) {
|
|
19344
|
-
logger$
|
|
19411
|
+
logger$8.error("[Session] Error creating call session:", error);
|
|
19345
19412
|
throw new CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
|
|
19346
19413
|
}
|
|
19347
19414
|
}
|
|
@@ -19389,8 +19456,8 @@ const isString = (obj) => typeof obj === "string";
|
|
|
19389
19456
|
|
|
19390
19457
|
//#endregion
|
|
19391
19458
|
//#region src/managers/ConversationsManager.ts
|
|
19392
|
-
var import_cjs$
|
|
19393
|
-
const logger$
|
|
19459
|
+
var import_cjs$5 = require_cjs();
|
|
19460
|
+
const logger$7 = getLogger();
|
|
19394
19461
|
var ConversationMessagesFetcher = class extends Fetcher {
|
|
19395
19462
|
constructor(groupId, http) {
|
|
19396
19463
|
super(`/api/fabric/conversations/${groupId}/messages`, "page_size=100", http);
|
|
@@ -19430,13 +19497,13 @@ var ConversationsManager = class {
|
|
|
19430
19497
|
}
|
|
19431
19498
|
throw new ConversationError("Join Failed - Unexpected response");
|
|
19432
19499
|
} catch (error) {
|
|
19433
|
-
logger$
|
|
19500
|
+
logger$7.error("[ConversationsManager] Failed to join conversation:", error);
|
|
19434
19501
|
throw error;
|
|
19435
19502
|
}
|
|
19436
19503
|
}
|
|
19437
19504
|
async getConversationMessageCollection(addressId) {
|
|
19438
19505
|
const groupId = this.groupIds.get(addressId) ?? await this.join(addressId);
|
|
19439
|
-
return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(filterAs(isConversationMessageMetadata, "params"), (0, import_cjs$
|
|
19506
|
+
return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(filterAs(isConversationMessageMetadata, "params"), (0, import_cjs$5.tap)((event) => logger$7.debug("[ConversationsManager ] Conversation Event:", event)), (0, import_cjs$5.map)((params) => ({ ...params }))), this.http, this.onError));
|
|
19440
19507
|
}
|
|
19441
19508
|
async sendText(text, destinationAddressId) {
|
|
19442
19509
|
const groupId = this.groupIds.get(destinationAddressId) ?? await this.join(destinationAddressId);
|
|
@@ -19453,12 +19520,222 @@ var ConversationsManager = class {
|
|
|
19453
19520
|
})).ok) return;
|
|
19454
19521
|
throw new ConversationError("Send Text Failed - Unexpected response");
|
|
19455
19522
|
} catch (error) {
|
|
19456
|
-
logger$
|
|
19523
|
+
logger$7.error("[ConversationsManager] Failed to send text message:", error);
|
|
19457
19524
|
throw error;
|
|
19458
19525
|
}
|
|
19459
19526
|
}
|
|
19460
19527
|
};
|
|
19461
19528
|
|
|
19529
|
+
//#endregion
|
|
19530
|
+
//#region src/managers/DeviceTokenManager.ts
|
|
19531
|
+
var import_cjs$4 = require_cjs();
|
|
19532
|
+
const logger$6 = getLogger();
|
|
19533
|
+
/**
|
|
19534
|
+
* Resolves the token expiry timestamp (epoch seconds) using a 3-tier priority chain:
|
|
19535
|
+
* 1. `data.expires_at` — server-provided absolute timestamp
|
|
19536
|
+
* 2. `data.expires_in` — server-provided relative lifetime
|
|
19537
|
+
* 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN` with a warning
|
|
19538
|
+
*/
|
|
19539
|
+
function resolveExpiresAt(data) {
|
|
19540
|
+
if (data.expires_at) return data.expires_at;
|
|
19541
|
+
if (data.expires_in) return Math.floor(Date.now() / 1e3) + data.expires_in;
|
|
19542
|
+
logger$6.warn("[DeviceToken] Could not determine token expiry, using default");
|
|
19543
|
+
return Math.floor(Date.now() / 1e3) + DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
19544
|
+
}
|
|
19545
|
+
/**
|
|
19546
|
+
* Resolves the token TTL in seconds from a fresh response.
|
|
19547
|
+
* Called at token receive time so `expires_at - now` reflects the original lifetime.
|
|
19548
|
+
*
|
|
19549
|
+
* 1. `data.expires_in` — server-provided TTL directly
|
|
19550
|
+
* 2. `data.expires_at - now` — derive TTL from absolute timestamp
|
|
19551
|
+
* 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN`
|
|
19552
|
+
*/
|
|
19553
|
+
function resolveExpireIn(data) {
|
|
19554
|
+
if (data.expires_in) return data.expires_in;
|
|
19555
|
+
if (data.expires_at) return Math.max(data.expires_at - Math.floor(Date.now() / 1e3), 1);
|
|
19556
|
+
return DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
19557
|
+
}
|
|
19558
|
+
/**
|
|
19559
|
+
* Manages the Client Bound SAT lifecycle: activation, token exchange,
|
|
19560
|
+
* reauthentication, and automatic refresh scheduling.
|
|
19561
|
+
*
|
|
19562
|
+
* Extends {@link Destroyable} for automatic RxJS subscription and subject cleanup.
|
|
19563
|
+
* Uses a reactive pipeline (`BehaviorSubject` + `switchMap(timer())`) instead of
|
|
19564
|
+
* raw `setTimeout` for refresh scheduling.
|
|
19565
|
+
*/
|
|
19566
|
+
var DeviceTokenManager = class extends Destroyable {
|
|
19567
|
+
constructor(dpopManager, http, errorHandler, getCredential) {
|
|
19568
|
+
super();
|
|
19569
|
+
this.dpopManager = dpopManager;
|
|
19570
|
+
this.http = http;
|
|
19571
|
+
this.errorHandler = errorHandler;
|
|
19572
|
+
this.getCredential = getCredential;
|
|
19573
|
+
this._currentToken$ = this.createBehaviorSubject(null);
|
|
19574
|
+
this._refreshInProgress = false;
|
|
19575
|
+
this._effectiveExpireIn = DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
19576
|
+
this.subscribeTo(this._currentToken$.pipe((0, import_cjs$4.filter)(Boolean), (0, import_cjs$4.switchMap)((tokenData) => {
|
|
19577
|
+
const expiresAt = resolveExpiresAt(tokenData);
|
|
19578
|
+
const refreshIn = Math.max(expiresAt * 1e3 - Date.now() - DEVICE_TOKEN_REFRESH_BUFFER_MS, 1e3);
|
|
19579
|
+
logger$6.debug(`[DeviceToken] Scheduling Client Bound SAT refresh in ${refreshIn}ms`);
|
|
19580
|
+
return (0, import_cjs$4.timer)(refreshIn);
|
|
19581
|
+
})), () => {
|
|
19582
|
+
this.executeRefresh();
|
|
19583
|
+
});
|
|
19584
|
+
}
|
|
19585
|
+
/** Current token TTL in milliseconds. Used to extend cached credential expiry on refresh. */
|
|
19586
|
+
get effectiveExpireIn() {
|
|
19587
|
+
return this._effectiveExpireIn;
|
|
19588
|
+
}
|
|
19589
|
+
/**
|
|
19590
|
+
* Activates the Client Bound SAT flow when the subscriber's token has
|
|
19591
|
+
* `sat:refresh` scope.
|
|
19592
|
+
*
|
|
19593
|
+
* Steps:
|
|
19594
|
+
* 1. Check subscriber's `sat_claims` for `sat:refresh` scope
|
|
19595
|
+
* 2. Call `/api/fabric/subscriber/devices/token` with a DPoP proof
|
|
19596
|
+
* 3. Reauthenticate the session with the Client Bound SAT + DPoP proof
|
|
19597
|
+
* 4. Emit token to trigger the reactive refresh pipeline
|
|
19598
|
+
*/
|
|
19599
|
+
async activate(subscriber, session, updateCredential) {
|
|
19600
|
+
const { satClaims } = subscriber;
|
|
19601
|
+
if (!satClaims?.scope?.includes(SAT_REFRESH_SCOPE)) {
|
|
19602
|
+
logger$6.debug("[DeviceToken] No sat:refresh scope, skipping Client Bound SAT activation");
|
|
19603
|
+
return;
|
|
19604
|
+
}
|
|
19605
|
+
this._session = session;
|
|
19606
|
+
this._updateCredential = updateCredential;
|
|
19607
|
+
try {
|
|
19608
|
+
const tokenData = await this.obtainToken();
|
|
19609
|
+
if (!tokenData.expires_at && !tokenData.expires_in && satClaims.expires_at) tokenData.expires_at = satClaims.expires_at;
|
|
19610
|
+
this._effectiveExpireIn = resolveExpireIn(tokenData);
|
|
19611
|
+
const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19612
|
+
await session.reauthenticate(tokenData.token, rpcProof, { clientBound: true });
|
|
19613
|
+
updateCredential({ token: tokenData.token });
|
|
19614
|
+
logger$6.info("[DeviceToken] Client Bound SAT activated successfully");
|
|
19615
|
+
this._currentToken$.next(tokenData);
|
|
19616
|
+
} catch (error) {
|
|
19617
|
+
logger$6.error("[DeviceToken] Failed to activate Client Bound SAT:", error);
|
|
19618
|
+
this.errorHandler(new DPoPInitError(error, "Failed to activate Client Bound SAT"));
|
|
19619
|
+
const credential = this.getCredential();
|
|
19620
|
+
const expiresAt = satClaims.expires_at ?? (credential.expiry_at ? credential.expiry_at / 1e3 : Date.now() / 1e3 + DEVICE_TOKEN_DEFAULT_EXPIRE_IN / 1e3);
|
|
19621
|
+
this._currentToken$.next({
|
|
19622
|
+
token: credential.token ?? "",
|
|
19623
|
+
expires_at: expiresAt
|
|
19624
|
+
});
|
|
19625
|
+
}
|
|
19626
|
+
}
|
|
19627
|
+
/**
|
|
19628
|
+
* Obtains a Client Bound SAT from `/api/fabric/subscriber/devices/token`.
|
|
19629
|
+
* Returns the full {@link DeviceTokenResponse} including expiry metadata.
|
|
19630
|
+
*/
|
|
19631
|
+
async obtainToken() {
|
|
19632
|
+
const dpopProof = await this.dpopManager.createHttpProof({
|
|
19633
|
+
method: "POST",
|
|
19634
|
+
uri: DEVICE_TOKEN_ENDPOINT
|
|
19635
|
+
});
|
|
19636
|
+
const response = await this.http.request({
|
|
19637
|
+
url: DEVICE_TOKEN_ENDPOINT,
|
|
19638
|
+
...POST_PARAMS,
|
|
19639
|
+
body: JSON.stringify({
|
|
19640
|
+
dpop_token: dpopProof,
|
|
19641
|
+
expire_in: DEVICE_TOKEN_DEFAULT_EXPIRE_IN
|
|
19642
|
+
})
|
|
19643
|
+
});
|
|
19644
|
+
if (!response.ok || !response.body) throw new DeviceTokenError(`Failed to obtain device token: ${response.status} ${response.statusText}`);
|
|
19645
|
+
const data = JSON.parse(response.body);
|
|
19646
|
+
if (!data.token) throw new DeviceTokenError("Device token response missing token field");
|
|
19647
|
+
return data;
|
|
19648
|
+
}
|
|
19649
|
+
/**
|
|
19650
|
+
* Refreshes the Client Bound SAT via `/api/fabric/subscriber/devices/refresh`.
|
|
19651
|
+
*
|
|
19652
|
+
* Creates a fresh DPoP proof, calls the refresh endpoint, reauthenticates
|
|
19653
|
+
* the WebSocket session, and returns the new token data (scheduling is
|
|
19654
|
+
* handled by the reactive pipeline).
|
|
19655
|
+
*/
|
|
19656
|
+
async refreshToken(session, currentToken, updateCredential) {
|
|
19657
|
+
logger$6.debug("[DeviceToken] Refreshing Client Bound SAT");
|
|
19658
|
+
const dpopProof = await this.dpopManager.createHttpProof({
|
|
19659
|
+
method: "POST",
|
|
19660
|
+
uri: DEVICE_REFRESH_ENDPOINT,
|
|
19661
|
+
accessToken: currentToken
|
|
19662
|
+
});
|
|
19663
|
+
const response = await this.http.request({
|
|
19664
|
+
url: DEVICE_REFRESH_ENDPOINT,
|
|
19665
|
+
...POST_PARAMS,
|
|
19666
|
+
body: JSON.stringify({
|
|
19667
|
+
dpop_token: dpopProof,
|
|
19668
|
+
expire_in: this._effectiveExpireIn
|
|
19669
|
+
})
|
|
19670
|
+
});
|
|
19671
|
+
if (!response.ok || !response.body) throw new TokenRefreshError(`Failed to refresh device token: ${response.status} ${response.statusText}`);
|
|
19672
|
+
const data = JSON.parse(response.body);
|
|
19673
|
+
if (!data.token) throw new TokenRefreshError("Device token refresh response missing token field");
|
|
19674
|
+
if (!data.expires_at && !data.expires_in) data.expires_in = this._effectiveExpireIn;
|
|
19675
|
+
this._effectiveExpireIn = resolveExpireIn(data);
|
|
19676
|
+
const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19677
|
+
await session.reauthenticate(data.token, rpcProof);
|
|
19678
|
+
updateCredential({ token: data.token });
|
|
19679
|
+
logger$6.info("[DeviceToken] Client Bound SAT refreshed successfully");
|
|
19680
|
+
return data;
|
|
19681
|
+
}
|
|
19682
|
+
/**
|
|
19683
|
+
* Executes a refresh with retry and exponential backoff.
|
|
19684
|
+
* On success, emits to `_currentToken$` to schedule the next refresh.
|
|
19685
|
+
* On all retries exhausted, emits to `errorHandler`.
|
|
19686
|
+
*/
|
|
19687
|
+
async executeRefresh() {
|
|
19688
|
+
if (this._refreshInProgress) {
|
|
19689
|
+
logger$6.debug("[DeviceToken] Refresh already in progress, skipping");
|
|
19690
|
+
return;
|
|
19691
|
+
}
|
|
19692
|
+
const session = this._session;
|
|
19693
|
+
const updateCredential = this._updateCredential;
|
|
19694
|
+
if (!session || !updateCredential) {
|
|
19695
|
+
logger$6.warn("[DeviceToken] Cannot refresh: session or updateCredential not set");
|
|
19696
|
+
return;
|
|
19697
|
+
}
|
|
19698
|
+
if (!session.authenticated) {
|
|
19699
|
+
logger$6.debug("[DeviceToken] Session not authenticated, deferring refresh");
|
|
19700
|
+
return;
|
|
19701
|
+
}
|
|
19702
|
+
this._refreshInProgress = true;
|
|
19703
|
+
try {
|
|
19704
|
+
const currentToken = this.getCredential().token;
|
|
19705
|
+
if (!currentToken) throw new TokenRefreshError("No current token available for refresh");
|
|
19706
|
+
const newTokenData = await this.retryRefresh(session, currentToken, updateCredential);
|
|
19707
|
+
this._currentToken$.next(newTokenData);
|
|
19708
|
+
} catch (error) {
|
|
19709
|
+
logger$6.error("[DeviceToken] Automatic Client Bound SAT refresh failed:", error);
|
|
19710
|
+
this.errorHandler(error instanceof TokenRefreshError ? error : new TokenRefreshError("Automatic token refresh failed", error));
|
|
19711
|
+
} finally {
|
|
19712
|
+
this._refreshInProgress = false;
|
|
19713
|
+
}
|
|
19714
|
+
}
|
|
19715
|
+
/**
|
|
19716
|
+
* Retries `refreshToken()` up to `DEVICE_TOKEN_REFRESH_MAX_RETRIES` times
|
|
19717
|
+
* with exponential backoff (1s, 2s, 4s).
|
|
19718
|
+
*/
|
|
19719
|
+
async retryRefresh(session, currentToken, updateCredential) {
|
|
19720
|
+
let lastError;
|
|
19721
|
+
for (let attempt = 0; attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES; attempt++) try {
|
|
19722
|
+
return await this.refreshToken(session, currentToken, updateCredential);
|
|
19723
|
+
} catch (error) {
|
|
19724
|
+
lastError = error;
|
|
19725
|
+
if (attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES - 1) {
|
|
19726
|
+
const delay$1 = DEVICE_TOKEN_REFRESH_RETRY_BASE_MS * Math.pow(2, attempt);
|
|
19727
|
+
logger$6.warn(`[DeviceToken] Refresh attempt ${attempt + 1} failed, retrying in ${delay$1}ms`);
|
|
19728
|
+
await new Promise((resolve) => setTimeout(resolve, delay$1));
|
|
19729
|
+
}
|
|
19730
|
+
}
|
|
19731
|
+
throw lastError instanceof Error ? lastError : new TokenRefreshError("All refresh retries exhausted", lastError);
|
|
19732
|
+
}
|
|
19733
|
+
/** Cleans up the manager, cancelling the reactive pipeline and all subscriptions. */
|
|
19734
|
+
destroy() {
|
|
19735
|
+
super.destroy();
|
|
19736
|
+
}
|
|
19737
|
+
};
|
|
19738
|
+
|
|
19462
19739
|
//#endregion
|
|
19463
19740
|
//#region src/managers/DiagnosticsCollector.ts
|
|
19464
19741
|
const logger$5 = getLogger();
|
|
@@ -20392,13 +20669,43 @@ var SignalWire = class extends Destroyable {
|
|
|
20392
20669
|
this._errors$.next(error);
|
|
20393
20670
|
});
|
|
20394
20671
|
await this._clientSession.connect();
|
|
20395
|
-
|
|
20396
|
-
|
|
20397
|
-
|
|
20672
|
+
if (this._dpopManager?.initialized) {
|
|
20673
|
+
if (this._refreshTimerId) {
|
|
20674
|
+
clearTimeout(this._refreshTimerId);
|
|
20675
|
+
this._refreshTimerId = void 0;
|
|
20676
|
+
logger$1.debug("[SignalWire] Developer refresh disabled — Client Bound SAT activation starting");
|
|
20677
|
+
}
|
|
20678
|
+
this._deviceTokenManager = new DeviceTokenManager(this._dpopManager, this._deps.http, (error) => this._errors$.next(error), () => this._deps.credential);
|
|
20679
|
+
await this._deviceTokenManager.activate(this._deps.subscriber, this._clientSession, (cred) => {
|
|
20680
|
+
this._deps.credential = {
|
|
20681
|
+
...this._deps.credential,
|
|
20682
|
+
...cred
|
|
20683
|
+
};
|
|
20684
|
+
});
|
|
20685
|
+
}
|
|
20686
|
+
this.subscribeTo(this._clientSession.authenticated$.pipe((0, import_cjs.skip)(1), (0, import_cjs.filter)(Boolean)), async () => {
|
|
20687
|
+
try {
|
|
20688
|
+
if (this._deviceTokenManager) {
|
|
20689
|
+
await this._deviceTokenManager.activate(this._deps.subscriber, this._clientSession, (cred) => {
|
|
20690
|
+
this._deps.credential = {
|
|
20691
|
+
...this._deps.credential,
|
|
20692
|
+
...cred
|
|
20693
|
+
};
|
|
20694
|
+
});
|
|
20695
|
+
logger$1.debug("[SignalWire] Client Bound SAT re-activated after reconnect");
|
|
20696
|
+
}
|
|
20697
|
+
} catch (error) {
|
|
20698
|
+
logger$1.error("[SignalWire] Client Bound SAT re-activation failed (non-fatal):", error);
|
|
20699
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
20700
|
+
}
|
|
20701
|
+
try {
|
|
20702
|
+
logger$1.debug("[SignalWire] Re-registering subscriber after reconnect");
|
|
20703
|
+
await this.register();
|
|
20398
20704
|
logger$1.debug("[SignalWire] Subscriber re-registered successfully after reconnect");
|
|
20399
|
-
}
|
|
20705
|
+
} catch (error) {
|
|
20400
20706
|
logger$1.error("[SignalWire] Re-registration failed after reconnect:", error);
|
|
20401
|
-
|
|
20707
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
20708
|
+
}
|
|
20402
20709
|
});
|
|
20403
20710
|
const conversationManager = new ConversationsManager(this._clientSession, this._deps.http, () => this._deps.getSubscriberFromAddressId(), errorHandler);
|
|
20404
20711
|
const directory = new DirectoryManager(this._deps.http, this._clientSession, conversationManager, errorHandler);
|