@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.mjs
CHANGED
|
@@ -3390,7 +3390,7 @@ var require_map = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3390
3390
|
exports.map = void 0;
|
|
3391
3391
|
var lift_1$64 = require_lift();
|
|
3392
3392
|
var OperatorSubscriber_1$54 = require_OperatorSubscriber();
|
|
3393
|
-
function map$
|
|
3393
|
+
function map$19(project, thisArg) {
|
|
3394
3394
|
return lift_1$64.operate(function(source, subscriber) {
|
|
3395
3395
|
var index = 0;
|
|
3396
3396
|
source.subscribe(OperatorSubscriber_1$54.createOperatorSubscriber(subscriber, function(value) {
|
|
@@ -3398,7 +3398,7 @@ var require_map = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3398
3398
|
}));
|
|
3399
3399
|
});
|
|
3400
3400
|
}
|
|
3401
|
-
exports.map = map$
|
|
3401
|
+
exports.map = map$19;
|
|
3402
3402
|
}));
|
|
3403
3403
|
|
|
3404
3404
|
//#endregion
|
|
@@ -4140,7 +4140,7 @@ var require_timer = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4140
4140
|
var async_1$11 = require_async();
|
|
4141
4141
|
var isScheduler_1 = require_isScheduler();
|
|
4142
4142
|
var isDate_1$1 = require_isDate();
|
|
4143
|
-
function timer$
|
|
4143
|
+
function timer$2(dueTime, intervalOrScheduler, scheduler) {
|
|
4144
4144
|
if (dueTime === void 0) dueTime = 0;
|
|
4145
4145
|
if (scheduler === void 0) scheduler = async_1$11.async;
|
|
4146
4146
|
var intervalDuration = -1;
|
|
@@ -4159,7 +4159,7 @@ var require_timer = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4159
4159
|
}, due);
|
|
4160
4160
|
});
|
|
4161
4161
|
}
|
|
4162
|
-
exports.timer = timer$
|
|
4162
|
+
exports.timer = timer$2;
|
|
4163
4163
|
}));
|
|
4164
4164
|
|
|
4165
4165
|
//#endregion
|
|
@@ -4293,7 +4293,7 @@ var require_filter = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4293
4293
|
exports.filter = void 0;
|
|
4294
4294
|
var lift_1$62 = require_lift();
|
|
4295
4295
|
var OperatorSubscriber_1$49 = require_OperatorSubscriber();
|
|
4296
|
-
function filter$
|
|
4296
|
+
function filter$16(predicate, thisArg) {
|
|
4297
4297
|
return lift_1$62.operate(function(source, subscriber) {
|
|
4298
4298
|
var index = 0;
|
|
4299
4299
|
source.subscribe(OperatorSubscriber_1$49.createOperatorSubscriber(subscriber, function(value) {
|
|
@@ -4301,7 +4301,7 @@ var require_filter = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4301
4301
|
}));
|
|
4302
4302
|
});
|
|
4303
4303
|
}
|
|
4304
|
-
exports.filter = filter$
|
|
4304
|
+
exports.filter = filter$16;
|
|
4305
4305
|
}));
|
|
4306
4306
|
|
|
4307
4307
|
//#endregion
|
|
@@ -6934,7 +6934,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6934
6934
|
var innerFrom_1$6 = require_innerFrom();
|
|
6935
6935
|
var lift_1$13 = require_lift();
|
|
6936
6936
|
var OperatorSubscriber_1$11 = require_OperatorSubscriber();
|
|
6937
|
-
function switchMap$
|
|
6937
|
+
function switchMap$7(project, resultSelector) {
|
|
6938
6938
|
return lift_1$13.operate(function(source, subscriber) {
|
|
6939
6939
|
var innerSubscriber = null;
|
|
6940
6940
|
var index = 0;
|
|
@@ -6958,7 +6958,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6958
6958
|
}));
|
|
6959
6959
|
});
|
|
6960
6960
|
}
|
|
6961
|
-
exports.switchMap = switchMap$
|
|
6961
|
+
exports.switchMap = switchMap$7;
|
|
6962
6962
|
}));
|
|
6963
6963
|
|
|
6964
6964
|
//#endregion
|
|
@@ -7582,7 +7582,7 @@ var require_withLatestFrom = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
7582
7582
|
var identity_1$1 = require_identity();
|
|
7583
7583
|
var noop_1$1 = require_noop();
|
|
7584
7584
|
var args_1 = require_args();
|
|
7585
|
-
function withLatestFrom$
|
|
7585
|
+
function withLatestFrom$2() {
|
|
7586
7586
|
var inputs = [];
|
|
7587
7587
|
for (var _i = 0; _i < arguments.length; _i++) inputs[_i] = arguments[_i];
|
|
7588
7588
|
var project = args_1.popResultSelector(inputs);
|
|
@@ -7611,7 +7611,7 @@ var require_withLatestFrom = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
7611
7611
|
}));
|
|
7612
7612
|
});
|
|
7613
7613
|
}
|
|
7614
|
-
exports.withLatestFrom = withLatestFrom$
|
|
7614
|
+
exports.withLatestFrom = withLatestFrom$2;
|
|
7615
7615
|
}));
|
|
7616
7616
|
|
|
7617
7617
|
//#endregion
|
|
@@ -8933,13 +8933,13 @@ var require_cjs = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
8933
8933
|
|
|
8934
8934
|
//#endregion
|
|
8935
8935
|
//#region src/behaviors/Destroyable.ts
|
|
8936
|
-
var import_cjs$
|
|
8936
|
+
var import_cjs$28 = require_cjs();
|
|
8937
8937
|
var Destroyable = class {
|
|
8938
8938
|
constructor() {
|
|
8939
8939
|
this.subscriptions = [];
|
|
8940
8940
|
this.subjects = [];
|
|
8941
|
-
this._destroyed$ = new import_cjs$
|
|
8942
|
-
this._change$ = new import_cjs$
|
|
8941
|
+
this._destroyed$ = new import_cjs$28.Subject();
|
|
8942
|
+
this._change$ = new import_cjs$28.Subject();
|
|
8943
8943
|
}
|
|
8944
8944
|
destroy() {
|
|
8945
8945
|
this._observableCache?.clear();
|
|
@@ -8976,7 +8976,7 @@ var Destroyable = class {
|
|
|
8976
8976
|
this._observableCache ??= /* @__PURE__ */ new Map();
|
|
8977
8977
|
let cached = this._observableCache.get(publicKey);
|
|
8978
8978
|
if (!cached) {
|
|
8979
|
-
cached = factory().pipe((0, import_cjs$
|
|
8979
|
+
cached = factory().pipe((0, import_cjs$28.observeOn)(import_cjs$28.asapScheduler));
|
|
8980
8980
|
this._observableCache.set(publicKey, cached);
|
|
8981
8981
|
}
|
|
8982
8982
|
return cached;
|
|
@@ -8990,32 +8990,32 @@ var Destroyable = class {
|
|
|
8990
8990
|
* Do NOT use for observables consumed internally by the SDK.
|
|
8991
8991
|
*/
|
|
8992
8992
|
deferEmission(observable) {
|
|
8993
|
-
return observable.pipe((0, import_cjs$
|
|
8993
|
+
return observable.pipe((0, import_cjs$28.observeOn)(import_cjs$28.asapScheduler));
|
|
8994
8994
|
}
|
|
8995
8995
|
subscribeTo(observable, observerOrNext) {
|
|
8996
8996
|
const subscription = observable.subscribe(observerOrNext);
|
|
8997
8997
|
this.subscriptions.push(subscription);
|
|
8998
8998
|
}
|
|
8999
8999
|
createSubject() {
|
|
9000
|
-
const subject = new import_cjs$
|
|
9000
|
+
const subject = new import_cjs$28.Subject();
|
|
9001
9001
|
this.subjects.push(subject);
|
|
9002
|
-
this.subscriptions.push(subject.pipe((0, import_cjs$
|
|
9002
|
+
this.subscriptions.push(subject.pipe((0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
|
|
9003
9003
|
return subject;
|
|
9004
9004
|
}
|
|
9005
9005
|
createReplaySubject(bufferSize, windowTime$1) {
|
|
9006
|
-
const subject = new import_cjs$
|
|
9006
|
+
const subject = new import_cjs$28.ReplaySubject(bufferSize, windowTime$1);
|
|
9007
9007
|
this.subjects.push(subject);
|
|
9008
|
-
this.subscriptions.push(subject.pipe((0, import_cjs$
|
|
9008
|
+
this.subscriptions.push(subject.pipe((0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
|
|
9009
9009
|
return subject;
|
|
9010
9010
|
}
|
|
9011
9011
|
createBehaviorSubject(initialValue) {
|
|
9012
|
-
const subject = new import_cjs$
|
|
9012
|
+
const subject = new import_cjs$28.BehaviorSubject(initialValue);
|
|
9013
9013
|
this.subjects.push(subject);
|
|
9014
|
-
this.subscriptions.push(subject.pipe((0, import_cjs$
|
|
9014
|
+
this.subscriptions.push(subject.pipe((0, import_cjs$28.skip)(1), (0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
|
|
9015
9015
|
return subject;
|
|
9016
9016
|
}
|
|
9017
9017
|
get $() {
|
|
9018
|
-
return this._change$.pipe((0, import_cjs$
|
|
9018
|
+
return this._change$.pipe((0, import_cjs$28.map)(() => this));
|
|
9019
9019
|
}
|
|
9020
9020
|
/**
|
|
9021
9021
|
* Observable that emits when the instance is destroyed
|
|
@@ -9474,9 +9474,9 @@ var require_loglevel = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
9474
9474
|
defaultLogger$1 = new Logger();
|
|
9475
9475
|
defaultLogger$1.getLogger = function getLogger$1(name) {
|
|
9476
9476
|
if (typeof name !== "symbol" && typeof name !== "string" || name === "") throw new TypeError("You must supply a name when creating a logger.");
|
|
9477
|
-
var logger$
|
|
9478
|
-
if (!logger$
|
|
9479
|
-
return logger$
|
|
9477
|
+
var logger$30 = _loggersByName[name];
|
|
9478
|
+
if (!logger$30) logger$30 = _loggersByName[name] = new Logger(name, defaultLogger$1.methodFactory);
|
|
9479
|
+
return logger$30;
|
|
9480
9480
|
};
|
|
9481
9481
|
var _log = typeof window !== undefinedType ? window.log : void 0;
|
|
9482
9482
|
defaultLogger$1.noConflict = function() {
|
|
@@ -9516,15 +9516,15 @@ const shouldStringify = (payload) => {
|
|
|
9516
9516
|
return true;
|
|
9517
9517
|
};
|
|
9518
9518
|
const wsTraffic = ({ type, payload }) => {
|
|
9519
|
-
const logger$
|
|
9519
|
+
const logger$30 = getLoggerInstance();
|
|
9520
9520
|
const { logWsTraffic } = debugOptions ?? {};
|
|
9521
9521
|
if (!logWsTraffic) return;
|
|
9522
9522
|
const msg = shouldStringify(payload) ? JSON.stringify(payload, null, 2) : payload;
|
|
9523
|
-
return logger$
|
|
9523
|
+
return logger$30.debug(`${type.toUpperCase()}: \n`, msg, "\n");
|
|
9524
9524
|
};
|
|
9525
9525
|
const getLogger = () => {
|
|
9526
|
-
const logger$
|
|
9527
|
-
return new Proxy(logger$
|
|
9526
|
+
const logger$30 = getLoggerInstance();
|
|
9527
|
+
return new Proxy(logger$30, { get(target, prop, receiver) {
|
|
9528
9528
|
if (prop === "wsTraffic") return wsTraffic;
|
|
9529
9529
|
return Reflect.get(target, prop, receiver);
|
|
9530
9530
|
} });
|
|
@@ -9573,8 +9573,8 @@ const asyncRetry = async ({ asyncCallable, maxRetries: retries = DEFAULT_MAX_RET
|
|
|
9573
9573
|
|
|
9574
9574
|
//#endregion
|
|
9575
9575
|
//#region src/controllers/HTTPRequestController.ts
|
|
9576
|
-
var import_cjs$
|
|
9577
|
-
const logger$
|
|
9576
|
+
var import_cjs$27 = require_cjs();
|
|
9577
|
+
const logger$29 = getLogger();
|
|
9578
9578
|
const GET_PARAMS = {
|
|
9579
9579
|
method: "GET",
|
|
9580
9580
|
headers: { Accept: "application/json" }
|
|
@@ -9609,9 +9609,9 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9609
9609
|
constructor(baseURL, getCredential, options = {}) {
|
|
9610
9610
|
this.baseURL = baseURL;
|
|
9611
9611
|
this.getCredential = getCredential;
|
|
9612
|
-
this._responses$ = new import_cjs$
|
|
9613
|
-
this._errors$ = new import_cjs$
|
|
9614
|
-
this._status$ = new import_cjs$
|
|
9612
|
+
this._responses$ = new import_cjs$27.Subject();
|
|
9613
|
+
this._errors$ = new import_cjs$27.Subject();
|
|
9614
|
+
this._status$ = new import_cjs$27.BehaviorSubject("idle");
|
|
9615
9615
|
this.maxRetries = options.maxRetries ?? HTTPRequestController.defaultMaxRetries;
|
|
9616
9616
|
this.retryDelayMin = options.retryDelayMin ?? HTTPRequestController.defaultRetryDelayMinMs;
|
|
9617
9617
|
this.retryDelayMax = options.retryDelayMax ?? HTTPRequestController.defaultRetryDelayMaxMs;
|
|
@@ -9637,7 +9637,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9637
9637
|
this._responses$.next(response);
|
|
9638
9638
|
return response;
|
|
9639
9639
|
} catch (error) {
|
|
9640
|
-
logger$
|
|
9640
|
+
logger$29.error("[HTTPRequestController] Request error:", error);
|
|
9641
9641
|
this._status$.next("error");
|
|
9642
9642
|
const err = error instanceof Error ? error : new Error("HTTP request failed", { cause: error });
|
|
9643
9643
|
this._errors$.next(err);
|
|
@@ -9664,7 +9664,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9664
9664
|
const url = this.buildURL(request.url);
|
|
9665
9665
|
const headers = this.buildHeaders(request.headers);
|
|
9666
9666
|
const timeout$5 = request.timeout ?? this.requestTimeout;
|
|
9667
|
-
logger$
|
|
9667
|
+
logger$29.debug("[HTTPRequestController] Executing request:", {
|
|
9668
9668
|
method: request.method,
|
|
9669
9669
|
url,
|
|
9670
9670
|
headers: Object.keys(headers).reduce((acc, key) => {
|
|
@@ -9684,7 +9684,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9684
9684
|
});
|
|
9685
9685
|
clearTimeout(timeoutId);
|
|
9686
9686
|
const httpResponse = await this.convertResponse(response);
|
|
9687
|
-
logger$
|
|
9687
|
+
logger$29.debug("[HTTPRequestController] Response received:", {
|
|
9688
9688
|
status: response.status,
|
|
9689
9689
|
statusText: response.statusText,
|
|
9690
9690
|
headers: [...response.headers.entries()],
|
|
@@ -9694,7 +9694,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9694
9694
|
} catch (error) {
|
|
9695
9695
|
clearTimeout(timeoutId);
|
|
9696
9696
|
if (error instanceof Error && error.name === "AbortError") throw new RequestTimeoutError(`Request timeout after ${timeout$5}ms`, { cause: error });
|
|
9697
|
-
logger$
|
|
9697
|
+
logger$29.error("[HTTPRequestController] Request failed:", error);
|
|
9698
9698
|
throw error;
|
|
9699
9699
|
}
|
|
9700
9700
|
}
|
|
@@ -9708,8 +9708,8 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9708
9708
|
const credential = this.getCredential();
|
|
9709
9709
|
if (credential.token) {
|
|
9710
9710
|
headers.Authorization = `Bearer ${credential.token}`;
|
|
9711
|
-
logger$
|
|
9712
|
-
} else logger$
|
|
9711
|
+
logger$29.debug("[HTTPRequestController] Using Bearer token auth, token length:", credential.token.length);
|
|
9712
|
+
} else logger$29.warn("[HTTPRequestController] No credentials available for authentication");
|
|
9713
9713
|
return headers;
|
|
9714
9714
|
}
|
|
9715
9715
|
/**
|
|
@@ -9858,6 +9858,19 @@ const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
|
|
|
9858
9858
|
const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
|
|
9859
9859
|
const DEFAULT_DEVICE_POLLING_INTERVAL_MS = 0;
|
|
9860
9860
|
const PREFERENCES_STORAGE_KEY = "sw:preferences";
|
|
9861
|
+
/** Scope value that enables automatic token refresh. */
|
|
9862
|
+
const SAT_REFRESH_SCOPE = "sat:refresh";
|
|
9863
|
+
/** API endpoints for device token operations. */
|
|
9864
|
+
const DEVICE_TOKEN_ENDPOINT = "/api/fabric/subscriber/devices/token";
|
|
9865
|
+
const DEVICE_REFRESH_ENDPOINT = "/api/fabric/subscriber/devices/refresh";
|
|
9866
|
+
/** Default device token TTL in seconds (15 minutes). */
|
|
9867
|
+
const DEVICE_TOKEN_DEFAULT_EXPIRE_IN = 900;
|
|
9868
|
+
/** Buffer time in milliseconds before expiry to trigger refresh. */
|
|
9869
|
+
const DEVICE_TOKEN_REFRESH_BUFFER_MS = 3e4;
|
|
9870
|
+
/** Maximum retry attempts for device token refresh on transient failure. */
|
|
9871
|
+
const DEVICE_TOKEN_REFRESH_MAX_RETRIES = 3;
|
|
9872
|
+
/** Base delay in milliseconds for exponential backoff on refresh retry. */
|
|
9873
|
+
const DEVICE_TOKEN_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9861
9874
|
/** JSON-RPC error code for requester validation failure (corrupted auth state). */
|
|
9862
9875
|
const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
|
|
9863
9876
|
/** JSON-RPC error code for invalid params (e.g., missing authentication block). */
|
|
@@ -9948,7 +9961,7 @@ function fromMsToSec(milliseconds) {
|
|
|
9948
9961
|
|
|
9949
9962
|
//#endregion
|
|
9950
9963
|
//#region src/containers/PreferencesContainer.ts
|
|
9951
|
-
const logger$
|
|
9964
|
+
const logger$28 = getLogger();
|
|
9952
9965
|
var PreferencesContainer = class PreferencesContainer {
|
|
9953
9966
|
static get instance() {
|
|
9954
9967
|
this._instance ??= new PreferencesContainer();
|
|
@@ -10610,7 +10623,7 @@ var ClientPreferences = class {
|
|
|
10610
10623
|
if (!this._storage) return;
|
|
10611
10624
|
const data = collectStoredPreferences();
|
|
10612
10625
|
this._storage.setItem(PREFERENCES_STORAGE_KEY, data, "local").catch((error) => {
|
|
10613
|
-
logger$
|
|
10626
|
+
logger$28.error(`[ClientPreferences] Failed to save preferences: ${String(error)}`);
|
|
10614
10627
|
});
|
|
10615
10628
|
}
|
|
10616
10629
|
/** Loads preferences from storage and applies them to the container. */
|
|
@@ -10619,15 +10632,15 @@ var ClientPreferences = class {
|
|
|
10619
10632
|
this._storage.getItem(PREFERENCES_STORAGE_KEY, "local").then((stored) => {
|
|
10620
10633
|
if (stored) applyStoredPreferences(stored);
|
|
10621
10634
|
}).catch((error) => {
|
|
10622
|
-
logger$
|
|
10635
|
+
logger$28.error(`[ClientPreferences] Failed to load preferences: ${String(error)}`);
|
|
10623
10636
|
});
|
|
10624
10637
|
}
|
|
10625
10638
|
};
|
|
10626
10639
|
|
|
10627
10640
|
//#endregion
|
|
10628
10641
|
//#region src/controllers/NavigatorDeviceController.ts
|
|
10629
|
-
var import_cjs$
|
|
10630
|
-
const logger$
|
|
10642
|
+
var import_cjs$26 = require_cjs();
|
|
10643
|
+
const logger$27 = getLogger();
|
|
10631
10644
|
/** Maps a device kind to its storage key. */
|
|
10632
10645
|
const DEVICE_STORAGE_KEYS = {
|
|
10633
10646
|
audioinput: DEVICE_STORAGE_KEY_AUDIO_INPUT,
|
|
@@ -10649,7 +10662,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10649
10662
|
super();
|
|
10650
10663
|
this.webRTCApiProvider = webRTCApiProvider;
|
|
10651
10664
|
this.deviceChangeHandler = () => {
|
|
10652
|
-
logger$
|
|
10665
|
+
logger$27.debug("[DeviceController] Device change detected");
|
|
10653
10666
|
this.enumerateDevices();
|
|
10654
10667
|
};
|
|
10655
10668
|
this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
|
|
@@ -10686,17 +10699,17 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10686
10699
|
return {};
|
|
10687
10700
|
}
|
|
10688
10701
|
get errors$() {
|
|
10689
|
-
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$
|
|
10702
|
+
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10690
10703
|
}
|
|
10691
10704
|
/** Observable that emits when the SDK auto-switches a device. */
|
|
10692
10705
|
get deviceRecovered$() {
|
|
10693
|
-
return this._deviceRecovered$.asObservable().pipe((0, import_cjs$
|
|
10706
|
+
return this._deviceRecovered$.asObservable().pipe((0, import_cjs$26.takeUntil)(this.destroyed$));
|
|
10694
10707
|
}
|
|
10695
10708
|
get videoInputDisabled$() {
|
|
10696
|
-
return this.cachedObservable("videoInputDisabled$", () => this._videoInputDisabled$.asObservable().pipe((0, import_cjs$
|
|
10709
|
+
return this.cachedObservable("videoInputDisabled$", () => this._videoInputDisabled$.asObservable().pipe((0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10697
10710
|
}
|
|
10698
10711
|
get audioInputDisabled$() {
|
|
10699
|
-
return this.cachedObservable("audioInputDisabled$", () => this._audioInputDisabled$.asObservable().pipe((0, import_cjs$
|
|
10712
|
+
return this.cachedObservable("audioInputDisabled$", () => this._audioInputDisabled$.asObservable().pipe((0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10700
10713
|
}
|
|
10701
10714
|
get videoInputDisabled() {
|
|
10702
10715
|
return this._videoInputDisabled$.value;
|
|
@@ -10705,22 +10718,22 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10705
10718
|
return this._audioInputDisabled$.value;
|
|
10706
10719
|
}
|
|
10707
10720
|
get audioInputDevices$() {
|
|
10708
|
-
return this.cachedObservable("audioInputDevices$", () => this._devicesState$.pipe((0, import_cjs$
|
|
10721
|
+
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$)));
|
|
10709
10722
|
}
|
|
10710
10723
|
get audioOutputDevices$() {
|
|
10711
|
-
return this.cachedObservable("audioOutputDevices$", () => this._devicesState$.pipe((0, import_cjs$
|
|
10724
|
+
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$)));
|
|
10712
10725
|
}
|
|
10713
10726
|
get videoInputDevices$() {
|
|
10714
|
-
return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, import_cjs$
|
|
10727
|
+
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$)));
|
|
10715
10728
|
}
|
|
10716
10729
|
get selectedAudioInputDevice$() {
|
|
10717
|
-
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$
|
|
10730
|
+
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))));
|
|
10718
10731
|
}
|
|
10719
10732
|
get selectedAudioOutputDevice$() {
|
|
10720
|
-
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$
|
|
10733
|
+
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))));
|
|
10721
10734
|
}
|
|
10722
10735
|
get selectedVideoInputDevice$() {
|
|
10723
|
-
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$
|
|
10736
|
+
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))));
|
|
10724
10737
|
}
|
|
10725
10738
|
get selectedAudioInputDevice() {
|
|
10726
10739
|
if (this._audioInputDisabled$.value) return null;
|
|
@@ -10795,7 +10808,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10795
10808
|
if (device) this.persistDeviceSelection("audioinput", device);
|
|
10796
10809
|
}
|
|
10797
10810
|
selectVideoInputDevice(device) {
|
|
10798
|
-
logger$
|
|
10811
|
+
logger$27.debug("[DeviceController] Setting selected video input device:", device);
|
|
10799
10812
|
if (this._videoInputDisabled$.value && device) this._videoInputDisabled$.next(false);
|
|
10800
10813
|
const previous = this._selectedDevicesState$.value.videoinput;
|
|
10801
10814
|
if (previous && previous.deviceId !== device?.deviceId) this._deviceHistory.push("videoinput", previous);
|
|
@@ -10816,7 +10829,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10816
10829
|
}
|
|
10817
10830
|
init() {
|
|
10818
10831
|
this.loadPersistedDevices();
|
|
10819
|
-
this.subscribeTo(this._devicesState$.pipe((0, import_cjs$
|
|
10832
|
+
this.subscribeTo(this._devicesState$.pipe((0, import_cjs$26.debounceTime)(PreferencesContainer.instance.deviceDebounceTime)), (devicesState) => {
|
|
10820
10833
|
const currentSelected = this._selectedDevicesState$.value;
|
|
10821
10834
|
const newAudioInput = this._audioInputDisabled$.value ? null : this.resolveDevice("audioinput", devicesState.audioinput, currentSelected.audioinput, PreferencesContainer.instance.preferredAudioInput);
|
|
10822
10835
|
const newAudioOutput = this.resolveDevice("audiooutput", devicesState.audiooutput, currentSelected.audiooutput, PreferencesContainer.instance.preferredAudioOutput);
|
|
@@ -10852,7 +10865,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10852
10865
|
}
|
|
10853
10866
|
const fromHistory = this._deviceHistory.findInHistory(kind, devices);
|
|
10854
10867
|
if (fromHistory) {
|
|
10855
|
-
logger$
|
|
10868
|
+
logger$27.debug(`[DeviceController] Device disappeared, falling back to history: ${fromHistory.label}`);
|
|
10856
10869
|
this.emitDeviceRecovered(kind, selected, fromHistory, "device_disconnected");
|
|
10857
10870
|
return fromHistory;
|
|
10858
10871
|
}
|
|
@@ -10905,7 +10918,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10905
10918
|
try {
|
|
10906
10919
|
await this._storageManager.setItem(DEVICE_STORAGE_KEYS[kind], stored, "local");
|
|
10907
10920
|
} catch (error) {
|
|
10908
|
-
logger$
|
|
10921
|
+
logger$27.error(`[DeviceController] Failed to persist device selection for ${kind}:`, error);
|
|
10909
10922
|
}
|
|
10910
10923
|
}
|
|
10911
10924
|
async loadPersistedDevices() {
|
|
@@ -10921,7 +10934,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10921
10934
|
[kind]: stored
|
|
10922
10935
|
};
|
|
10923
10936
|
} catch (error) {
|
|
10924
|
-
logger$
|
|
10937
|
+
logger$27.error(`[DeviceController] Failed to load persisted device for ${kind}:`, error);
|
|
10925
10938
|
}
|
|
10926
10939
|
}
|
|
10927
10940
|
/** Clears device history, persisted selections, and re-enumerates devices. */
|
|
@@ -10938,8 +10951,8 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10938
10951
|
enableDeviceMonitoring() {
|
|
10939
10952
|
this.disableDeviceMonitoring();
|
|
10940
10953
|
this.webRTCApiProvider.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
|
|
10941
|
-
if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$
|
|
10942
|
-
logger$
|
|
10954
|
+
if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$26.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
|
|
10955
|
+
logger$27.debug("[DeviceController] Polling devices due to interval");
|
|
10943
10956
|
this.enumerateDevices();
|
|
10944
10957
|
});
|
|
10945
10958
|
this.enumerateDevices();
|
|
@@ -10965,13 +10978,13 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10965
10978
|
videoinput: []
|
|
10966
10979
|
});
|
|
10967
10980
|
this._devicesState$.next(devicesByKind);
|
|
10968
|
-
logger$
|
|
10981
|
+
logger$27.debug("[DeviceController] Devices enumerated:", {
|
|
10969
10982
|
audioInputs: devicesByKind.audioinput.length,
|
|
10970
10983
|
audioOutputs: devicesByKind.audiooutput.length,
|
|
10971
10984
|
videoInputs: devicesByKind.videoinput.length
|
|
10972
10985
|
});
|
|
10973
10986
|
} catch (error) {
|
|
10974
|
-
logger$
|
|
10987
|
+
logger$27.error("[DeviceController] Failed to enumerate devices:", error);
|
|
10975
10988
|
this._errors$.next(error);
|
|
10976
10989
|
}
|
|
10977
10990
|
}
|
|
@@ -10987,7 +11000,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10987
11000
|
stream.getTracks().forEach((t) => t.stop());
|
|
10988
11001
|
return capabilities;
|
|
10989
11002
|
} catch (error) {
|
|
10990
|
-
logger$
|
|
11003
|
+
logger$27.error("[DeviceController] Failed to get device capabilities:", error);
|
|
10991
11004
|
this._errors$.next(error);
|
|
10992
11005
|
throw error;
|
|
10993
11006
|
}
|
|
@@ -11238,7 +11251,7 @@ var DependencyContainer = class {
|
|
|
11238
11251
|
|
|
11239
11252
|
//#endregion
|
|
11240
11253
|
//#region src/controllers/CryptoController.ts
|
|
11241
|
-
const logger$
|
|
11254
|
+
const logger$26 = getLogger();
|
|
11242
11255
|
const DPOP_DB_NAME = "sw-dpop";
|
|
11243
11256
|
const DPOP_DB_VERSION = 1;
|
|
11244
11257
|
const DPOP_STORE_NAME = "keys";
|
|
@@ -11297,7 +11310,7 @@ async function loadKeyPairFromDB() {
|
|
|
11297
11310
|
tx.oncomplete = () => db.close();
|
|
11298
11311
|
});
|
|
11299
11312
|
} catch (error) {
|
|
11300
|
-
logger$
|
|
11313
|
+
logger$26.warn("[DPoP] Failed to load key pair from IndexedDB:", error);
|
|
11301
11314
|
return null;
|
|
11302
11315
|
}
|
|
11303
11316
|
}
|
|
@@ -11317,7 +11330,7 @@ async function saveKeyPairToDB(keyPair) {
|
|
|
11317
11330
|
};
|
|
11318
11331
|
});
|
|
11319
11332
|
} catch (error) {
|
|
11320
|
-
logger$
|
|
11333
|
+
logger$26.warn("[DPoP] Failed to save key pair to IndexedDB:", error);
|
|
11321
11334
|
}
|
|
11322
11335
|
}
|
|
11323
11336
|
async function deleteKeyPairFromDB() {
|
|
@@ -11336,7 +11349,7 @@ async function deleteKeyPairFromDB() {
|
|
|
11336
11349
|
};
|
|
11337
11350
|
});
|
|
11338
11351
|
} catch (error) {
|
|
11339
|
-
logger$
|
|
11352
|
+
logger$26.warn("[DPoP] Failed to delete key pair from IndexedDB:", error);
|
|
11340
11353
|
}
|
|
11341
11354
|
}
|
|
11342
11355
|
/**
|
|
@@ -11396,13 +11409,13 @@ var CryptoController = class {
|
|
|
11396
11409
|
this._publicJwk = await crypto.subtle.exportKey("jwk", stored.publicKey);
|
|
11397
11410
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11398
11411
|
this._initialized = true;
|
|
11399
|
-
logger$
|
|
11412
|
+
logger$26.debug("[DPoP] Key pair restored from IndexedDB, fingerprint:", this._fingerprint);
|
|
11400
11413
|
return this._fingerprint;
|
|
11401
11414
|
} catch (error) {
|
|
11402
|
-
logger$
|
|
11415
|
+
logger$26.warn("[DPoP] Stored key pair unusable, generating new one:", error);
|
|
11403
11416
|
await deleteKeyPairFromDB();
|
|
11404
11417
|
}
|
|
11405
|
-
logger$
|
|
11418
|
+
logger$26.debug("[DPoP] Generating RSA key pair");
|
|
11406
11419
|
this._keyPair = await crypto.subtle.generateKey({
|
|
11407
11420
|
name: "RSASSA-PKCS1-v1_5",
|
|
11408
11421
|
modulusLength: 2048,
|
|
@@ -11417,7 +11430,7 @@ var CryptoController = class {
|
|
|
11417
11430
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11418
11431
|
this._initialized = true;
|
|
11419
11432
|
await saveKeyPairToDB(this._keyPair);
|
|
11420
|
-
logger$
|
|
11433
|
+
logger$26.debug("[DPoP] Key pair generated and persisted, fingerprint:", this._fingerprint);
|
|
11421
11434
|
return this._fingerprint;
|
|
11422
11435
|
}
|
|
11423
11436
|
/**
|
|
@@ -11483,7 +11496,7 @@ var CryptoController = class {
|
|
|
11483
11496
|
this._fingerprint = null;
|
|
11484
11497
|
this._initialized = false;
|
|
11485
11498
|
deleteKeyPairFromDB();
|
|
11486
|
-
logger$
|
|
11499
|
+
logger$26.debug("[DPoP] Controller destroyed");
|
|
11487
11500
|
}
|
|
11488
11501
|
get publicJwk() {
|
|
11489
11502
|
if (!this._publicJwk) throw new DPoPInitError("CryptoController not initialized. Call init() first.");
|
|
@@ -11506,8 +11519,8 @@ var CryptoController = class {
|
|
|
11506
11519
|
|
|
11507
11520
|
//#endregion
|
|
11508
11521
|
//#region src/controllers/NetworkMonitor.ts
|
|
11509
|
-
var import_cjs$
|
|
11510
|
-
const logger$
|
|
11522
|
+
var import_cjs$25 = require_cjs();
|
|
11523
|
+
const logger$25 = getLogger();
|
|
11511
11524
|
/**
|
|
11512
11525
|
* Safely check whether we are running in a browser environment
|
|
11513
11526
|
* with `window` and the relevant event targets.
|
|
@@ -11550,13 +11563,13 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11550
11563
|
this.attachListeners();
|
|
11551
11564
|
}
|
|
11552
11565
|
get isOnline$() {
|
|
11553
|
-
return this._isOnline$.asObservable().pipe((0, import_cjs$
|
|
11566
|
+
return this._isOnline$.asObservable().pipe((0, import_cjs$25.takeUntil)(this._destroyed$));
|
|
11554
11567
|
}
|
|
11555
11568
|
get isOnline() {
|
|
11556
11569
|
return this._isOnline$.value;
|
|
11557
11570
|
}
|
|
11558
11571
|
get networkChange$() {
|
|
11559
|
-
return this._networkChange$.asObservable().pipe((0, import_cjs$
|
|
11572
|
+
return this._networkChange$.asObservable().pipe((0, import_cjs$25.takeUntil)(this._destroyed$));
|
|
11560
11573
|
}
|
|
11561
11574
|
destroy() {
|
|
11562
11575
|
this.removeListeners();
|
|
@@ -11564,7 +11577,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11564
11577
|
}
|
|
11565
11578
|
attachListeners() {
|
|
11566
11579
|
if (!hasBrowserNetworkEvents()) {
|
|
11567
|
-
logger$
|
|
11580
|
+
logger$25.debug("NetworkMonitor: no browser environment detected, skipping event listeners");
|
|
11568
11581
|
return;
|
|
11569
11582
|
}
|
|
11570
11583
|
window.addEventListener("online", this._onOnline);
|
|
@@ -11572,7 +11585,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11572
11585
|
const connection = getNetworkConnection();
|
|
11573
11586
|
if (connection) connection.addEventListener("change", this._onConnectionChange);
|
|
11574
11587
|
this._listenersAttached = true;
|
|
11575
|
-
logger$
|
|
11588
|
+
logger$25.debug("NetworkMonitor: event listeners attached");
|
|
11576
11589
|
}
|
|
11577
11590
|
removeListeners() {
|
|
11578
11591
|
if (!this._listenersAttached) return;
|
|
@@ -11583,10 +11596,10 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11583
11596
|
if (connection) connection.removeEventListener("change", this._onConnectionChange);
|
|
11584
11597
|
}
|
|
11585
11598
|
this._listenersAttached = false;
|
|
11586
|
-
logger$
|
|
11599
|
+
logger$25.debug("NetworkMonitor: event listeners removed");
|
|
11587
11600
|
}
|
|
11588
11601
|
handleOnline() {
|
|
11589
|
-
logger$
|
|
11602
|
+
logger$25.info("NetworkMonitor: browser went online");
|
|
11590
11603
|
this._isOnline$.next(true);
|
|
11591
11604
|
this._networkChange$.next({
|
|
11592
11605
|
type: "online",
|
|
@@ -11595,7 +11608,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11595
11608
|
});
|
|
11596
11609
|
}
|
|
11597
11610
|
handleOffline() {
|
|
11598
|
-
logger$
|
|
11611
|
+
logger$25.info("NetworkMonitor: browser went offline");
|
|
11599
11612
|
this._isOnline$.next(false);
|
|
11600
11613
|
this._networkChange$.next({
|
|
11601
11614
|
type: "offline",
|
|
@@ -11604,7 +11617,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11604
11617
|
}
|
|
11605
11618
|
handleConnectionChange() {
|
|
11606
11619
|
const networkType = getNetworkType();
|
|
11607
|
-
logger$
|
|
11620
|
+
logger$25.info(`NetworkMonitor: connection changed — effectiveType=${networkType ?? "unknown"}`);
|
|
11608
11621
|
this._networkChange$.next({
|
|
11609
11622
|
type: "connection_change",
|
|
11610
11623
|
timestamp: Date.now(),
|
|
@@ -11719,8 +11732,8 @@ function getNavigatorMediaDevices() {
|
|
|
11719
11732
|
|
|
11720
11733
|
//#endregion
|
|
11721
11734
|
//#region src/controllers/PreflightRunner.ts
|
|
11722
|
-
var import_cjs$
|
|
11723
|
-
const logger$
|
|
11735
|
+
var import_cjs$24 = require_cjs();
|
|
11736
|
+
const logger$24 = getLogger();
|
|
11724
11737
|
const DEFAULT_MEDIA_TEST_DURATION_S = 10;
|
|
11725
11738
|
const ICE_GATHERING_TIMEOUT_MS = 1e4;
|
|
11726
11739
|
const SIGNALING_RTT_TIMEOUT_MS = 5e3;
|
|
@@ -11769,7 +11782,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11769
11782
|
if (!this._options.skipMediaTest) try {
|
|
11770
11783
|
bandwidth = await this.testMediaBandwidth(destination);
|
|
11771
11784
|
} catch (error) {
|
|
11772
|
-
logger$
|
|
11785
|
+
logger$24.warn("[PreflightRunner] Media bandwidth test failed:", error);
|
|
11773
11786
|
warnings.push("Media bandwidth test failed");
|
|
11774
11787
|
}
|
|
11775
11788
|
return {
|
|
@@ -11781,7 +11794,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11781
11794
|
warnings
|
|
11782
11795
|
};
|
|
11783
11796
|
} catch (error) {
|
|
11784
|
-
logger$
|
|
11797
|
+
logger$24.error("[PreflightRunner] Preflight test failed:", error);
|
|
11785
11798
|
throw new PreflightError("preflight", error instanceof Error ? error : new Error(String(error)));
|
|
11786
11799
|
} finally {
|
|
11787
11800
|
this.destroy();
|
|
@@ -11812,7 +11825,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11812
11825
|
if (track.kind === "video" && track.readyState === "live") videoWorking = true;
|
|
11813
11826
|
}
|
|
11814
11827
|
} catch (error) {
|
|
11815
|
-
logger$
|
|
11828
|
+
logger$24.warn("[PreflightRunner] Device test failed:", error);
|
|
11816
11829
|
} finally {
|
|
11817
11830
|
if (audioStream) audioStream.getTracks().forEach((t) => t.stop());
|
|
11818
11831
|
}
|
|
@@ -11839,7 +11852,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11839
11852
|
const candidateTypes = /* @__PURE__ */ new Set();
|
|
11840
11853
|
const startTime = Date.now();
|
|
11841
11854
|
const gatheringComplete = new Promise((resolve) => {
|
|
11842
|
-
const timer$
|
|
11855
|
+
const timer$3 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
|
|
11843
11856
|
peerConnection.onicecandidate = (event) => {
|
|
11844
11857
|
if (event.candidate) {
|
|
11845
11858
|
const candidateStr = event.candidate.candidate;
|
|
@@ -11847,7 +11860,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11847
11860
|
if (candidateStr.includes("typ srflx")) candidateTypes.add("srflx");
|
|
11848
11861
|
if (candidateStr.includes("typ relay")) candidateTypes.add("relay");
|
|
11849
11862
|
} else {
|
|
11850
|
-
clearTimeout(timer$
|
|
11863
|
+
clearTimeout(timer$3);
|
|
11851
11864
|
resolve();
|
|
11852
11865
|
}
|
|
11853
11866
|
};
|
|
@@ -11870,7 +11883,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11870
11883
|
rttMs
|
|
11871
11884
|
};
|
|
11872
11885
|
} catch (error) {
|
|
11873
|
-
logger$
|
|
11886
|
+
logger$24.warn("[PreflightRunner] ICE connectivity test failed:", error);
|
|
11874
11887
|
return {
|
|
11875
11888
|
type: "failed",
|
|
11876
11889
|
turnReachable: false,
|
|
@@ -11888,7 +11901,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11888
11901
|
audio: true,
|
|
11889
11902
|
video: false
|
|
11890
11903
|
});
|
|
11891
|
-
await (0, import_cjs$
|
|
11904
|
+
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)));
|
|
11892
11905
|
const durationMs = this._options.duration * 1e3;
|
|
11893
11906
|
await new Promise((resolve) => setTimeout(resolve, durationMs));
|
|
11894
11907
|
const metrics = call.networkMetrics;
|
|
@@ -11917,8 +11930,8 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11917
11930
|
|
|
11918
11931
|
//#endregion
|
|
11919
11932
|
//#region src/controllers/VisibilityController.ts
|
|
11920
|
-
var import_cjs$
|
|
11921
|
-
const logger$
|
|
11933
|
+
var import_cjs$23 = require_cjs();
|
|
11934
|
+
const logger$23 = getLogger();
|
|
11922
11935
|
/**
|
|
11923
11936
|
* Checks whether the document visibility API is available.
|
|
11924
11937
|
*/
|
|
@@ -11955,15 +11968,15 @@ var VisibilityController = class extends Destroyable {
|
|
|
11955
11968
|
this._boundHandler = this._handleVisibilityChange.bind(this);
|
|
11956
11969
|
if (this._hasVisibilityApi) {
|
|
11957
11970
|
document.addEventListener("visibilitychange", this._boundHandler);
|
|
11958
|
-
logger$
|
|
11959
|
-
} else logger$
|
|
11971
|
+
logger$23.debug("VisibilityController: listening for visibilitychange events");
|
|
11972
|
+
} else logger$23.debug("VisibilityController: document visibility API not available, defaulting to visible");
|
|
11960
11973
|
}
|
|
11961
11974
|
/**
|
|
11962
11975
|
* Observable of the current visibility state.
|
|
11963
11976
|
* Emits 'visible' or 'hidden'. Always starts with the current state.
|
|
11964
11977
|
*/
|
|
11965
11978
|
get visibility$() {
|
|
11966
|
-
return this._visibility$.pipe((0, import_cjs$
|
|
11979
|
+
return this._visibility$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
|
|
11967
11980
|
}
|
|
11968
11981
|
/**
|
|
11969
11982
|
* The current visibility state value.
|
|
@@ -11976,12 +11989,12 @@ var VisibilityController = class extends Destroyable {
|
|
|
11976
11989
|
* Each event includes the previous state, new state, and timestamp.
|
|
11977
11990
|
*/
|
|
11978
11991
|
get visibilityChange$() {
|
|
11979
|
-
return this._visibilityChange$.pipe((0, import_cjs$
|
|
11992
|
+
return this._visibilityChange$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
|
|
11980
11993
|
}
|
|
11981
11994
|
destroy() {
|
|
11982
11995
|
if (this._hasVisibilityApi) {
|
|
11983
11996
|
document.removeEventListener("visibilitychange", this._boundHandler);
|
|
11984
|
-
logger$
|
|
11997
|
+
logger$23.debug("VisibilityController: removed visibilitychange listener");
|
|
11985
11998
|
}
|
|
11986
11999
|
super.destroy();
|
|
11987
12000
|
}
|
|
@@ -11999,7 +12012,7 @@ var VisibilityController = class extends Destroyable {
|
|
|
11999
12012
|
timestamp: Date.now()
|
|
12000
12013
|
};
|
|
12001
12014
|
this._visibilityChange$.next(changeEvent);
|
|
12002
|
-
logger$
|
|
12015
|
+
logger$23.debug("VisibilityController: visibility changed", {
|
|
12003
12016
|
from: previousState,
|
|
12004
12017
|
to: newState
|
|
12005
12018
|
});
|
|
@@ -12008,13 +12021,13 @@ var VisibilityController = class extends Destroyable {
|
|
|
12008
12021
|
|
|
12009
12022
|
//#endregion
|
|
12010
12023
|
//#region src/behaviors/Fetchable.ts
|
|
12011
|
-
var import_cjs$
|
|
12024
|
+
var import_cjs$22 = require_cjs();
|
|
12012
12025
|
var Fetchable = class extends Destroyable {
|
|
12013
12026
|
constructor(fromPath, http) {
|
|
12014
12027
|
super();
|
|
12015
12028
|
this.fromPath = fromPath;
|
|
12016
12029
|
this.http = http;
|
|
12017
|
-
this.fetched$ = (0, import_cjs$
|
|
12030
|
+
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$));
|
|
12018
12031
|
}
|
|
12019
12032
|
async fetch() {
|
|
12020
12033
|
const response = await this.http.request({
|
|
@@ -12249,7 +12262,7 @@ const RPCEventAckResponse = (id) => makeRPCResponse({
|
|
|
12249
12262
|
|
|
12250
12263
|
//#endregion
|
|
12251
12264
|
//#region src/managers/AttachManager.ts
|
|
12252
|
-
const logger$
|
|
12265
|
+
const logger$22 = getLogger();
|
|
12253
12266
|
var AttachManager = class {
|
|
12254
12267
|
constructor(storage, deviceController, reconnectCallsTimeout, attachKey) {
|
|
12255
12268
|
this.storage = storage;
|
|
@@ -12261,6 +12274,7 @@ var AttachManager = class {
|
|
|
12261
12274
|
const attached = await this.readAttached();
|
|
12262
12275
|
for (const callId of Object.keys(attached)) await this.detach({
|
|
12263
12276
|
id: callId,
|
|
12277
|
+
nodeId: attached[callId].nodeId,
|
|
12264
12278
|
mediaDirections: attached[callId].mediaDirections
|
|
12265
12279
|
});
|
|
12266
12280
|
}
|
|
@@ -12271,7 +12285,7 @@ var AttachManager = class {
|
|
|
12271
12285
|
try {
|
|
12272
12286
|
return await this.storage.getItem(this.attachKey) ?? {};
|
|
12273
12287
|
} catch (error) {
|
|
12274
|
-
logger$
|
|
12288
|
+
logger$22.warn("[AttachManager] Failed to retrieve attached calls from storage", error);
|
|
12275
12289
|
return {};
|
|
12276
12290
|
}
|
|
12277
12291
|
}
|
|
@@ -12279,20 +12293,20 @@ var AttachManager = class {
|
|
|
12279
12293
|
try {
|
|
12280
12294
|
await this.storage.setItem(this.attachKey, attached);
|
|
12281
12295
|
} catch (error) {
|
|
12282
|
-
logger$
|
|
12296
|
+
logger$22.warn("[AttachManager] Failed to write attached calls to storage", error);
|
|
12283
12297
|
}
|
|
12284
12298
|
}
|
|
12285
12299
|
async attach(call) {
|
|
12286
12300
|
if (!call.to) {
|
|
12287
|
-
logger$
|
|
12301
|
+
logger$22.warn("[AttachManager] Skip attach for calls with no destination");
|
|
12288
12302
|
return;
|
|
12289
12303
|
}
|
|
12290
12304
|
const attachment = {
|
|
12305
|
+
nodeId: call.nodeId,
|
|
12291
12306
|
destination: call.to,
|
|
12292
12307
|
mediaDirections: call.mediaDirections,
|
|
12293
12308
|
audioInputDevice: call.mediaDirections.audio !== "inactive" ? this.deviceController.selectedAudioInputDevice : null,
|
|
12294
12309
|
videoInputDevice: call.mediaDirections.video !== "inactive" ? this.deviceController.selectedVideoInputDevice : null,
|
|
12295
|
-
nodeId: call.nodeId,
|
|
12296
12310
|
attachedAt: Date.now()
|
|
12297
12311
|
};
|
|
12298
12312
|
const updated = {
|
|
@@ -12335,15 +12349,15 @@ var AttachManager = class {
|
|
|
12335
12349
|
callId,
|
|
12336
12350
|
...options
|
|
12337
12351
|
});
|
|
12338
|
-
logger$
|
|
12352
|
+
logger$22.info(`[AttachManager] Reattached call ${callId} (attempt ${attempt})`);
|
|
12339
12353
|
succeeded = true;
|
|
12340
12354
|
break;
|
|
12341
12355
|
} catch (error) {
|
|
12342
|
-
logger$
|
|
12356
|
+
logger$22.warn(`[AttachManager] Reattach attempt ${attempt}/3 failed for call ${callId}:`, error);
|
|
12343
12357
|
if (attempt < 3) await new Promise((r) => setTimeout(r, (attempt + 1) * 1e3));
|
|
12344
12358
|
}
|
|
12345
12359
|
if (!succeeded) {
|
|
12346
|
-
logger$
|
|
12360
|
+
logger$22.warn(`[AttachManager] Reattach failed after 3 attempts for call ${callId}, removing reference`);
|
|
12347
12361
|
await this.detach({
|
|
12348
12362
|
id: callId,
|
|
12349
12363
|
mediaDirections: attachment.mediaDirections
|
|
@@ -12357,12 +12371,13 @@ var AttachManager = class {
|
|
|
12357
12371
|
*/
|
|
12358
12372
|
buildCallOptions(attachment) {
|
|
12359
12373
|
const { audio: audioDirection, video: videoDirection } = attachment.mediaDirections;
|
|
12360
|
-
const { audioInputDevice, videoInputDevice } = attachment;
|
|
12374
|
+
const { audioInputDevice, videoInputDevice, nodeId } = attachment;
|
|
12361
12375
|
const receiveAudio = audioDirection.includes("recv");
|
|
12362
12376
|
const receiveVideo = videoDirection.includes("recv");
|
|
12363
12377
|
const sendAudio = audioDirection.includes("send");
|
|
12364
12378
|
const sendVideo = videoDirection.includes("send");
|
|
12365
12379
|
return {
|
|
12380
|
+
nodeId,
|
|
12366
12381
|
receiveAudio,
|
|
12367
12382
|
receiveVideo,
|
|
12368
12383
|
inputAudioDeviceConstraints: sendAudio ? {
|
|
@@ -12373,7 +12388,6 @@ var AttachManager = class {
|
|
|
12373
12388
|
video: true,
|
|
12374
12389
|
...this.deviceController.deviceInfoToConstraints(videoInputDevice)
|
|
12375
12390
|
} : void 0,
|
|
12376
|
-
nodeId: attachment.nodeId ?? void 0,
|
|
12377
12391
|
reattach: true
|
|
12378
12392
|
};
|
|
12379
12393
|
}
|
|
@@ -13249,7 +13263,7 @@ var require_operators = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
13249
13263
|
//#endregion
|
|
13250
13264
|
//#region src/operators/filterNull.ts
|
|
13251
13265
|
var import_operators$1 = require_operators();
|
|
13252
|
-
var import_cjs$
|
|
13266
|
+
var import_cjs$21 = require_cjs();
|
|
13253
13267
|
/**
|
|
13254
13268
|
* RxJS operator that filters out `null` and `undefined` values with type narrowing.
|
|
13255
13269
|
*
|
|
@@ -13261,7 +13275,7 @@ var import_cjs$20 = require_cjs();
|
|
|
13261
13275
|
* ```
|
|
13262
13276
|
*/
|
|
13263
13277
|
function filterNull() {
|
|
13264
|
-
return (0, import_cjs$
|
|
13278
|
+
return (0, import_cjs$21.filter)((value) => value != null);
|
|
13265
13279
|
}
|
|
13266
13280
|
|
|
13267
13281
|
//#endregion
|
|
@@ -13389,7 +13403,7 @@ function computeCapabilities(capabilities) {
|
|
|
13389
13403
|
|
|
13390
13404
|
//#endregion
|
|
13391
13405
|
//#region src/core/capabilities/SelfCapabilities.ts
|
|
13392
|
-
var import_cjs$
|
|
13406
|
+
var import_cjs$20 = require_cjs();
|
|
13393
13407
|
/**
|
|
13394
13408
|
* SelfCapabilities manages the capability state for the self participant.
|
|
13395
13409
|
*
|
|
@@ -13425,7 +13439,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13425
13439
|
}
|
|
13426
13440
|
/** Observable for self member capabilities */
|
|
13427
13441
|
get self$() {
|
|
13428
|
-
return this.cachedObservable("self$", () => this._state$.pipe((0, import_cjs$
|
|
13442
|
+
return this.cachedObservable("self$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.self), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13429
13443
|
}
|
|
13430
13444
|
/** Current self member capabilities */
|
|
13431
13445
|
get self() {
|
|
@@ -13433,7 +13447,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13433
13447
|
}
|
|
13434
13448
|
/** Observable for other member capabilities */
|
|
13435
13449
|
get member$() {
|
|
13436
|
-
return this.cachedObservable("member$", () => this._state$.pipe((0, import_cjs$
|
|
13450
|
+
return this.cachedObservable("member$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.member), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13437
13451
|
}
|
|
13438
13452
|
/** Current other member capabilities */
|
|
13439
13453
|
get member() {
|
|
@@ -13441,7 +13455,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13441
13455
|
}
|
|
13442
13456
|
/** Observable for end call capability */
|
|
13443
13457
|
get end$() {
|
|
13444
|
-
return this.cachedObservable("end$", () => this._state$.pipe((0, import_cjs$
|
|
13458
|
+
return this.cachedObservable("end$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.end), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13445
13459
|
}
|
|
13446
13460
|
/** Current end call capability */
|
|
13447
13461
|
get end() {
|
|
@@ -13449,7 +13463,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13449
13463
|
}
|
|
13450
13464
|
/** Observable for set layout capability */
|
|
13451
13465
|
get setLayout$() {
|
|
13452
|
-
return this.cachedObservable("setLayout$", () => this._state$.pipe((0, import_cjs$
|
|
13466
|
+
return this.cachedObservable("setLayout$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.setLayout), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13453
13467
|
}
|
|
13454
13468
|
/** Current set layout capability */
|
|
13455
13469
|
get setLayout() {
|
|
@@ -13457,7 +13471,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13457
13471
|
}
|
|
13458
13472
|
/** Observable for send digit capability */
|
|
13459
13473
|
get sendDigit$() {
|
|
13460
|
-
return this.cachedObservable("sendDigit$", () => this._state$.pipe((0, import_cjs$
|
|
13474
|
+
return this.cachedObservable("sendDigit$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.sendDigit), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13461
13475
|
}
|
|
13462
13476
|
/** Current send digit capability */
|
|
13463
13477
|
get sendDigit() {
|
|
@@ -13465,7 +13479,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13465
13479
|
}
|
|
13466
13480
|
/** Observable for vmuted hide capability */
|
|
13467
13481
|
get vmutedHide$() {
|
|
13468
|
-
return this.cachedObservable("vmutedHide$", () => this._state$.pipe((0, import_cjs$
|
|
13482
|
+
return this.cachedObservable("vmutedHide$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.vmutedHide), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13469
13483
|
}
|
|
13470
13484
|
/** Current vmuted hide capability */
|
|
13471
13485
|
get vmutedHide() {
|
|
@@ -13473,7 +13487,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13473
13487
|
}
|
|
13474
13488
|
/** Observable for lock capability */
|
|
13475
13489
|
get lock$() {
|
|
13476
|
-
return this.cachedObservable("lock$", () => this._state$.pipe((0, import_cjs$
|
|
13490
|
+
return this.cachedObservable("lock$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.lock), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13477
13491
|
}
|
|
13478
13492
|
/** Current lock capability */
|
|
13479
13493
|
get lock() {
|
|
@@ -13481,7 +13495,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13481
13495
|
}
|
|
13482
13496
|
/** Observable for device capability */
|
|
13483
13497
|
get device$() {
|
|
13484
|
-
return this.cachedObservable("device$", () => this._state$.pipe((0, import_cjs$
|
|
13498
|
+
return this.cachedObservable("device$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.device), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13485
13499
|
}
|
|
13486
13500
|
/** Current device capability */
|
|
13487
13501
|
get device() {
|
|
@@ -13489,7 +13503,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13489
13503
|
}
|
|
13490
13504
|
/** Observable for screenshare capability */
|
|
13491
13505
|
get screenshare$() {
|
|
13492
|
-
return this.cachedObservable("screenshare$", () => this._state$.pipe((0, import_cjs$
|
|
13506
|
+
return this.cachedObservable("screenshare$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.screenshare), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13493
13507
|
}
|
|
13494
13508
|
/** Current screenshare capability */
|
|
13495
13509
|
get screenshare() {
|
|
@@ -13516,7 +13530,7 @@ function toggleHandraiseMethod(is) {
|
|
|
13516
13530
|
|
|
13517
13531
|
//#endregion
|
|
13518
13532
|
//#region src/core/entities/Participant.ts
|
|
13519
|
-
const logger$
|
|
13533
|
+
const logger$21 = getLogger();
|
|
13520
13534
|
const initialState = {};
|
|
13521
13535
|
/**
|
|
13522
13536
|
* Represents a participant in a call.
|
|
@@ -13894,7 +13908,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13894
13908
|
try {
|
|
13895
13909
|
await this.vertoManager.addScreenMedia();
|
|
13896
13910
|
} catch (error) {
|
|
13897
|
-
logger$
|
|
13911
|
+
logger$21.error("[Participant.startScreenShare] Screen share error:", error);
|
|
13898
13912
|
}
|
|
13899
13913
|
}
|
|
13900
13914
|
/** Observable of the current screen share status. */
|
|
@@ -13914,7 +13928,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13914
13928
|
try {
|
|
13915
13929
|
await this.vertoManager.addInputDevice(options);
|
|
13916
13930
|
} catch (error) {
|
|
13917
|
-
logger$
|
|
13931
|
+
logger$21.error("[Participant.startScreenShare] Screen share error:", error);
|
|
13918
13932
|
}
|
|
13919
13933
|
}
|
|
13920
13934
|
/** Removes an additional media input device by ID. */
|
|
@@ -13976,7 +13990,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13976
13990
|
*/
|
|
13977
13991
|
exitStudioModeIfActive() {
|
|
13978
13992
|
if (this._studioAudio$.value) {
|
|
13979
|
-
logger$
|
|
13993
|
+
logger$21.debug("[SelfParticipant] Exiting studio audio mode due to individual flag toggle");
|
|
13980
13994
|
this._studioAudio$.next(false);
|
|
13981
13995
|
}
|
|
13982
13996
|
}
|
|
@@ -14000,7 +14014,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14000
14014
|
try {
|
|
14001
14015
|
await super.mute();
|
|
14002
14016
|
} catch (error) {
|
|
14003
|
-
logger$
|
|
14017
|
+
logger$21.warn("[Participant.toggleAudioInput] Server Error while muting audio input, proceeding with local toggle anyway", error);
|
|
14004
14018
|
} finally {
|
|
14005
14019
|
this.vertoManager.muteMainAudioInputDevice();
|
|
14006
14020
|
}
|
|
@@ -14010,7 +14024,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14010
14024
|
try {
|
|
14011
14025
|
await super.unmute();
|
|
14012
14026
|
} catch (error) {
|
|
14013
|
-
logger$
|
|
14027
|
+
logger$21.warn("[Participant.toggleAudioInput] Server Error while unmuting audio input, proceeding with local toggle anyway", error);
|
|
14014
14028
|
} finally {
|
|
14015
14029
|
await this.vertoManager.unmuteMainAudioInputDevice();
|
|
14016
14030
|
}
|
|
@@ -14020,7 +14034,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14020
14034
|
try {
|
|
14021
14035
|
await super.muteVideo();
|
|
14022
14036
|
} catch (error) {
|
|
14023
|
-
logger$
|
|
14037
|
+
logger$21.warn("[Participant.toggleVideoInput] Server Error while muting video input, proceeding with local toggle anyway", error);
|
|
14024
14038
|
} finally {
|
|
14025
14039
|
this.vertoManager.muteMainVideoInputDevice();
|
|
14026
14040
|
}
|
|
@@ -14030,7 +14044,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14030
14044
|
try {
|
|
14031
14045
|
await super.unmuteVideo();
|
|
14032
14046
|
} catch (error) {
|
|
14033
|
-
logger$
|
|
14047
|
+
logger$21.warn("[Participant.toggleVideoInput] Server Error while unmuting video input, proceeding with local toggle anyway", error);
|
|
14034
14048
|
} finally {
|
|
14035
14049
|
await this.vertoManager.unmuteMainVideoInputDevice();
|
|
14036
14050
|
}
|
|
@@ -14134,7 +14148,7 @@ const getValueFrom = (obj, path, defaultValue) => {
|
|
|
14134
14148
|
|
|
14135
14149
|
//#endregion
|
|
14136
14150
|
//#region src/operators/filterEventAs.ts
|
|
14137
|
-
var import_cjs$
|
|
14151
|
+
var import_cjs$19 = require_cjs();
|
|
14138
14152
|
var import_operators = require_operators();
|
|
14139
14153
|
/**
|
|
14140
14154
|
* RxJS operator that filters events based on a predicate and maps matching events.
|
|
@@ -14168,7 +14182,7 @@ var import_operators = require_operators();
|
|
|
14168
14182
|
* ```
|
|
14169
14183
|
*/
|
|
14170
14184
|
function ifIsMap(predicate, mapFn) {
|
|
14171
|
-
return (0, import_cjs$
|
|
14185
|
+
return (0, import_cjs$19.pipe)((0, import_operators.filter)(predicate), (0, import_operators.map)(mapFn));
|
|
14172
14186
|
}
|
|
14173
14187
|
/**
|
|
14174
14188
|
* Generic RxJS operator that filters events using a type guard and extracts a property.
|
|
@@ -14210,38 +14224,38 @@ function ifIsMap(predicate, mapFn) {
|
|
|
14210
14224
|
* ```
|
|
14211
14225
|
*/
|
|
14212
14226
|
function filterAs(predicate, resultPath) {
|
|
14213
|
-
return (0, import_cjs$
|
|
14227
|
+
return (0, import_cjs$19.pipe)(ifIsMap(predicate, (event) => {
|
|
14214
14228
|
return getValueFrom(event, resultPath);
|
|
14215
14229
|
}), (0, import_operators.filter)((value) => value !== void 0));
|
|
14216
14230
|
}
|
|
14217
14231
|
|
|
14218
14232
|
//#endregion
|
|
14219
14233
|
//#region src/operators/throwOnRPCError.ts
|
|
14220
|
-
var import_cjs$
|
|
14221
|
-
const logger$
|
|
14234
|
+
var import_cjs$18 = require_cjs();
|
|
14235
|
+
const logger$20 = getLogger();
|
|
14222
14236
|
/**
|
|
14223
14237
|
* RxJS operator that throws a {@link JSONRPCError} when the RPC response contains an error.
|
|
14224
14238
|
* Passes successful responses through unchanged.
|
|
14225
14239
|
*/
|
|
14226
14240
|
function throwOnRPCError() {
|
|
14227
|
-
return (0, import_cjs$
|
|
14241
|
+
return (0, import_cjs$18.map)((response) => {
|
|
14228
14242
|
if (response.error) {
|
|
14229
|
-
logger$
|
|
14243
|
+
logger$20.error("[throwOnRPCError] RPC error response:", {
|
|
14230
14244
|
code: response.error.code,
|
|
14231
14245
|
message: response.error.message,
|
|
14232
14246
|
data: response.error.data
|
|
14233
14247
|
});
|
|
14234
14248
|
throw new JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
14235
14249
|
}
|
|
14236
|
-
logger$
|
|
14250
|
+
logger$20.debug("[throwOnRPCError] RPC successful response:", response);
|
|
14237
14251
|
return response;
|
|
14238
14252
|
});
|
|
14239
14253
|
}
|
|
14240
14254
|
|
|
14241
14255
|
//#endregion
|
|
14242
14256
|
//#region src/managers/CallEventsManager.ts
|
|
14243
|
-
var import_cjs$
|
|
14244
|
-
const logger$
|
|
14257
|
+
var import_cjs$17 = require_cjs();
|
|
14258
|
+
const logger$19 = getLogger();
|
|
14245
14259
|
const initialSessionState = {};
|
|
14246
14260
|
/** @internal */
|
|
14247
14261
|
var CallEventsManager = class extends Destroyable {
|
|
@@ -14257,7 +14271,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14257
14271
|
this.initSubscriptions();
|
|
14258
14272
|
}
|
|
14259
14273
|
get participants$() {
|
|
14260
|
-
return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$
|
|
14274
|
+
return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$17.map)((participantsRecord) => Object.values(participantsRecord))));
|
|
14261
14275
|
}
|
|
14262
14276
|
get participants() {
|
|
14263
14277
|
return Object.values(this._participants$.value);
|
|
@@ -14275,40 +14289,40 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14275
14289
|
return this.callIds.has(callId);
|
|
14276
14290
|
}
|
|
14277
14291
|
get recording$() {
|
|
14278
|
-
return this.cachedObservable("recording$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14292
|
+
return this.cachedObservable("recording$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.recording), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14279
14293
|
}
|
|
14280
14294
|
get recordings$() {
|
|
14281
|
-
return this.cachedObservable("recordings$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14295
|
+
return this.cachedObservable("recordings$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.recordings), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14282
14296
|
}
|
|
14283
14297
|
get streaming$() {
|
|
14284
|
-
return this.cachedObservable("streaming$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14298
|
+
return this.cachedObservable("streaming$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.streaming), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14285
14299
|
}
|
|
14286
14300
|
get streams$() {
|
|
14287
|
-
return this.cachedObservable("streams$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14301
|
+
return this.cachedObservable("streams$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.streams), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14288
14302
|
}
|
|
14289
14303
|
get playbacks$() {
|
|
14290
|
-
return this.cachedObservable("playbacks$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14304
|
+
return this.cachedObservable("playbacks$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.playbacks), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14291
14305
|
}
|
|
14292
14306
|
get raiseHandPriority$() {
|
|
14293
|
-
return this.cachedObservable("raiseHandPriority$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14307
|
+
return this.cachedObservable("raiseHandPriority$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.prioritize_handraise), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14294
14308
|
}
|
|
14295
14309
|
get locked$() {
|
|
14296
|
-
return this.cachedObservable("locked$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14310
|
+
return this.cachedObservable("locked$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.locked), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14297
14311
|
}
|
|
14298
14312
|
get meta$() {
|
|
14299
|
-
return this.cachedObservable("meta$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14313
|
+
return this.cachedObservable("meta$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.meta), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14300
14314
|
}
|
|
14301
14315
|
get capabilities$() {
|
|
14302
|
-
return this.cachedObservable("capabilities$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14316
|
+
return this.cachedObservable("capabilities$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.capabilities), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14303
14317
|
}
|
|
14304
14318
|
get layout$() {
|
|
14305
|
-
return this.cachedObservable("layout$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14319
|
+
return this.cachedObservable("layout$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layout_name), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14306
14320
|
}
|
|
14307
14321
|
get layouts$() {
|
|
14308
|
-
return this.cachedObservable("layouts$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14322
|
+
return this.cachedObservable("layouts$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layouts), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14309
14323
|
}
|
|
14310
14324
|
get layoutLayers$() {
|
|
14311
|
-
return this.cachedObservable("layoutLayers$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14325
|
+
return this.cachedObservable("layoutLayers$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layout_layers), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14312
14326
|
}
|
|
14313
14327
|
get self() {
|
|
14314
14328
|
return this._self$.value;
|
|
@@ -14345,7 +14359,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14345
14359
|
}
|
|
14346
14360
|
initSubscriptions() {
|
|
14347
14361
|
this.subscribeTo(this.callJoinedEvent$, (callJoinedEvent) => {
|
|
14348
|
-
logger$
|
|
14362
|
+
logger$19.debug("[CallEventsManager] Handling call.joined event for call/session IDs:", {
|
|
14349
14363
|
callId: callJoinedEvent.call_id,
|
|
14350
14364
|
roomSessionId: callJoinedEvent.room_session_id
|
|
14351
14365
|
});
|
|
@@ -14372,19 +14386,19 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14372
14386
|
if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
|
|
14373
14387
|
});
|
|
14374
14388
|
this.subscribeTo(this.memberUpdates$, (member) => {
|
|
14375
|
-
logger$
|
|
14389
|
+
logger$19.debug("[CallEventsManager] Handling member update event for member ID:", member);
|
|
14376
14390
|
this.upsertParticipant(member);
|
|
14377
14391
|
});
|
|
14378
14392
|
this.subscribeTo(this.webRtcCallSession.memberLeft$, (memberLeftEvent) => {
|
|
14379
|
-
logger$
|
|
14393
|
+
logger$19.debug("[CallEventsManager] Handling member.left event for member ID:", memberLeftEvent.member.member_id);
|
|
14380
14394
|
const participants = { ...this._participants$.value };
|
|
14381
14395
|
if (memberLeftEvent.member.member_id in participants) {
|
|
14382
14396
|
delete participants[memberLeftEvent.member.member_id];
|
|
14383
14397
|
this._participants$.next(participants);
|
|
14384
|
-
} else logger$
|
|
14398
|
+
} else logger$19.warn(`[CallEventsManager] Received member.left event for unknown member ID: ${memberLeftEvent.member.member_id}`);
|
|
14385
14399
|
});
|
|
14386
14400
|
this.subscribeTo(this.webRtcCallSession.callUpdated$, (callUpdatedEvent) => {
|
|
14387
|
-
logger$
|
|
14401
|
+
logger$19.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
|
|
14388
14402
|
const roomSession = callUpdatedEvent.room_session;
|
|
14389
14403
|
this._sessionState$.next({
|
|
14390
14404
|
...this._sessionState$.value,
|
|
@@ -14399,7 +14413,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14399
14413
|
});
|
|
14400
14414
|
});
|
|
14401
14415
|
this.subscribeTo(this.layoutChangedEvent$, (layoutChangedEvent) => {
|
|
14402
|
-
logger$
|
|
14416
|
+
logger$19.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
|
|
14403
14417
|
this._sessionState$.next({
|
|
14404
14418
|
...this._sessionState$.value,
|
|
14405
14419
|
layout_name: layoutChangedEvent.id,
|
|
@@ -14409,10 +14423,10 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14409
14423
|
});
|
|
14410
14424
|
}
|
|
14411
14425
|
updateParticipantPositions(layoutChangedEvent) {
|
|
14412
|
-
if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$
|
|
14426
|
+
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.");
|
|
14413
14427
|
layoutChangedEvent.layers.filter((layer) => !!layer.member_id).filter((layer) => {
|
|
14414
14428
|
if (!(layer.member_id in this._participants$.value)) {
|
|
14415
|
-
logger$
|
|
14429
|
+
logger$19.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
|
|
14416
14430
|
return false;
|
|
14417
14431
|
}
|
|
14418
14432
|
return true;
|
|
@@ -14435,7 +14449,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14435
14449
|
layouts: response.result.layouts
|
|
14436
14450
|
});
|
|
14437
14451
|
}).catch((error) => {
|
|
14438
|
-
logger$
|
|
14452
|
+
logger$19.error("[CallEventsManager] Error fetching layouts:", error);
|
|
14439
14453
|
});
|
|
14440
14454
|
}
|
|
14441
14455
|
updateParticipants(members) {
|
|
@@ -14451,7 +14465,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14451
14465
|
}
|
|
14452
14466
|
const participant = this._participants$.value[member.member_id];
|
|
14453
14467
|
const oldValue = participant.value;
|
|
14454
|
-
logger$
|
|
14468
|
+
logger$19.debug("[CallEventsManager] Updating participant:", member.member_id, {
|
|
14455
14469
|
oldValue,
|
|
14456
14470
|
newValue: member
|
|
14457
14471
|
});
|
|
@@ -14463,18 +14477,18 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14463
14477
|
this._participants$.next(this._participants$.value);
|
|
14464
14478
|
}
|
|
14465
14479
|
get callJoinedEvent$() {
|
|
14466
|
-
return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$
|
|
14467
|
-
logger$
|
|
14480
|
+
return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$17.filter)(isCallJoinedPayload), (0, import_cjs$17.tap)((event) => {
|
|
14481
|
+
logger$19.debug("[CallEventsManager] Call joined event:", event);
|
|
14468
14482
|
})));
|
|
14469
14483
|
}
|
|
14470
14484
|
get layoutChangedEvent$() {
|
|
14471
|
-
return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$
|
|
14472
|
-
logger$
|
|
14485
|
+
return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$17.tap)((event) => {
|
|
14486
|
+
logger$19.debug("[CallEventsManager] Layout changed event:", event);
|
|
14473
14487
|
})));
|
|
14474
14488
|
}
|
|
14475
14489
|
get memberUpdates$() {
|
|
14476
|
-
return this.cachedObservable("memberUpdates$", () => (0, import_cjs$
|
|
14477
|
-
logger$
|
|
14490
|
+
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) => {
|
|
14491
|
+
logger$19.debug("[CallEventsManager] Member update event:", event);
|
|
14478
14492
|
})));
|
|
14479
14493
|
}
|
|
14480
14494
|
destroy() {
|
|
@@ -14730,8 +14744,8 @@ function appendStereoParams(fmtpLine, maxBitrate) {
|
|
|
14730
14744
|
|
|
14731
14745
|
//#endregion
|
|
14732
14746
|
//#region src/controllers/ICEGatheringController.ts
|
|
14733
|
-
var import_cjs$
|
|
14734
|
-
const logger$
|
|
14747
|
+
var import_cjs$16 = require_cjs();
|
|
14748
|
+
const logger$18 = getLogger();
|
|
14735
14749
|
var ICEGatheringController = class extends Destroyable {
|
|
14736
14750
|
constructor(peerConnection, peerConnectionControllerNegotiating$, options = {}) {
|
|
14737
14751
|
super();
|
|
@@ -14739,23 +14753,23 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14739
14753
|
this.peerConnectionControllerNegotiating$ = peerConnectionControllerNegotiating$;
|
|
14740
14754
|
this.onicegatheringstatechangeHandler = () => {
|
|
14741
14755
|
const { iceGatheringState } = this.peerConnection;
|
|
14742
|
-
logger$
|
|
14756
|
+
logger$18.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
|
|
14743
14757
|
if (iceGatheringState === "gathering") this._iceCandidatesState.next({
|
|
14744
14758
|
state: "gathering",
|
|
14745
14759
|
validSDP: false
|
|
14746
14760
|
});
|
|
14747
14761
|
};
|
|
14748
14762
|
this.onicecandidateHandler = (event) => {
|
|
14749
|
-
logger$
|
|
14763
|
+
logger$18.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
|
|
14750
14764
|
this.removeTimer("iceCandidateTimer");
|
|
14751
14765
|
if (event.candidate) this.iceCandidateTimer = setTimeout(() => {
|
|
14752
14766
|
if (this.peerConnection.iceGatheringState !== "complete") {
|
|
14753
|
-
logger$
|
|
14767
|
+
logger$18.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
|
|
14754
14768
|
this.handleICECandidateTimeout();
|
|
14755
14769
|
}
|
|
14756
14770
|
}, this.iceCandidateTimeout);
|
|
14757
14771
|
else {
|
|
14758
|
-
logger$
|
|
14772
|
+
logger$18.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
|
|
14759
14773
|
this.removeTimer("iceGatheringTimer");
|
|
14760
14774
|
this.handleICEGatheringComplete();
|
|
14761
14775
|
}
|
|
@@ -14768,12 +14782,12 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14768
14782
|
this.iceGatheringTimeout = options.iceGatheringTimeout ?? DEFAULT_ICE_GATHERING_TIMEOUT_MS;
|
|
14769
14783
|
this.relayOnly = options.relayOnly ?? false;
|
|
14770
14784
|
this.setupEventListeners();
|
|
14771
|
-
this.subscribeTo(this.peerConnectionControllerNegotiating$.pipe((0, import_cjs$
|
|
14785
|
+
this.subscribeTo(this.peerConnectionControllerNegotiating$.pipe((0, import_cjs$16.filter)((isNegotiating) => isNegotiating)), (isNegotiating) => {
|
|
14772
14786
|
if (isNegotiating) {
|
|
14773
14787
|
this.setupEventListeners();
|
|
14774
14788
|
this.iceGatheringTimer = setTimeout(() => {
|
|
14775
14789
|
if (this.peerConnection.iceGatheringState !== "complete") {
|
|
14776
|
-
logger$
|
|
14790
|
+
logger$18.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
|
|
14777
14791
|
this.handleICEGatheringTimeout();
|
|
14778
14792
|
}
|
|
14779
14793
|
}, this.iceGatheringTimeout);
|
|
@@ -14787,7 +14801,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14787
14801
|
this.peerConnection.addEventListener("icegatheringstatechange", this.onicegatheringstatechangeHandler);
|
|
14788
14802
|
}
|
|
14789
14803
|
get iceCandidatesState$() {
|
|
14790
|
-
return this._iceCandidatesState.pipe((0, import_cjs$
|
|
14804
|
+
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));
|
|
14791
14805
|
}
|
|
14792
14806
|
get hasValidLocalDescriptionSDP() {
|
|
14793
14807
|
const sdp = this.peerConnection.localDescription?.sdp;
|
|
@@ -14800,9 +14814,9 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14800
14814
|
this.relayOnly = value;
|
|
14801
14815
|
}
|
|
14802
14816
|
handleICEGatheringComplete() {
|
|
14803
|
-
logger$
|
|
14804
|
-
logger$
|
|
14805
|
-
logger$
|
|
14817
|
+
logger$18.debug("[ICEGatheringController] Handling ICE gathering complete");
|
|
14818
|
+
logger$18.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`);
|
|
14819
|
+
logger$18.debug("[ICEGatheringController] ICE gathering complete");
|
|
14806
14820
|
this._iceCandidatesState.next({
|
|
14807
14821
|
state: "complete",
|
|
14808
14822
|
validSDP: this.hasValidLocalDescriptionSDP
|
|
@@ -14818,21 +14832,21 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14818
14832
|
this.removeTimer("iceGatheringTimer");
|
|
14819
14833
|
const validSDP = this.hasValidLocalDescriptionSDP;
|
|
14820
14834
|
if (validSDP) {
|
|
14821
|
-
logger$
|
|
14835
|
+
logger$18.debug("[ICEGatheringController] Local SDP is valid");
|
|
14822
14836
|
this._iceCandidatesState.next({
|
|
14823
14837
|
state: "timeout",
|
|
14824
14838
|
validSDP
|
|
14825
14839
|
});
|
|
14826
14840
|
this.stopGathering();
|
|
14827
|
-
} else logger$
|
|
14841
|
+
} else logger$18.debug("### ICE gathering timeout\n", this.peerConnection.localDescription?.sdp);
|
|
14828
14842
|
}
|
|
14829
14843
|
handleICECandidateTimeout() {
|
|
14830
14844
|
if (this.iceCandidateTimer) this.removeTimer("iceCandidateTimer");
|
|
14831
|
-
logger$
|
|
14845
|
+
logger$18.warn("[ICEGatheringController] ICE candidate timeout");
|
|
14832
14846
|
const validSDP = this.hasValidLocalDescriptionSDP;
|
|
14833
14847
|
if (!validSDP && !this.relayOnly) this.restartICEGatheringWithRelayOnly();
|
|
14834
14848
|
else {
|
|
14835
|
-
logger$
|
|
14849
|
+
logger$18.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout");
|
|
14836
14850
|
this._iceCandidatesState.next({
|
|
14837
14851
|
state: "timeout",
|
|
14838
14852
|
validSDP
|
|
@@ -14841,7 +14855,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14841
14855
|
}
|
|
14842
14856
|
}
|
|
14843
14857
|
restartICEGatheringWithRelayOnly() {
|
|
14844
|
-
logger$
|
|
14858
|
+
logger$18.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
|
|
14845
14859
|
this.relayOnly = true;
|
|
14846
14860
|
this.peerConnection.setConfiguration({
|
|
14847
14861
|
...this.peerConnection.getConfiguration(),
|
|
@@ -14849,14 +14863,14 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14849
14863
|
});
|
|
14850
14864
|
if (!(this.peerConnection.connectionState === "connected")) this.peerConnection.restartIce();
|
|
14851
14865
|
}
|
|
14852
|
-
removeTimer(timer$
|
|
14853
|
-
if (this[timer$
|
|
14854
|
-
clearTimeout(this[timer$
|
|
14855
|
-
this[timer$
|
|
14866
|
+
removeTimer(timer$3) {
|
|
14867
|
+
if (this[timer$3]) {
|
|
14868
|
+
clearTimeout(this[timer$3]);
|
|
14869
|
+
this[timer$3] = void 0;
|
|
14856
14870
|
}
|
|
14857
14871
|
}
|
|
14858
14872
|
clearAllTimers() {
|
|
14859
|
-
logger$
|
|
14873
|
+
logger$18.debug("[ICEGatheringController] Clearing all timers");
|
|
14860
14874
|
this.removeTimer("iceGatheringTimer");
|
|
14861
14875
|
this.removeTimer("iceCandidateTimer");
|
|
14862
14876
|
}
|
|
@@ -14865,7 +14879,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14865
14879
|
this.peerConnection.removeEventListener("icecandidate", this.onicecandidateHandler);
|
|
14866
14880
|
}
|
|
14867
14881
|
destroy() {
|
|
14868
|
-
logger$
|
|
14882
|
+
logger$18.debug("[ICEGatheringController] Destroying ICEGatheringController");
|
|
14869
14883
|
this.clearAllTimers();
|
|
14870
14884
|
this.removeEventListeners();
|
|
14871
14885
|
super.destroy();
|
|
@@ -14874,8 +14888,8 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14874
14888
|
|
|
14875
14889
|
//#endregion
|
|
14876
14890
|
//#region src/controllers/LocalStreamController.ts
|
|
14877
|
-
var import_cjs$
|
|
14878
|
-
const logger$
|
|
14891
|
+
var import_cjs$15 = require_cjs();
|
|
14892
|
+
const logger$17 = getLogger();
|
|
14879
14893
|
var LocalStreamController = class extends Destroyable {
|
|
14880
14894
|
constructor(options) {
|
|
14881
14895
|
super();
|
|
@@ -14889,16 +14903,16 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14889
14903
|
this._mediaTrackEnded$ = this.createSubject();
|
|
14890
14904
|
}
|
|
14891
14905
|
get localStream$() {
|
|
14892
|
-
return this._localStream$.asObservable().pipe((0, import_cjs$
|
|
14906
|
+
return this._localStream$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14893
14907
|
}
|
|
14894
14908
|
get localAudioTracks$() {
|
|
14895
|
-
return this._localAudioTracks$.asObservable().pipe((0, import_cjs$
|
|
14909
|
+
return this._localAudioTracks$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14896
14910
|
}
|
|
14897
14911
|
get localVideoTracks$() {
|
|
14898
|
-
return this._localVideoTracks$.asObservable().pipe((0, import_cjs$
|
|
14912
|
+
return this._localVideoTracks$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14899
14913
|
}
|
|
14900
14914
|
get mediaTrackEnded$() {
|
|
14901
|
-
return this._mediaTrackEnded$.asObservable().pipe((0, import_cjs$
|
|
14915
|
+
return this._mediaTrackEnded$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14902
14916
|
}
|
|
14903
14917
|
get localStream() {
|
|
14904
14918
|
return this._localStream$.value;
|
|
@@ -14913,26 +14927,26 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14913
14927
|
* Build the local media stream based on the provided options.
|
|
14914
14928
|
*/
|
|
14915
14929
|
async buildLocalStream() {
|
|
14916
|
-
logger$
|
|
14930
|
+
logger$17.debug("[LocalStreamController] Building local media stream.");
|
|
14917
14931
|
let stream;
|
|
14918
14932
|
if (this.options.inputAudioStream ?? this.options.inputVideoStream) {
|
|
14919
14933
|
const tracks = [...this.options.inputAudioStream?.getTracks() ?? [], ...this.options.inputVideoStream?.getTracks() ?? []];
|
|
14920
14934
|
stream = new MediaStream(tracks);
|
|
14921
14935
|
} else if (this.options.propose === "screenshare") {
|
|
14922
|
-
logger$
|
|
14936
|
+
logger$17.debug("[LocalStreamController] Requesting display media for screen sharing with audio:", Boolean(this.options.inputAudioDeviceConstraints));
|
|
14923
14937
|
stream = await this.options.getDisplayMedia({
|
|
14924
14938
|
video: true,
|
|
14925
14939
|
audio: Boolean(this.options.inputAudioDeviceConstraints)
|
|
14926
14940
|
});
|
|
14927
|
-
logger$
|
|
14941
|
+
logger$17.debug("[LocalStreamController] Screen share media obtained:", stream);
|
|
14928
14942
|
} else {
|
|
14929
14943
|
const constraints = {
|
|
14930
14944
|
audio: this.options.inputAudioDeviceConstraints,
|
|
14931
14945
|
video: this.options.inputVideoDeviceConstraints
|
|
14932
14946
|
};
|
|
14933
|
-
logger$
|
|
14947
|
+
logger$17.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
|
|
14934
14948
|
stream = await this.options.getUserMedia(constraints);
|
|
14935
|
-
logger$
|
|
14949
|
+
logger$17.debug("[LocalStreamController] User media obtained:", stream);
|
|
14936
14950
|
}
|
|
14937
14951
|
this._localStream$.next(stream);
|
|
14938
14952
|
return stream;
|
|
@@ -14949,7 +14963,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14949
14963
|
this._localStream$.next(localStream);
|
|
14950
14964
|
if (track.kind === "video") this._localVideoTracks$.next(localStream.getVideoTracks());
|
|
14951
14965
|
else this._localAudioTracks$.next(localStream.getAudioTracks());
|
|
14952
|
-
logger$
|
|
14966
|
+
logger$17.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
|
|
14953
14967
|
return localStream;
|
|
14954
14968
|
}
|
|
14955
14969
|
/**
|
|
@@ -14961,7 +14975,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14961
14975
|
const stream = this._localStream$.value;
|
|
14962
14976
|
const track = stream?.getTracks().find((t) => t.id === trackId);
|
|
14963
14977
|
if (!track) {
|
|
14964
|
-
logger$
|
|
14978
|
+
logger$17.debug(`[LocalStreamController] track not found: ${trackId}`);
|
|
14965
14979
|
return;
|
|
14966
14980
|
}
|
|
14967
14981
|
track.removeEventListener("ended", this.mediaTrackEndedHandler);
|
|
@@ -14970,7 +14984,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14970
14984
|
this._localStream$.next(stream);
|
|
14971
14985
|
if (track.kind === "video") this._localVideoTracks$.next(stream?.getVideoTracks() ?? []);
|
|
14972
14986
|
else this._localAudioTracks$.next(stream?.getAudioTracks() ?? []);
|
|
14973
|
-
logger$
|
|
14987
|
+
logger$17.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
|
|
14974
14988
|
return track;
|
|
14975
14989
|
}
|
|
14976
14990
|
/**
|
|
@@ -15005,7 +15019,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15005
15019
|
*/
|
|
15006
15020
|
stopAllTracks() {
|
|
15007
15021
|
this._localStream$.value?.getTracks().forEach((track) => {
|
|
15008
|
-
logger$
|
|
15022
|
+
logger$17.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
|
|
15009
15023
|
track.removeEventListener("ended", this.mediaTrackEndedHandler);
|
|
15010
15024
|
track.stop();
|
|
15011
15025
|
});
|
|
@@ -15021,7 +15035,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15021
15035
|
|
|
15022
15036
|
//#endregion
|
|
15023
15037
|
//#region src/controllers/TransceiverController.ts
|
|
15024
|
-
const logger$
|
|
15038
|
+
const logger$16 = getLogger();
|
|
15025
15039
|
const getDirection = (send, recv) => {
|
|
15026
15040
|
if (send && recv) return "sendrecv";
|
|
15027
15041
|
else if (send && !recv) return "sendonly";
|
|
@@ -15123,7 +15137,7 @@ var TransceiverController = class extends Destroyable {
|
|
|
15123
15137
|
sendEncodings: isAudio ? void 0 : this.sendEncodings,
|
|
15124
15138
|
streams: direction === "recvonly" ? void 0 : [localStream]
|
|
15125
15139
|
};
|
|
15126
|
-
logger$
|
|
15140
|
+
logger$16.debug(`[TransceiverController] Setting up transceiver sender for local ${track.kind} track:`, {
|
|
15127
15141
|
transceiver,
|
|
15128
15142
|
transceiverParams
|
|
15129
15143
|
});
|
|
@@ -15131,11 +15145,11 @@ var TransceiverController = class extends Destroyable {
|
|
|
15131
15145
|
await transceiver.sender.replaceTrack(track);
|
|
15132
15146
|
transceiver.direction = transceiverParams.direction;
|
|
15133
15147
|
if (transceiverParams.streams?.some((stream) => Boolean(stream))) {
|
|
15134
|
-
logger$
|
|
15148
|
+
logger$16.debug(`[TransceiverController] Setting streams for transceiver sender for local ${track.kind} track:`, transceiverParams.streams);
|
|
15135
15149
|
transceiver.sender.setStreams(...transceiverParams.streams);
|
|
15136
15150
|
}
|
|
15137
15151
|
} else {
|
|
15138
|
-
logger$
|
|
15152
|
+
logger$16.debug(`[TransceiverController] Adding new transceiver for local ${track.kind} track:`, track.id);
|
|
15139
15153
|
this.peerConnection.addTransceiver(track, transceiverParams);
|
|
15140
15154
|
}
|
|
15141
15155
|
}
|
|
@@ -15149,13 +15163,13 @@ var TransceiverController = class extends Destroyable {
|
|
|
15149
15163
|
if (options.updateTransceiverDirection) transceiver.direction = "inactive";
|
|
15150
15164
|
}
|
|
15151
15165
|
} catch (error) {
|
|
15152
|
-
logger$
|
|
15166
|
+
logger$16.error("[TransceiverController] stopTrackSender error", kind, error);
|
|
15153
15167
|
this.options.onError?.(new MediaTrackError("stopTrackSender", kind, error));
|
|
15154
15168
|
}
|
|
15155
15169
|
}
|
|
15156
15170
|
async restoreTrackSender(kind) {
|
|
15157
15171
|
try {
|
|
15158
|
-
logger$
|
|
15172
|
+
logger$16.debug("[TransceiverController] restoreTrackSender called", kind);
|
|
15159
15173
|
const constraints = {};
|
|
15160
15174
|
const transceivers = this.transceiverByKind(kind);
|
|
15161
15175
|
for (const transceiver of transceivers) {
|
|
@@ -15165,23 +15179,23 @@ var TransceiverController = class extends Destroyable {
|
|
|
15165
15179
|
if (trackKind === "audio" || trackKind === "video") constraints[trackKind] = this.getConstraintsFor(trackKind);
|
|
15166
15180
|
}
|
|
15167
15181
|
}
|
|
15168
|
-
logger$
|
|
15182
|
+
logger$16.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
|
|
15169
15183
|
if (Object.keys(constraints).length === 0) {
|
|
15170
|
-
logger$
|
|
15184
|
+
logger$16.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
|
|
15171
15185
|
return;
|
|
15172
15186
|
}
|
|
15173
15187
|
const newTracks = (await this.options.getUserMedia(constraints)).getTracks();
|
|
15174
|
-
logger$
|
|
15188
|
+
logger$16.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
|
|
15175
15189
|
for (const newTrack of newTracks) {
|
|
15176
15190
|
this.options.localStreamController.addTrack(newTrack);
|
|
15177
15191
|
const trackKind = newTrack.kind;
|
|
15178
15192
|
const transceiverOfKind = this.transceiverByKind(trackKind)[0];
|
|
15179
15193
|
transceiverOfKind.direction = trackKind === "audio" ? this.audioDirection : this.videoDirection;
|
|
15180
|
-
logger$
|
|
15194
|
+
logger$16.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
|
|
15181
15195
|
await transceiverOfKind.sender.replaceTrack(newTrack);
|
|
15182
15196
|
}
|
|
15183
15197
|
} catch (error) {
|
|
15184
|
-
logger$
|
|
15198
|
+
logger$16.error("[TransceiverController] restoreTrackSender error", kind, error);
|
|
15185
15199
|
this.options.onError?.(new MediaTrackError("restoreTrackSender", kind, error));
|
|
15186
15200
|
}
|
|
15187
15201
|
}
|
|
@@ -15222,14 +15236,14 @@ var TransceiverController = class extends Destroyable {
|
|
|
15222
15236
|
};
|
|
15223
15237
|
try {
|
|
15224
15238
|
await track.applyConstraints(constraintsToApply);
|
|
15225
|
-
logger$
|
|
15226
|
-
logger$
|
|
15239
|
+
logger$16.debug(`[TransceiverController] Updated ${kind} sender constraints:`, constraintsToApply);
|
|
15240
|
+
logger$16.debug(`[TransceiverController] Updated ${kind} sender constraints:`, track.getConstraints());
|
|
15227
15241
|
} catch (error) {
|
|
15228
|
-
logger$
|
|
15242
|
+
logger$16.warn(`[TransceiverController] applyConstraints failed for ${kind} track ${track.id}, attempting track replacement fallback:`, error);
|
|
15229
15243
|
try {
|
|
15230
15244
|
await this.replaceTrackFallback(sender, track, kind, constraintsToApply);
|
|
15231
15245
|
} catch (fallbackError) {
|
|
15232
|
-
logger$
|
|
15246
|
+
logger$16.warn(`[TransceiverController] Track replacement fallback also failed for ${kind} track:`, fallbackError);
|
|
15233
15247
|
this.options.onError?.(new MediaTrackError("updateSendersConstraints", kind, fallbackError));
|
|
15234
15248
|
}
|
|
15235
15249
|
}
|
|
@@ -15257,7 +15271,7 @@ var TransceiverController = class extends Destroyable {
|
|
|
15257
15271
|
if (!newTrack) throw new MediaTrackError("replaceTrackFallback", kind, /* @__PURE__ */ new Error("getUserMedia returned no track of the requested kind"));
|
|
15258
15272
|
await sender.replaceTrack(newTrack);
|
|
15259
15273
|
this.options.localStreamController.addTrack(newTrack);
|
|
15260
|
-
logger$
|
|
15274
|
+
logger$16.debug(`[TransceiverController] Track replacement fallback succeeded for ${kind}. New track: ${newTrack.id}`);
|
|
15261
15275
|
}
|
|
15262
15276
|
getMediaDirections() {
|
|
15263
15277
|
if (this.peerConnection.connectionState === "connected") return this.peerConnection.getTransceivers().reduce((acc, transceiver) => {
|
|
@@ -15287,60 +15301,60 @@ var TransceiverController = class extends Destroyable {
|
|
|
15287
15301
|
|
|
15288
15302
|
//#endregion
|
|
15289
15303
|
//#region src/controllers/RTCPeerConnectionController.ts
|
|
15290
|
-
var import_cjs$
|
|
15291
|
-
const logger$
|
|
15304
|
+
var import_cjs$14 = require_cjs();
|
|
15305
|
+
const logger$15 = getLogger();
|
|
15292
15306
|
var RTCPeerConnectionController = class extends Destroyable {
|
|
15293
15307
|
constructor(options = {}, remoteSessionDescription, deviceController) {
|
|
15294
15308
|
super();
|
|
15295
15309
|
this.options = options;
|
|
15296
15310
|
this.firstSDPExchangeCompleted = false;
|
|
15297
15311
|
this.negotiationNeeded$ = this.createSubject();
|
|
15298
|
-
this.localDescription$ = (0, import_cjs$
|
|
15312
|
+
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)(() => {
|
|
15299
15313
|
this.negotiationEnded();
|
|
15300
|
-
}), (0, import_cjs$
|
|
15314
|
+
}), (0, import_cjs$14.filter)(() => this.shouldEmitLocalDescription), (0, import_cjs$14.map)(() => this.peerConnection?.localDescription), filterNull(), (0, import_cjs$14.tap)((desc) => {
|
|
15301
15315
|
if (desc.type === "answer") this._type = "offer";
|
|
15302
|
-
}))), (0, import_cjs$
|
|
15316
|
+
}))), (0, import_cjs$14.shareReplay)(1), (0, import_cjs$14.takeUntil)(this.destroyed$));
|
|
15303
15317
|
this.connectionTimeout = 3e3;
|
|
15304
15318
|
this.oniceconnectionstatechangeHandler = () => {
|
|
15305
15319
|
if (this.peerConnection) {
|
|
15306
15320
|
const { iceConnectionState } = this.peerConnection;
|
|
15307
|
-
logger$
|
|
15321
|
+
logger$15.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
|
|
15308
15322
|
this._iceConnectionState$.next(this.peerConnection.iceConnectionState);
|
|
15309
15323
|
}
|
|
15310
15324
|
};
|
|
15311
15325
|
this.onconnectionstatechangeHandler = () => {
|
|
15312
15326
|
if (this.peerConnection) {
|
|
15313
15327
|
const { connectionState } = this.peerConnection;
|
|
15314
|
-
logger$
|
|
15328
|
+
logger$15.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
|
|
15315
15329
|
if (connectionState === "connected") this.removeConnectionTimer();
|
|
15316
15330
|
this._connectionState$.next(this.peerConnection.connectionState);
|
|
15317
15331
|
}
|
|
15318
15332
|
};
|
|
15319
15333
|
this.onsignalingstatechangeHandler = () => {
|
|
15320
|
-
logger$
|
|
15334
|
+
logger$15.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
|
|
15321
15335
|
};
|
|
15322
15336
|
this.onicegatheringstatechangeHandler = () => {
|
|
15323
15337
|
if (this.peerConnection) this._iceGatheringState$.next(this.peerConnection.iceGatheringState);
|
|
15324
15338
|
};
|
|
15325
15339
|
this.onnegotiationneededHandler = (event) => {
|
|
15326
|
-
logger$
|
|
15340
|
+
logger$15.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
|
|
15327
15341
|
this.negotiationNeeded$.next();
|
|
15328
15342
|
};
|
|
15329
15343
|
this.updateSelectedInputDevice = async (kind, deviceInfo) => {
|
|
15330
15344
|
try {
|
|
15331
15345
|
const { localStream } = this;
|
|
15332
15346
|
if (!localStream) {
|
|
15333
|
-
logger$
|
|
15347
|
+
logger$15.warn("[RTCPeerConnectionController] No local stream available to update input device.");
|
|
15334
15348
|
return;
|
|
15335
15349
|
}
|
|
15336
|
-
logger$
|
|
15350
|
+
logger$15.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
|
|
15337
15351
|
const track = localStream.getTracks().find((track$1) => track$1.kind === kind);
|
|
15338
15352
|
if (track) {
|
|
15339
15353
|
this.transceiverController?.stopTrackSender(kind);
|
|
15340
15354
|
this.localStream?.removeTrack(track);
|
|
15341
|
-
logger$
|
|
15355
|
+
logger$15.debug(`[RTCPeerConnectionController] Stopped existing ${kind} track: ${track.id}`, localStream.getTracks());
|
|
15342
15356
|
if (!deviceInfo) {
|
|
15343
|
-
logger$
|
|
15357
|
+
logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
|
|
15344
15358
|
return;
|
|
15345
15359
|
}
|
|
15346
15360
|
const streamTrack = (await this.getUserMedia({ [kind]: {
|
|
@@ -15348,15 +15362,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15348
15362
|
...this.deviceController.deviceInfoToConstraints(deviceInfo)
|
|
15349
15363
|
} })).getTracks().find((t) => t.kind === kind);
|
|
15350
15364
|
if (streamTrack) {
|
|
15351
|
-
logger$
|
|
15365
|
+
logger$15.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
|
|
15352
15366
|
this.localStream?.addTrack(streamTrack);
|
|
15353
15367
|
await this.transceiverController?.replaceSenderTrack(kind, streamTrack);
|
|
15354
|
-
logger$
|
|
15368
|
+
logger$15.debug(`[RTCPeerConnectionController] Added new ${kind} track: ${streamTrack.id}`, this.localStream?.getTracks());
|
|
15355
15369
|
}
|
|
15356
15370
|
}
|
|
15357
|
-
logger$
|
|
15371
|
+
logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
|
|
15358
15372
|
} catch (error) {
|
|
15359
|
-
logger$
|
|
15373
|
+
logger$15.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
|
|
15360
15374
|
this._errors$.next(error);
|
|
15361
15375
|
throw error;
|
|
15362
15376
|
}
|
|
@@ -15442,43 +15456,43 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15442
15456
|
};
|
|
15443
15457
|
}
|
|
15444
15458
|
get iceGatheringState$() {
|
|
15445
|
-
return this.cachedObservable("iceGatheringState$", () => this._iceGatheringState$.asObservable().pipe((0, import_cjs$
|
|
15459
|
+
return this.cachedObservable("iceGatheringState$", () => this._iceGatheringState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15446
15460
|
}
|
|
15447
15461
|
get mediaTrackEnded$() {
|
|
15448
|
-
return this.cachedObservable("mediaTrackEnded$", () => this.localStreamController.mediaTrackEnded$.pipe((0, import_cjs$
|
|
15462
|
+
return this.cachedObservable("mediaTrackEnded$", () => this.localStreamController.mediaTrackEnded$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15449
15463
|
}
|
|
15450
15464
|
get errors$() {
|
|
15451
|
-
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$
|
|
15465
|
+
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15452
15466
|
}
|
|
15453
15467
|
get iceCandidates$() {
|
|
15454
|
-
return this.cachedObservable("iceCandidates$", () => this._iceCandidates$.asObservable().pipe((0, import_cjs$
|
|
15468
|
+
return this.cachedObservable("iceCandidates$", () => this._iceCandidates$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15455
15469
|
}
|
|
15456
15470
|
get initialized$() {
|
|
15457
|
-
return this.cachedObservable("initialized$", () => this._initialized$.asObservable().pipe((0, import_cjs$
|
|
15471
|
+
return this.cachedObservable("initialized$", () => this._initialized$.asObservable().pipe((0, import_cjs$14.filter)((initialized) => initialized), (0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15458
15472
|
}
|
|
15459
15473
|
get remoteDescription$() {
|
|
15460
|
-
return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, import_cjs$
|
|
15474
|
+
return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15461
15475
|
}
|
|
15462
15476
|
get localStream$() {
|
|
15463
|
-
return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, import_cjs$
|
|
15477
|
+
return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15464
15478
|
}
|
|
15465
15479
|
get remoteStream$() {
|
|
15466
|
-
return this.cachedObservable("remoteStream$", () => this._remoteStream$.asObservable().pipe((0, import_cjs$
|
|
15480
|
+
return this.cachedObservable("remoteStream$", () => this._remoteStream$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15467
15481
|
}
|
|
15468
15482
|
get localAudioTracks$() {
|
|
15469
|
-
return this.cachedObservable("localAudioTracks$", () => this.localStreamController.localAudioTracks$.pipe((0, import_cjs$
|
|
15483
|
+
return this.cachedObservable("localAudioTracks$", () => this.localStreamController.localAudioTracks$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15470
15484
|
}
|
|
15471
15485
|
get localVideoTracks$() {
|
|
15472
|
-
return this.cachedObservable("localVideoTracks$", () => this.localStreamController.localVideoTracks$.pipe((0, import_cjs$
|
|
15486
|
+
return this.cachedObservable("localVideoTracks$", () => this.localStreamController.localVideoTracks$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15473
15487
|
}
|
|
15474
15488
|
get iceConnectionState$() {
|
|
15475
|
-
return this.cachedObservable("iceConnectionState$", () => this._iceConnectionState$.asObservable().pipe((0, import_cjs$
|
|
15489
|
+
return this.cachedObservable("iceConnectionState$", () => this._iceConnectionState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15476
15490
|
}
|
|
15477
15491
|
get connectionState$() {
|
|
15478
|
-
return this.cachedObservable("connectionState$", () => this._connectionState$.asObservable().pipe((0, import_cjs$
|
|
15492
|
+
return this.cachedObservable("connectionState$", () => this._connectionState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15479
15493
|
}
|
|
15480
15494
|
get signalingState$() {
|
|
15481
|
-
return this.cachedObservable("signalingState$", () => this._signalingState$.asObservable().pipe((0, import_cjs$
|
|
15495
|
+
return this.cachedObservable("signalingState$", () => this._signalingState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15482
15496
|
}
|
|
15483
15497
|
get type() {
|
|
15484
15498
|
return this._type;
|
|
@@ -15591,17 +15605,17 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15591
15605
|
async doInit() {
|
|
15592
15606
|
try {
|
|
15593
15607
|
this.setupPeerConnection();
|
|
15594
|
-
this.subscribeTo(this.negotiationNeeded$.pipe((0, import_cjs$
|
|
15608
|
+
this.subscribeTo(this.negotiationNeeded$.pipe((0, import_cjs$14.auditTime)(0), (0, import_cjs$14.exhaustMap)(async () => this.startNegotiation())), {
|
|
15595
15609
|
next: () => {
|
|
15596
|
-
logger$
|
|
15610
|
+
logger$15.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
|
|
15597
15611
|
},
|
|
15598
15612
|
error: (error) => {
|
|
15599
|
-
logger$
|
|
15613
|
+
logger$15.error("[RTCPeerConnectionController] Start Negotiation error:", error);
|
|
15600
15614
|
this._errors$.next(error);
|
|
15601
15615
|
}
|
|
15602
15616
|
});
|
|
15603
|
-
this.subscribeTo((0, import_cjs$
|
|
15604
|
-
logger$
|
|
15617
|
+
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]) => {
|
|
15618
|
+
logger$15.debug(`[RTCPeerConnectionController] Selected input device changed for:`, {
|
|
15605
15619
|
kind,
|
|
15606
15620
|
deviceInfo
|
|
15607
15621
|
});
|
|
@@ -15618,7 +15632,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15618
15632
|
this._initialized$.next(true);
|
|
15619
15633
|
}
|
|
15620
15634
|
} catch (error) {
|
|
15621
|
-
logger$
|
|
15635
|
+
logger$15.error("[RTCPeerConnectionController] Initialization error:", error);
|
|
15622
15636
|
this._errors$.next(error);
|
|
15623
15637
|
this.destroy();
|
|
15624
15638
|
}
|
|
@@ -15650,22 +15664,22 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15650
15664
|
}
|
|
15651
15665
|
async startNegotiation() {
|
|
15652
15666
|
if (this.isNegotiating) {
|
|
15653
|
-
logger$
|
|
15667
|
+
logger$15.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
|
|
15654
15668
|
return;
|
|
15655
15669
|
}
|
|
15656
15670
|
this.setupEventListeners();
|
|
15657
15671
|
if (this.type === "answer") {
|
|
15658
|
-
logger$
|
|
15672
|
+
logger$15.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");
|
|
15659
15673
|
return;
|
|
15660
15674
|
}
|
|
15661
15675
|
this._isNegotiating$.next(true);
|
|
15662
|
-
logger$
|
|
15676
|
+
logger$15.debug("[RTCPeerConnectionController] Starting negotiation.");
|
|
15663
15677
|
try {
|
|
15664
15678
|
const { offerOptions } = this;
|
|
15665
|
-
logger$
|
|
15679
|
+
logger$15.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
|
|
15666
15680
|
await this.createOffer(offerOptions);
|
|
15667
15681
|
} catch (error) {
|
|
15668
|
-
logger$
|
|
15682
|
+
logger$15.error("[RTCPeerConnectionController] Error during negotiation:", error);
|
|
15669
15683
|
this._errors$.next(error);
|
|
15670
15684
|
}
|
|
15671
15685
|
}
|
|
@@ -15681,14 +15695,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15681
15695
|
let readyToConnect = status !== "failed";
|
|
15682
15696
|
try {
|
|
15683
15697
|
if (status === "received" && sdp) {
|
|
15684
|
-
logger$
|
|
15698
|
+
logger$15.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
|
|
15685
15699
|
await this._setRemoteDescription({
|
|
15686
15700
|
type: "answer",
|
|
15687
15701
|
sdp
|
|
15688
15702
|
});
|
|
15689
15703
|
}
|
|
15690
15704
|
} catch (error) {
|
|
15691
|
-
logger$
|
|
15705
|
+
logger$15.error("[RTCPeerConnectionController] Error updating answer status:", error);
|
|
15692
15706
|
this._errors$.next(error);
|
|
15693
15707
|
readyToConnect = false;
|
|
15694
15708
|
} finally {
|
|
@@ -15707,7 +15721,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15707
15721
|
await this.handleOfferReceived();
|
|
15708
15722
|
break;
|
|
15709
15723
|
case "failed":
|
|
15710
|
-
logger$
|
|
15724
|
+
logger$15.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
|
|
15711
15725
|
break;
|
|
15712
15726
|
case "sent":
|
|
15713
15727
|
default:
|
|
@@ -15739,7 +15753,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15739
15753
|
}
|
|
15740
15754
|
await this.setupLocalTracks();
|
|
15741
15755
|
const { answerOptions } = this;
|
|
15742
|
-
logger$
|
|
15756
|
+
logger$15.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
|
|
15743
15757
|
await this.createAnswer(answerOptions);
|
|
15744
15758
|
}
|
|
15745
15759
|
async handleOfferReceived() {
|
|
@@ -15747,7 +15761,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15747
15761
|
this._isNegotiating$.next(true);
|
|
15748
15762
|
await this._setRemoteDescription(this.sdpInit);
|
|
15749
15763
|
const { answerOptions } = this;
|
|
15750
|
-
logger$
|
|
15764
|
+
logger$15.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
|
|
15751
15765
|
await this.createAnswer(answerOptions);
|
|
15752
15766
|
}
|
|
15753
15767
|
readyToConnect() {
|
|
@@ -15755,7 +15769,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15755
15769
|
this.connectionTimer = setTimeout(() => {
|
|
15756
15770
|
this.removeConnectionTimer();
|
|
15757
15771
|
if (this.peerConnection?.connectionState !== "connected") {
|
|
15758
|
-
logger$
|
|
15772
|
+
logger$15.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only.");
|
|
15759
15773
|
this.iceGatheringController.restartICEGatheringWithRelayOnly();
|
|
15760
15774
|
}
|
|
15761
15775
|
}, this.connectionTimeout);
|
|
@@ -15777,14 +15791,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15777
15791
|
const stereo = this.options.stereo ?? PreferencesContainer.instance.stereoAudio;
|
|
15778
15792
|
if (preferredAudioCodecs.length > 0 || preferredVideoCodecs.length > 0) {
|
|
15779
15793
|
result = setCodecPreferences(result, preferredAudioCodecs, preferredVideoCodecs);
|
|
15780
|
-
logger$
|
|
15794
|
+
logger$15.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
|
|
15781
15795
|
preferredAudioCodecs,
|
|
15782
15796
|
preferredVideoCodecs
|
|
15783
15797
|
});
|
|
15784
15798
|
}
|
|
15785
15799
|
if (stereo) {
|
|
15786
15800
|
result = enableStereoOpus(result);
|
|
15787
|
-
logger$
|
|
15801
|
+
logger$15.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP");
|
|
15788
15802
|
}
|
|
15789
15803
|
return Promise.resolve(result);
|
|
15790
15804
|
}
|
|
@@ -15843,18 +15857,18 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15843
15857
|
...this.peerConnection.getConfiguration(),
|
|
15844
15858
|
iceTransportPolicy: "relay"
|
|
15845
15859
|
});
|
|
15846
|
-
logger$
|
|
15860
|
+
logger$15.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only");
|
|
15847
15861
|
} catch (error) {
|
|
15848
|
-
logger$
|
|
15862
|
+
logger$15.warn("[RTCPeerConnectionController] Failed to set relay-only policy:", error);
|
|
15849
15863
|
}
|
|
15850
15864
|
this.setupEventListeners();
|
|
15851
15865
|
this._isNegotiating$.next(true);
|
|
15852
|
-
logger$
|
|
15866
|
+
logger$15.debug(`[RTCPeerConnectionController] Triggering ICE restart${relayOnly ? " (relay-only)" : ""}.`);
|
|
15853
15867
|
try {
|
|
15854
15868
|
const offer = await this.peerConnection.createOffer({ iceRestart: true });
|
|
15855
15869
|
await this.setLocalDescription(offer);
|
|
15856
15870
|
} catch (error) {
|
|
15857
|
-
logger$
|
|
15871
|
+
logger$15.error("[RTCPeerConnectionController] ICE restart offer failed:", error);
|
|
15858
15872
|
this._errors$.next(error);
|
|
15859
15873
|
this.negotiationEnded();
|
|
15860
15874
|
if (policyChanged) this.restoreIceTransportPolicy();
|
|
@@ -15868,9 +15882,9 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15868
15882
|
...this.peerConnection.getConfiguration(),
|
|
15869
15883
|
iceTransportPolicy: this.options.relayOnly ? "relay" : "all"
|
|
15870
15884
|
});
|
|
15871
|
-
logger$
|
|
15885
|
+
logger$15.debug("[RTCPeerConnectionController] ICE transport policy restored");
|
|
15872
15886
|
} catch (error) {
|
|
15873
|
-
logger$
|
|
15887
|
+
logger$15.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:", error);
|
|
15874
15888
|
}
|
|
15875
15889
|
}
|
|
15876
15890
|
/**
|
|
@@ -15882,13 +15896,13 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15882
15896
|
await this.setupRemoteTracks();
|
|
15883
15897
|
}
|
|
15884
15898
|
async setupLocalTracks() {
|
|
15885
|
-
logger$
|
|
15899
|
+
logger$15.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
15886
15900
|
const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
15887
15901
|
if (this.transceiverController?.useAddStream ?? false) {
|
|
15888
|
-
logger$
|
|
15902
|
+
logger$15.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
15889
15903
|
this.peerConnection?.addStream(localStream);
|
|
15890
15904
|
if (!this.isNegotiating) {
|
|
15891
|
-
logger$
|
|
15905
|
+
logger$15.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
15892
15906
|
this.negotiationNeeded$.next();
|
|
15893
15907
|
}
|
|
15894
15908
|
return;
|
|
@@ -15904,7 +15918,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15904
15918
|
const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
|
|
15905
15919
|
await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
|
|
15906
15920
|
} else {
|
|
15907
|
-
logger$
|
|
15921
|
+
logger$15.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
|
|
15908
15922
|
this.peerConnection?.addTrack(track, localStream);
|
|
15909
15923
|
}
|
|
15910
15924
|
}
|
|
@@ -15921,7 +15935,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15921
15935
|
async setupRemoteTracks() {
|
|
15922
15936
|
if (!this.peerConnection) throw new DependencyError("RTCPeerConnection is not initialized");
|
|
15923
15937
|
this.peerConnection.ontrack = (event) => {
|
|
15924
|
-
logger$
|
|
15938
|
+
logger$15.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
|
|
15925
15939
|
if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
|
|
15926
15940
|
else {
|
|
15927
15941
|
const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
|
|
@@ -15947,9 +15961,9 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15947
15961
|
try {
|
|
15948
15962
|
const localStream = this.localStreamController.addTrack(track);
|
|
15949
15963
|
this.peerConnection.addTrack(track, localStream);
|
|
15950
|
-
logger$
|
|
15964
|
+
logger$15.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
|
|
15951
15965
|
} catch (error) {
|
|
15952
|
-
logger$
|
|
15966
|
+
logger$15.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
|
|
15953
15967
|
this._errors$.next(error);
|
|
15954
15968
|
throw error;
|
|
15955
15969
|
}
|
|
@@ -15966,15 +15980,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15966
15980
|
}
|
|
15967
15981
|
const sender = this.peerConnection.getSenders().find((sender$1) => sender$1.track?.id === trackId);
|
|
15968
15982
|
if (!sender) {
|
|
15969
|
-
logger$
|
|
15983
|
+
logger$15.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
|
|
15970
15984
|
return;
|
|
15971
15985
|
}
|
|
15972
15986
|
try {
|
|
15973
15987
|
this.peerConnection.removeTrack(sender);
|
|
15974
15988
|
this.localStreamController.removeTrack(trackId);
|
|
15975
|
-
logger$
|
|
15989
|
+
logger$15.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
|
|
15976
15990
|
} catch (error) {
|
|
15977
|
-
logger$
|
|
15991
|
+
logger$15.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
|
|
15978
15992
|
this._errors$.next(error);
|
|
15979
15993
|
throw error;
|
|
15980
15994
|
}
|
|
@@ -16001,7 +16015,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16001
16015
|
async replaceAudioTrackWithConstraints(constraints) {
|
|
16002
16016
|
const senders = this.peerConnection?.getSenders().filter((s) => s.track?.kind === "audio" && s.track.readyState === "live");
|
|
16003
16017
|
if (!senders || senders.length === 0) {
|
|
16004
|
-
logger$
|
|
16018
|
+
logger$15.warn("[RTCPeerConnectionController] No live audio sender to replace");
|
|
16005
16019
|
return;
|
|
16006
16020
|
}
|
|
16007
16021
|
for (const sender of senders) {
|
|
@@ -16019,7 +16033,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16019
16033
|
const newTrack = (await this.getUserMedia({ audio: mergedConstraints })).getAudioTracks()[0];
|
|
16020
16034
|
await sender.replaceTrack(newTrack);
|
|
16021
16035
|
this.localStreamController.addTrack(newTrack);
|
|
16022
|
-
logger$
|
|
16036
|
+
logger$15.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
|
|
16023
16037
|
}
|
|
16024
16038
|
}
|
|
16025
16039
|
/**
|
|
@@ -16027,7 +16041,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16027
16041
|
* Completes all observables to prevent memory leaks.
|
|
16028
16042
|
*/
|
|
16029
16043
|
destroy() {
|
|
16030
|
-
logger$
|
|
16044
|
+
logger$15.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
|
|
16031
16045
|
this.removeConnectionTimer();
|
|
16032
16046
|
this._iceGatheringController?.destroy();
|
|
16033
16047
|
this.localStreamController.destroy();
|
|
@@ -16051,7 +16065,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16051
16065
|
}
|
|
16052
16066
|
stopRemoteTracks() {
|
|
16053
16067
|
this._remoteStream$.value?.getTracks().forEach((track) => {
|
|
16054
|
-
logger$
|
|
16068
|
+
logger$15.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
|
|
16055
16069
|
track.stop();
|
|
16056
16070
|
});
|
|
16057
16071
|
}
|
|
@@ -16068,7 +16082,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16068
16082
|
...params,
|
|
16069
16083
|
sdp: finalRemote
|
|
16070
16084
|
};
|
|
16071
|
-
logger$
|
|
16085
|
+
logger$15.debug("[RTCPeerConnectionController] Setting remote description:", answer);
|
|
16072
16086
|
return this.peerConnection.setRemoteDescription(answer);
|
|
16073
16087
|
}
|
|
16074
16088
|
};
|
|
@@ -16106,8 +16120,8 @@ function isVertoPingInnerParams(value) {
|
|
|
16106
16120
|
|
|
16107
16121
|
//#endregion
|
|
16108
16122
|
//#region src/managers/VertoManager.ts
|
|
16109
|
-
var import_cjs$
|
|
16110
|
-
const logger$
|
|
16123
|
+
var import_cjs$13 = require_cjs();
|
|
16124
|
+
const logger$14 = getLogger();
|
|
16111
16125
|
var VertoManager = class extends Destroyable {
|
|
16112
16126
|
constructor(callSession) {
|
|
16113
16127
|
super();
|
|
@@ -16133,6 +16147,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16133
16147
|
this._screenShareTimeoutMs = 5e4;
|
|
16134
16148
|
this._nodeId$ = this.createBehaviorSubject(options.nodeId ?? null);
|
|
16135
16149
|
this.onError = options.onError;
|
|
16150
|
+
this.onModifyFailed = options.onModifyFailed;
|
|
16136
16151
|
this.initSubscriptions();
|
|
16137
16152
|
this.initMainPeerConnection();
|
|
16138
16153
|
}
|
|
@@ -16145,7 +16160,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16145
16160
|
try {
|
|
16146
16161
|
await this.executeVerto(vertoModifyMessage);
|
|
16147
16162
|
} catch (error) {
|
|
16148
|
-
logger$
|
|
16163
|
+
logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:", error);
|
|
16149
16164
|
throw error;
|
|
16150
16165
|
}
|
|
16151
16166
|
}
|
|
@@ -16158,7 +16173,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16158
16173
|
try {
|
|
16159
16174
|
await this.executeVerto(vertoModifyMessage);
|
|
16160
16175
|
} catch (error) {
|
|
16161
|
-
logger$
|
|
16176
|
+
logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:", error);
|
|
16162
16177
|
throw error;
|
|
16163
16178
|
}
|
|
16164
16179
|
}
|
|
@@ -16198,7 +16213,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16198
16213
|
return rtcPeerConnection;
|
|
16199
16214
|
}
|
|
16200
16215
|
get signalingStatus$() {
|
|
16201
|
-
return this.cachedObservable("signalingStatus$", () => (0, import_cjs$
|
|
16216
|
+
return this.cachedObservable("signalingStatus$", () => (0, import_cjs$13.merge)(this._signalingStatus$.pipe(filterNull()), this.mainPeerConnection.connectionState$.pipe((0, import_cjs$13.filter)((connectionState) => [
|
|
16202
16217
|
"connected",
|
|
16203
16218
|
"disconnected",
|
|
16204
16219
|
"failed"
|
|
@@ -16211,7 +16226,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16211
16226
|
if (event.member_id) this.setSelfIdIfNull(event.member_id);
|
|
16212
16227
|
});
|
|
16213
16228
|
this.subscribeTo(this.vertoMedia$, (event) => {
|
|
16214
|
-
logger$
|
|
16229
|
+
logger$14.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
|
|
16215
16230
|
this._signalingStatus$.next("ringing");
|
|
16216
16231
|
const { sdp, callID } = event;
|
|
16217
16232
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
@@ -16220,7 +16235,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16220
16235
|
});
|
|
16221
16236
|
});
|
|
16222
16237
|
this.subscribeTo(this.vertoAnswer$, (event) => {
|
|
16223
|
-
logger$
|
|
16238
|
+
logger$14.debug("[WebRTCManager] Received Verto answer event:", event);
|
|
16224
16239
|
this._signalingStatus$.next("connecting");
|
|
16225
16240
|
const { sdp, callID } = event;
|
|
16226
16241
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
@@ -16229,7 +16244,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16229
16244
|
});
|
|
16230
16245
|
});
|
|
16231
16246
|
this.subscribeTo(this.vertoMediaParams$, (event) => {
|
|
16232
|
-
logger$
|
|
16247
|
+
logger$14.debug("[WebRTCManager] Received Verto mediaParams event:", event);
|
|
16233
16248
|
const { mediaParams, callID } = event;
|
|
16234
16249
|
const rtcPeerConnController = this._rtcPeerConnectionsMap.get(callID);
|
|
16235
16250
|
const { audio, video } = mediaParams;
|
|
@@ -16243,13 +16258,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16243
16258
|
timestamp: Date.now()
|
|
16244
16259
|
});
|
|
16245
16260
|
} catch (error) {
|
|
16246
|
-
logger$
|
|
16261
|
+
logger$14.warn("[WebRTCManager] Error applying server-pushed media params:", error);
|
|
16247
16262
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16248
16263
|
}
|
|
16249
16264
|
})();
|
|
16250
16265
|
});
|
|
16251
16266
|
this.subscribeTo(this.vertoPing$, (vertoPing) => {
|
|
16252
|
-
this.attachManager.attach(this.
|
|
16267
|
+
this.attachManager.attach(this.buildAttachableCall());
|
|
16253
16268
|
this.sendVertoPong(vertoPing);
|
|
16254
16269
|
});
|
|
16255
16270
|
}
|
|
@@ -16265,13 +16280,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16265
16280
|
*/
|
|
16266
16281
|
setNodeIdIfNull(nodeId) {
|
|
16267
16282
|
if (!this._nodeId$.value && nodeId) {
|
|
16268
|
-
logger$
|
|
16283
|
+
logger$14.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
|
|
16269
16284
|
this._nodeId$.next(nodeId);
|
|
16270
16285
|
}
|
|
16271
16286
|
}
|
|
16272
16287
|
setSelfIdIfNull(selfId) {
|
|
16273
16288
|
if (!this._selfId$.value && selfId) {
|
|
16274
|
-
logger$
|
|
16289
|
+
logger$14.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
|
|
16275
16290
|
this._selfId$.next(selfId);
|
|
16276
16291
|
}
|
|
16277
16292
|
}
|
|
@@ -16280,7 +16295,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16280
16295
|
const vertoPongMessage = VertoPong({ ...vertoPing });
|
|
16281
16296
|
await this.executeVerto(vertoPongMessage);
|
|
16282
16297
|
} catch (error) {
|
|
16283
|
-
logger$
|
|
16298
|
+
logger$14.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:", error);
|
|
16284
16299
|
this.onError?.(new VertoPongError(error));
|
|
16285
16300
|
}
|
|
16286
16301
|
}
|
|
@@ -16290,7 +16305,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16290
16305
|
if (audio) await this.mainPeerConnection.updateSendersConstraints("audio", audio);
|
|
16291
16306
|
if (video) await this.mainPeerConnection.updateSendersConstraints("video", video);
|
|
16292
16307
|
} catch (error) {
|
|
16293
|
-
logger$
|
|
16308
|
+
logger$14.warn("[WebRTCManager] Error updating media constraints:", error);
|
|
16294
16309
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16295
16310
|
throw error;
|
|
16296
16311
|
}
|
|
@@ -16298,6 +16313,15 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16298
16313
|
get selfId() {
|
|
16299
16314
|
return this._selfId$.value;
|
|
16300
16315
|
}
|
|
16316
|
+
/** Build an AttachableCall from the current call state. */
|
|
16317
|
+
buildAttachableCall(idOverride) {
|
|
16318
|
+
return {
|
|
16319
|
+
nodeId: this.nodeId ?? void 0,
|
|
16320
|
+
id: idOverride ?? this.webRtcCallSession.id,
|
|
16321
|
+
to: this.webRtcCallSession.to,
|
|
16322
|
+
mediaDirections: this.webRtcCallSession.mediaDirections
|
|
16323
|
+
};
|
|
16324
|
+
}
|
|
16301
16325
|
/**
|
|
16302
16326
|
* Request a video keyframe via RTCP PLI/FIR.
|
|
16303
16327
|
*
|
|
@@ -16311,20 +16335,20 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16311
16335
|
try {
|
|
16312
16336
|
const pc = this.mainPeerConnection.peerConnection;
|
|
16313
16337
|
if (!pc) {
|
|
16314
|
-
logger$
|
|
16338
|
+
logger$14.warn("[WebRTCManager] No peer connection for keyframe request");
|
|
16315
16339
|
return;
|
|
16316
16340
|
}
|
|
16317
16341
|
const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
|
|
16318
16342
|
if (!videoReceiver) {
|
|
16319
|
-
logger$
|
|
16343
|
+
logger$14.warn("[WebRTCManager] No video receiver for keyframe request");
|
|
16320
16344
|
return;
|
|
16321
16345
|
}
|
|
16322
16346
|
if (typeof videoReceiver.requestKeyFrame === "function") {
|
|
16323
16347
|
videoReceiver.requestKeyFrame();
|
|
16324
|
-
logger$
|
|
16325
|
-
} else logger$
|
|
16348
|
+
logger$14.debug("[WebRTCManager] Keyframe requested via RTCRtpReceiver.requestKeyFrame()");
|
|
16349
|
+
} else logger$14.debug("[WebRTCManager] requestKeyFrame() not supported, skipping");
|
|
16326
16350
|
} catch (error) {
|
|
16327
|
-
logger$
|
|
16351
|
+
logger$14.warn("[WebRTCManager] Keyframe request failed (non-fatal):", error);
|
|
16328
16352
|
}
|
|
16329
16353
|
}
|
|
16330
16354
|
/**
|
|
@@ -16342,13 +16366,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16342
16366
|
try {
|
|
16343
16367
|
const controller = this.mainPeerConnection;
|
|
16344
16368
|
if (!controller.peerConnection) {
|
|
16345
|
-
logger$
|
|
16369
|
+
logger$14.warn("[WebRTCManager] No peer connection for ICE restart");
|
|
16346
16370
|
return;
|
|
16347
16371
|
}
|
|
16348
16372
|
await controller.triggerIceRestart(relayOnly);
|
|
16349
|
-
logger$
|
|
16373
|
+
logger$14.info(`[WebRTCManager] ICE restart initiated${relayOnly ? " (relay-only)" : ""}`);
|
|
16350
16374
|
} catch (error) {
|
|
16351
|
-
logger$
|
|
16375
|
+
logger$14.error("[WebRTCManager] ICE restart failed:", error);
|
|
16352
16376
|
throw error;
|
|
16353
16377
|
}
|
|
16354
16378
|
}
|
|
@@ -16366,13 +16390,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16366
16390
|
const entries = Array.from(this._rtcPeerConnectionsMap.entries());
|
|
16367
16391
|
for (const [id, controller] of entries) try {
|
|
16368
16392
|
if (!controller.peerConnection) {
|
|
16369
|
-
logger$
|
|
16393
|
+
logger$14.debug(`[WebRTCManager] No peer connection for leg ${id}, skipping ICE restart`);
|
|
16370
16394
|
continue;
|
|
16371
16395
|
}
|
|
16372
16396
|
await controller.triggerIceRestart(relayOnly);
|
|
16373
|
-
logger$
|
|
16397
|
+
logger$14.info(`[WebRTCManager] ICE restart initiated for leg ${id}${relayOnly ? " (relay-only)" : ""}`);
|
|
16374
16398
|
} catch (error) {
|
|
16375
|
-
logger$
|
|
16399
|
+
logger$14.warn(`[WebRTCManager] ICE restart failed for leg ${id}:`, error);
|
|
16376
16400
|
}
|
|
16377
16401
|
}
|
|
16378
16402
|
/**
|
|
@@ -16384,7 +16408,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16384
16408
|
requestKeyframeAll() {
|
|
16385
16409
|
for (const [id, controller] of this._rtcPeerConnectionsMap) {
|
|
16386
16410
|
if (controller.isScreenShare) {
|
|
16387
|
-
logger$
|
|
16411
|
+
logger$14.debug(`[WebRTCManager] Skipping keyframe for send-only screen share leg ${id}`);
|
|
16388
16412
|
continue;
|
|
16389
16413
|
}
|
|
16390
16414
|
try {
|
|
@@ -16394,33 +16418,33 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16394
16418
|
if (!videoReceiver) continue;
|
|
16395
16419
|
if (typeof videoReceiver.requestKeyFrame === "function") {
|
|
16396
16420
|
videoReceiver.requestKeyFrame();
|
|
16397
|
-
logger$
|
|
16421
|
+
logger$14.debug(`[WebRTCManager] Keyframe requested for leg ${id}`);
|
|
16398
16422
|
}
|
|
16399
16423
|
} catch (error) {
|
|
16400
|
-
logger$
|
|
16424
|
+
logger$14.warn(`[WebRTCManager] Keyframe request failed for leg ${id} (non-fatal):`, error);
|
|
16401
16425
|
}
|
|
16402
16426
|
}
|
|
16403
16427
|
}
|
|
16404
16428
|
get callJoinedEvent$() {
|
|
16405
|
-
return this.webRtcCallSession.callEvent$.pipe((0, import_cjs$
|
|
16429
|
+
return this.webRtcCallSession.callEvent$.pipe((0, import_cjs$13.filter)(isCallJoinedPayload), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16406
16430
|
}
|
|
16407
16431
|
get vertoMedia$() {
|
|
16408
|
-
return this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaInnerParams, "params"), (0, import_cjs$
|
|
16432
|
+
return this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16409
16433
|
}
|
|
16410
16434
|
get vertoAnswer$() {
|
|
16411
|
-
return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAnswerInnerParams, "params"), (0, import_cjs$
|
|
16435
|
+
return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAnswerInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16412
16436
|
}
|
|
16413
16437
|
get vertoMediaParams$() {
|
|
16414
|
-
return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$
|
|
16438
|
+
return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16415
16439
|
}
|
|
16416
16440
|
get vertoBye$() {
|
|
16417
|
-
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeMessage, "params"), (0, import_cjs$
|
|
16441
|
+
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeMessage, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16418
16442
|
}
|
|
16419
16443
|
get vertoAttach$() {
|
|
16420
|
-
return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$
|
|
16444
|
+
return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16421
16445
|
}
|
|
16422
16446
|
get vertoPing$() {
|
|
16423
|
-
return this.cachedObservable("vertoPing$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoPingInnerParams, "params"), (0, import_cjs$
|
|
16447
|
+
return this.cachedObservable("vertoPing$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoPingInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16424
16448
|
}
|
|
16425
16449
|
async executeVerto(message, optionals = {}) {
|
|
16426
16450
|
const webrtcVertoMessage = WebrtcVerto({
|
|
@@ -16445,7 +16469,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16445
16469
|
}
|
|
16446
16470
|
async sendLocalDescription(message, rtcPeerConnController) {
|
|
16447
16471
|
const vertoMethod = message.method;
|
|
16448
|
-
const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController,
|
|
16472
|
+
const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController, message);
|
|
16449
16473
|
try {
|
|
16450
16474
|
const response = await this.executeVerto(message, optionalsParams);
|
|
16451
16475
|
switch (vertoMethod) {
|
|
@@ -16458,8 +16482,9 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16458
16482
|
default:
|
|
16459
16483
|
}
|
|
16460
16484
|
} catch (error) {
|
|
16461
|
-
logger$
|
|
16485
|
+
logger$14.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
|
|
16462
16486
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16487
|
+
if (vertoMethod === "verto.modify") this.onModifyFailed?.();
|
|
16463
16488
|
}
|
|
16464
16489
|
}
|
|
16465
16490
|
async processModifyResponse(response, rtcPeerConnController) {
|
|
@@ -16472,7 +16497,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16472
16497
|
sdp
|
|
16473
16498
|
});
|
|
16474
16499
|
} catch (error) {
|
|
16475
|
-
logger$
|
|
16500
|
+
logger$14.warn("[WebRTCManager] Error processing modify response:", error);
|
|
16476
16501
|
const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
16477
16502
|
this.onError?.(modifyError);
|
|
16478
16503
|
}
|
|
@@ -16484,19 +16509,24 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16484
16509
|
this._nodeId$.next(getValueFrom(response, "result.node_id") ?? null);
|
|
16485
16510
|
const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
|
|
16486
16511
|
const callId = getValueFrom(response, "result.result.result.callID") ?? null;
|
|
16487
|
-
logger$
|
|
16512
|
+
logger$14.debug("[WebRTCManager] Verto invite response:", {
|
|
16488
16513
|
callId,
|
|
16489
16514
|
memberId,
|
|
16490
16515
|
response
|
|
16491
16516
|
});
|
|
16492
16517
|
this._selfId$.next(memberId);
|
|
16493
16518
|
rtcPeerConnController.setMemberId(memberId);
|
|
16494
|
-
if (callId)
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
logger$
|
|
16519
|
+
if (callId) {
|
|
16520
|
+
this.webRtcCallSession.addCallId(callId);
|
|
16521
|
+
this.attachManager.attach(this.buildAttachableCall(callId));
|
|
16522
|
+
} else logger$14.warn("[WebRTCManager] Cannot attach call, missing callId:", {
|
|
16523
|
+
nodeId: this.nodeId,
|
|
16524
|
+
callId
|
|
16525
|
+
});
|
|
16526
|
+
logger$14.info("[WebRTCManager] Verto invite successful");
|
|
16527
|
+
logger$14.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
|
|
16498
16528
|
} else {
|
|
16499
|
-
logger$
|
|
16529
|
+
logger$14.error("[WebRTCManager] Verto invite failed:", response);
|
|
16500
16530
|
const inviteError = response.error ? new JSONRPCError(response.error.code, response.error.message, response.error.data) : /* @__PURE__ */ new Error("Verto invite failed: unexpected response");
|
|
16501
16531
|
this.onError?.(inviteError);
|
|
16502
16532
|
}
|
|
@@ -16541,17 +16571,17 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16541
16571
|
if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
|
|
16542
16572
|
}
|
|
16543
16573
|
async handleInboundAnswer(rtcPeerConnController) {
|
|
16544
|
-
logger$
|
|
16545
|
-
const vertoByeOrAccepted = await (0, import_cjs$
|
|
16574
|
+
logger$14.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
|
|
16575
|
+
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);
|
|
16546
16576
|
if (vertoByeOrAccepted === null) {
|
|
16547
|
-
logger$
|
|
16577
|
+
logger$14.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
|
|
16548
16578
|
return;
|
|
16549
16579
|
}
|
|
16550
16580
|
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
16551
|
-
logger$
|
|
16581
|
+
logger$14.info("[WebRTCManager] Inbound call ended by remote before answer.");
|
|
16552
16582
|
this.callSession?.destroy();
|
|
16553
16583
|
} else if (!vertoByeOrAccepted) {
|
|
16554
|
-
logger$
|
|
16584
|
+
logger$14.info("[WebRTCManager] Inbound call rejected by user.");
|
|
16555
16585
|
try {
|
|
16556
16586
|
await this.bye("USER_BUSY");
|
|
16557
16587
|
} finally {
|
|
@@ -16559,21 +16589,22 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16559
16589
|
this.callSession?.destroy();
|
|
16560
16590
|
}
|
|
16561
16591
|
} else {
|
|
16562
|
-
logger$
|
|
16592
|
+
logger$14.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
|
|
16563
16593
|
const answerOptions = this.webRtcCallSession.answerMediaOptions;
|
|
16564
16594
|
try {
|
|
16565
16595
|
await rtcPeerConnController.acceptInbound(answerOptions);
|
|
16566
16596
|
} catch (error) {
|
|
16567
|
-
logger$
|
|
16597
|
+
logger$14.error("[WebRTCManager] Error creating inbound answer:", error);
|
|
16568
16598
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16569
16599
|
}
|
|
16570
16600
|
}
|
|
16571
16601
|
}
|
|
16572
16602
|
setupVertoAttachHandler() {
|
|
16573
16603
|
this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
|
|
16574
|
-
logger$
|
|
16604
|
+
logger$14.debug("[WebRTCManager] Received Verto attach event for existing call:", vertoAttach);
|
|
16575
16605
|
const { callID } = vertoAttach;
|
|
16576
16606
|
await this.attachManager.attach({
|
|
16607
|
+
nodeId: this.nodeId ?? void 0,
|
|
16577
16608
|
id: callID,
|
|
16578
16609
|
to: vertoAttach.callee_id_number,
|
|
16579
16610
|
mediaDirections: {
|
|
@@ -16584,12 +16615,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16584
16615
|
});
|
|
16585
16616
|
}
|
|
16586
16617
|
initObservables(rtcPeerConnController) {
|
|
16587
|
-
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$
|
|
16588
|
-
this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$
|
|
16589
|
-
this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$
|
|
16618
|
+
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$));
|
|
16619
|
+
this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16620
|
+
this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16590
16621
|
}
|
|
16591
16622
|
setupLocalDescriptionHandler(rtcPeerConnController) {
|
|
16592
|
-
this.subscribeTo(rtcPeerConnController.localDescription$.pipe((0, import_cjs$
|
|
16623
|
+
this.subscribeTo(rtcPeerConnController.localDescription$.pipe((0, import_cjs$13.filter)((description) => description !== null), (0, import_cjs$13.takeUntil)(this.destroyed$)), (description) => {
|
|
16593
16624
|
const { type, sdp } = description;
|
|
16594
16625
|
const dialogParams = this.dialogParams(rtcPeerConnController);
|
|
16595
16626
|
const initial = !rtcPeerConnController.firstSDPExchangeCompleted;
|
|
@@ -16618,11 +16649,11 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16618
16649
|
setupVertoByeHandler() {
|
|
16619
16650
|
this.subscribeTo(this.vertoBye$, () => {
|
|
16620
16651
|
this._signalingStatus$.next("disconnected");
|
|
16621
|
-
this.attachManager.detach(this.
|
|
16652
|
+
this.attachManager.detach(this.buildAttachableCall());
|
|
16622
16653
|
this.callSession?.destroy();
|
|
16623
16654
|
});
|
|
16624
16655
|
}
|
|
16625
|
-
getSendLocalSDPOptionalParams(rtcPeerConnController,
|
|
16656
|
+
getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMessage) {
|
|
16626
16657
|
let subscribe = void 0;
|
|
16627
16658
|
if (!rtcPeerConnController.firstSDPExchangeCompleted) {
|
|
16628
16659
|
subscribe = [];
|
|
@@ -16630,7 +16661,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16630
16661
|
else if (rtcPeerConnController.isAdditionalDevice) subscribe.push(...PreferencesContainer.instance.inviteSubscribeAdditionalDevice);
|
|
16631
16662
|
else if (rtcPeerConnController.isScreenShare) subscribe.push(...PreferencesContainer.instance.inviteSubscribeScreenshare);
|
|
16632
16663
|
}
|
|
16633
|
-
const isInvite =
|
|
16664
|
+
const isInvite = isVertoInviteMessage(vertoMessage);
|
|
16634
16665
|
const isReattach = isInvite && this.webRtcCallSession.options.reattach;
|
|
16635
16666
|
return {
|
|
16636
16667
|
callID: rtcPeerConnController.id,
|
|
@@ -16639,13 +16670,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16639
16670
|
};
|
|
16640
16671
|
}
|
|
16641
16672
|
async sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnectionController) {
|
|
16642
|
-
logger$
|
|
16643
|
-
const vertoByeOrAccepted = await (0, import_cjs$
|
|
16673
|
+
logger$14.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");
|
|
16674
|
+
const vertoByeOrAccepted = await (0, import_cjs$13.firstValueFrom)((0, import_cjs$13.race)(this.vertoBye$, this.webRtcCallSession.answered$));
|
|
16644
16675
|
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
16645
|
-
logger$
|
|
16676
|
+
logger$14.info("[WebRTCManager] Call ended before answer was sent.");
|
|
16646
16677
|
this.callSession?.destroy();
|
|
16647
16678
|
} else if (!vertoByeOrAccepted) {
|
|
16648
|
-
logger$
|
|
16679
|
+
logger$14.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
|
|
16649
16680
|
try {
|
|
16650
16681
|
await this.bye("USER_BUSY");
|
|
16651
16682
|
} finally {
|
|
@@ -16653,14 +16684,14 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16653
16684
|
this.callSession?.destroy();
|
|
16654
16685
|
}
|
|
16655
16686
|
} else {
|
|
16656
|
-
logger$
|
|
16687
|
+
logger$14.debug("[WebRTCManager] Call accepted, sending answer");
|
|
16657
16688
|
try {
|
|
16658
16689
|
this._signalingStatus$.next("connecting");
|
|
16659
16690
|
await this.sendLocalDescription(vertoMessageRequest, rtcPeerConnectionController);
|
|
16660
16691
|
await rtcPeerConnectionController.updateAnswerStatus({ status: "sent" });
|
|
16661
|
-
await this.attachManager.attach(this.
|
|
16692
|
+
await this.attachManager.attach(this.buildAttachableCall());
|
|
16662
16693
|
} catch (error) {
|
|
16663
|
-
logger$
|
|
16694
|
+
logger$14.error("[WebRTCManager] Error sending Verto answer:", error);
|
|
16664
16695
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16665
16696
|
await rtcPeerConnectionController.updateAnswerStatus({ status: "failed" });
|
|
16666
16697
|
}
|
|
@@ -16749,12 +16780,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16749
16780
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
16750
16781
|
this.onError?.(error);
|
|
16751
16782
|
});
|
|
16752
|
-
await (0, import_cjs$
|
|
16783
|
+
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)));
|
|
16753
16784
|
this._screenShareStatus$.next("started");
|
|
16754
|
-
logger$
|
|
16785
|
+
logger$14.info("[WebRTCManager] Screen share started successfully.");
|
|
16755
16786
|
return rtcPeerConnController.id;
|
|
16756
16787
|
} catch (error) {
|
|
16757
|
-
logger$
|
|
16788
|
+
logger$14.warn("[WebRTCManager] Error initializing additional peer connection:", error);
|
|
16758
16789
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16759
16790
|
if (rtcPeerConnController) rtcPeerConnController.destroy();
|
|
16760
16791
|
this._screenShareStatus$.next("none");
|
|
@@ -16773,9 +16804,9 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16773
16804
|
if (removeTrack) return this.mainPeerConnection.stopTrackSender(removeTrack, { updateTransceiverDirection: true });
|
|
16774
16805
|
}
|
|
16775
16806
|
async removeScreenMedia() {
|
|
16776
|
-
if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$
|
|
16807
|
+
if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$14.warn("[WebRTCManager] No active screen share to stop.");
|
|
16777
16808
|
if (!this._screenShareId) {
|
|
16778
|
-
logger$
|
|
16809
|
+
logger$14.debug("[WebRTCManager] No screen share peer connection found.");
|
|
16779
16810
|
return;
|
|
16780
16811
|
}
|
|
16781
16812
|
this._screenShareStatus$.next("stopping");
|
|
@@ -16804,12 +16835,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16804
16835
|
dialogParams: this.dialogParams(rtcPeerConnController)
|
|
16805
16836
|
}));
|
|
16806
16837
|
} catch (error) {
|
|
16807
|
-
logger$
|
|
16838
|
+
logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:", error);
|
|
16808
16839
|
throw error;
|
|
16809
16840
|
}
|
|
16810
16841
|
}
|
|
16811
16842
|
async bye(cause) {
|
|
16812
|
-
this.attachManager.detach(this.
|
|
16843
|
+
this.attachManager.detach(this.buildAttachableCall());
|
|
16813
16844
|
const rtcPeerConnController = this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id);
|
|
16814
16845
|
if (rtcPeerConnController) await this.executeVertoBye(rtcPeerConnController, cause);
|
|
16815
16846
|
}
|
|
@@ -16822,7 +16853,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16822
16853
|
try {
|
|
16823
16854
|
await this.executeVerto(vertoInfoMessage);
|
|
16824
16855
|
} catch (error) {
|
|
16825
|
-
logger$
|
|
16856
|
+
logger$14.warn("[WebRTCManager] Error sending DTMF digits:", error);
|
|
16826
16857
|
throw error;
|
|
16827
16858
|
}
|
|
16828
16859
|
}
|
|
@@ -16833,10 +16864,10 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16833
16864
|
action: "transfer"
|
|
16834
16865
|
});
|
|
16835
16866
|
try {
|
|
16836
|
-
logger$
|
|
16867
|
+
logger$14.debug("[WebRTCManager] Transferring call with options:", options);
|
|
16837
16868
|
await this.executeVerto(message);
|
|
16838
16869
|
} catch (error) {
|
|
16839
|
-
logger$
|
|
16870
|
+
logger$14.error("[WebRTCManager] Error transferring call:", error);
|
|
16840
16871
|
throw error;
|
|
16841
16872
|
}
|
|
16842
16873
|
}
|
|
@@ -16852,8 +16883,8 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16852
16883
|
|
|
16853
16884
|
//#endregion
|
|
16854
16885
|
//#region src/controllers/RTCStatsMonitor.ts
|
|
16855
|
-
var import_cjs$
|
|
16856
|
-
const logger$
|
|
16886
|
+
var import_cjs$12 = require_cjs();
|
|
16887
|
+
const logger$13 = getLogger();
|
|
16857
16888
|
const DEFAULT_POLLING_INTERVAL_MS = 1e3;
|
|
16858
16889
|
const DEFAULT_BASELINE_SAMPLES = 10;
|
|
16859
16890
|
const DEFAULT_NO_AUDIO_PACKET_THRESHOLD_MS = 2e3;
|
|
@@ -16915,7 +16946,7 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16915
16946
|
}
|
|
16916
16947
|
/** Simple boolean health indicator. */
|
|
16917
16948
|
get isNetworkHealthy$() {
|
|
16918
|
-
return this.cachedObservable("isNetworkHealthy$", () => this._networkIssues$.pipe((0, import_cjs$
|
|
16949
|
+
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$)));
|
|
16919
16950
|
}
|
|
16920
16951
|
/** Whether the network is currently healthy. */
|
|
16921
16952
|
get isNetworkHealthy() {
|
|
@@ -16931,7 +16962,7 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16931
16962
|
}
|
|
16932
16963
|
/** Emits individual critical issues for the recovery pipeline. */
|
|
16933
16964
|
get criticalIssue$() {
|
|
16934
|
-
return this.cachedObservable("criticalIssue$", () => this._networkIssues$.pipe((0, import_cjs$
|
|
16965
|
+
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$)));
|
|
16935
16966
|
}
|
|
16936
16967
|
/** Emits each raw stats sample extracted from the peer connection. */
|
|
16937
16968
|
get sample$() {
|
|
@@ -16943,32 +16974,32 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16943
16974
|
const now = Date.now();
|
|
16944
16975
|
this.lastAudioPacketChangeTime = now;
|
|
16945
16976
|
this.lastVideoPacketChangeTime = now;
|
|
16946
|
-
logger$
|
|
16947
|
-
this.subscribeTo((0, import_cjs$
|
|
16948
|
-
logger$
|
|
16949
|
-
return import_cjs$
|
|
16950
|
-
}))), (0, import_cjs$
|
|
16951
|
-
this.subscribeTo(this._sample$.pipe((0, import_cjs$
|
|
16977
|
+
logger$13.debug("[RTCStatsMonitor] Starting stats monitoring");
|
|
16978
|
+
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) => {
|
|
16979
|
+
logger$13.warn("[RTCStatsMonitor] Failed to get stats:", err);
|
|
16980
|
+
return import_cjs$12.EMPTY;
|
|
16981
|
+
}))), (0, import_cjs$12.filter)(() => this.running), (0, import_cjs$12.map)((report) => this.extractSample(report))), (sample$1) => this._sample$.next(sample$1));
|
|
16982
|
+
this.subscribeTo(this._sample$.pipe((0, import_cjs$12.take)(this.baselineSampleCount), (0, import_cjs$12.toArray)(), (0, import_cjs$12.map)((samples) => ({
|
|
16952
16983
|
rtt: samples.reduce((s, b) => s + b.roundTripTime, 0) / samples.length,
|
|
16953
16984
|
jitter: samples.reduce((s, b) => s + b.audioJitter, 0) / samples.length,
|
|
16954
16985
|
ready: true
|
|
16955
16986
|
}))), (baseline) => {
|
|
16956
|
-
logger$
|
|
16987
|
+
logger$13.debug(`[RTCStatsMonitor] Baseline established: rtt=${baseline.rtt.toFixed(1)}ms, jitter=${baseline.jitter.toFixed(1)}ms`);
|
|
16957
16988
|
this._baseline$.next(baseline);
|
|
16958
16989
|
});
|
|
16959
|
-
this.subscribeTo(this._sample$.pipe((0, import_cjs$
|
|
16990
|
+
this.subscribeTo(this._sample$.pipe((0, import_cjs$12.scan)((acc, sample$1) => ({
|
|
16960
16991
|
prev: acc.current,
|
|
16961
16992
|
current: sample$1
|
|
16962
16993
|
}), {
|
|
16963
16994
|
prev: null,
|
|
16964
16995
|
current: null
|
|
16965
|
-
}), (0, import_cjs$
|
|
16996
|
+
}), (0, import_cjs$12.filter)((pair) => pair.current !== null)), ({ prev, current }) => {
|
|
16966
16997
|
const now$1 = current.timestamp;
|
|
16967
16998
|
this.updatePacketTracking(current, now$1);
|
|
16968
16999
|
const issues = this.detectIssues(current, prev, now$1);
|
|
16969
17000
|
this._networkIssues$.next(issues);
|
|
16970
17001
|
});
|
|
16971
|
-
this.subscribeTo(this._sample$.pipe((0, import_cjs$
|
|
17002
|
+
this.subscribeTo(this._sample$.pipe((0, import_cjs$12.scan)((history, sample$1) => {
|
|
16972
17003
|
const cutoff = sample$1.timestamp - this.historyWindowSeconds * 1e3;
|
|
16973
17004
|
const metrics = {
|
|
16974
17005
|
timestamp: sample$1.timestamp,
|
|
@@ -16990,10 +17021,10 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16990
17021
|
stop() {
|
|
16991
17022
|
if (!this.running) return;
|
|
16992
17023
|
this.running = false;
|
|
16993
|
-
logger$
|
|
17024
|
+
logger$13.debug("[RTCStatsMonitor] Stopping stats monitoring");
|
|
16994
17025
|
}
|
|
16995
17026
|
destroy() {
|
|
16996
|
-
logger$
|
|
17027
|
+
logger$13.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor");
|
|
16997
17028
|
this.stop();
|
|
16998
17029
|
super.destroy();
|
|
16999
17030
|
}
|
|
@@ -17121,8 +17152,8 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
17121
17152
|
|
|
17122
17153
|
//#endregion
|
|
17123
17154
|
//#region src/managers/CallRecoveryManager.ts
|
|
17124
|
-
var import_cjs$
|
|
17125
|
-
const logger$
|
|
17155
|
+
var import_cjs$11 = require_cjs();
|
|
17156
|
+
const logger$12 = getLogger();
|
|
17126
17157
|
const DEFAULT_DEBOUNCE_TIME_MS = 2e3;
|
|
17127
17158
|
const DEFAULT_COOLDOWN_MS = 1e4;
|
|
17128
17159
|
const DEFAULT_ICE_GRACE_PERIOD_MS = 3e3;
|
|
@@ -17158,7 +17189,7 @@ const DEGRADATION_ONLY_ISSUES = new Set([
|
|
|
17158
17189
|
* A state machine tracks the pipeline: IDLE -> DEBOUNCING -> RECOVERING -> COOLDOWN.
|
|
17159
17190
|
*/
|
|
17160
17191
|
var CallRecoveryManager = class extends Destroyable {
|
|
17161
|
-
constructor(callbacks, config = {}) {
|
|
17192
|
+
constructor(callbacks, inputs, config = {}) {
|
|
17162
17193
|
super();
|
|
17163
17194
|
this._recoveryState$ = this.createBehaviorSubject("idle");
|
|
17164
17195
|
this._recoveryEvent$ = this.createSubject();
|
|
@@ -17172,6 +17203,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17172
17203
|
this._cooldownUntil = 0;
|
|
17173
17204
|
this._pipelineStop$ = this.createSubject();
|
|
17174
17205
|
this._callbacks = callbacks;
|
|
17206
|
+
this._inputs = inputs;
|
|
17175
17207
|
this._config = {
|
|
17176
17208
|
debounceTimeMs: config.debounceTimeMs ?? DEFAULT_DEBOUNCE_TIME_MS,
|
|
17177
17209
|
cooldownMs: config.cooldownMs ?? DEFAULT_COOLDOWN_MS,
|
|
@@ -17191,16 +17223,16 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17191
17223
|
this.initDegradationRecoveryPipeline();
|
|
17192
17224
|
}
|
|
17193
17225
|
get recoveryState$() {
|
|
17194
|
-
return this._recoveryState$.asObservable().pipe((0, import_cjs$
|
|
17226
|
+
return this._recoveryState$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
|
|
17195
17227
|
}
|
|
17196
17228
|
get recoveryState() {
|
|
17197
17229
|
return this._recoveryState$.value;
|
|
17198
17230
|
}
|
|
17199
17231
|
get recoveryEvent$() {
|
|
17200
|
-
return this._recoveryEvent$.asObservable().pipe((0, import_cjs$
|
|
17232
|
+
return this._recoveryEvent$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
|
|
17201
17233
|
}
|
|
17202
17234
|
get bandwidthConstrained$() {
|
|
17203
|
-
return this._bandwidthConstrained$.asObservable().pipe((0, import_cjs$
|
|
17235
|
+
return this._bandwidthConstrained$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
|
|
17204
17236
|
}
|
|
17205
17237
|
get bandwidthConstrained() {
|
|
17206
17238
|
return this._bandwidthConstrained$.value;
|
|
@@ -17218,10 +17250,10 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17218
17250
|
*/
|
|
17219
17251
|
async requestIceRestart() {
|
|
17220
17252
|
if (this._recoveryState$.value === "recovering") {
|
|
17221
|
-
logger$
|
|
17253
|
+
logger$12.info("CallRecoveryManager: manual ICE restart skipped — recovery already in progress");
|
|
17222
17254
|
return;
|
|
17223
17255
|
}
|
|
17224
|
-
logger$
|
|
17256
|
+
logger$12.info("CallRecoveryManager: manual ICE restart requested");
|
|
17225
17257
|
this.transitionTo("recovering");
|
|
17226
17258
|
await this.executeIceRestart(false);
|
|
17227
17259
|
this.startCooldown();
|
|
@@ -17237,7 +17269,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17237
17269
|
* WebSocket reconnect or call state recovers to 'connected'.
|
|
17238
17270
|
*/
|
|
17239
17271
|
reset() {
|
|
17240
|
-
logger$
|
|
17272
|
+
logger$12.info("CallRecoveryManager: resetting counters");
|
|
17241
17273
|
this._attemptCount = 0;
|
|
17242
17274
|
this._keyframeBurstCount = 0;
|
|
17243
17275
|
this._keyframeBurstStart = 0;
|
|
@@ -17246,6 +17278,22 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17246
17278
|
this.transitionTo("idle");
|
|
17247
17279
|
}
|
|
17248
17280
|
/**
|
|
17281
|
+
* Notify the recovery manager that a verto.modify (ICE restart SDP exchange)
|
|
17282
|
+
* failed at the signaling layer. Resets cooldown and pushes a new trigger
|
|
17283
|
+
* so recovery can re-attempt.
|
|
17284
|
+
*/
|
|
17285
|
+
notifyModifyFailed() {
|
|
17286
|
+
if (this._recoveryState$.value === "cooldown" || this._recoveryState$.value === "idle") {
|
|
17287
|
+
logger$12.info("CallRecoveryManager: verto.modify failed — re-entering recovery");
|
|
17288
|
+
this._cooldownUntil = 0;
|
|
17289
|
+
this.transitionTo("idle");
|
|
17290
|
+
this.pushTrigger({
|
|
17291
|
+
source: "network",
|
|
17292
|
+
detail: "modify_failed_during_recovery"
|
|
17293
|
+
});
|
|
17294
|
+
}
|
|
17295
|
+
}
|
|
17296
|
+
/**
|
|
17249
17297
|
* Feed bandwidth information for graceful degradation (Section 22).
|
|
17250
17298
|
* Call this from the stats monitor with current available outgoing bitrate.
|
|
17251
17299
|
*/
|
|
@@ -17260,7 +17308,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17260
17308
|
reason: `bandwidth ${bitrateKbps}kbps below threshold ${this._config.degradationBitrateThreshold}kbps`,
|
|
17261
17309
|
timestamp: Date.now()
|
|
17262
17310
|
});
|
|
17263
|
-
logger$
|
|
17311
|
+
logger$12.warn(`CallRecoveryManager: disabling video — bandwidth ${bitrateKbps}kbps < ${this._config.degradationBitrateThreshold}kbps`);
|
|
17264
17312
|
} else if (wasConstrained && bitrateKbps >= this._config.degradationRecoveryThreshold) {
|
|
17265
17313
|
this._bandwidthConstrained$.next(false);
|
|
17266
17314
|
this._callbacks.enableVideo();
|
|
@@ -17269,7 +17317,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17269
17317
|
reason: `bandwidth ${bitrateKbps}kbps recovered above ${this._config.degradationRecoveryThreshold}kbps`,
|
|
17270
17318
|
timestamp: Date.now()
|
|
17271
17319
|
});
|
|
17272
|
-
logger$
|
|
17320
|
+
logger$12.info(`CallRecoveryManager: restoring video — bandwidth ${bitrateKbps}kbps >= ${this._config.degradationRecoveryThreshold}kbps`);
|
|
17273
17321
|
}
|
|
17274
17322
|
}
|
|
17275
17323
|
/**
|
|
@@ -17288,14 +17336,14 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17288
17336
|
handleWebSocketReconnect() {
|
|
17289
17337
|
const pcState = this._callbacks.getPeerConnectionState();
|
|
17290
17338
|
if (pcState === "connected" || pcState === "completed") {
|
|
17291
|
-
logger$
|
|
17339
|
+
logger$12.info("CallRecoveryManager: signal-only reconnect — peer connection still alive");
|
|
17292
17340
|
this.emitEvent({
|
|
17293
17341
|
action: "signal_reconnect",
|
|
17294
17342
|
reason: "WebSocket reconnected, peer connection still connected",
|
|
17295
17343
|
timestamp: Date.now()
|
|
17296
17344
|
});
|
|
17297
17345
|
} else {
|
|
17298
|
-
logger$
|
|
17346
|
+
logger$12.info("CallRecoveryManager: full reconnect — peer connection also down");
|
|
17299
17347
|
this.emitEvent({
|
|
17300
17348
|
action: "full_reconnect",
|
|
17301
17349
|
reason: "WebSocket reconnected, peer connection not connected — ICE restart needed",
|
|
@@ -17314,12 +17362,12 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17314
17362
|
super.destroy();
|
|
17315
17363
|
}
|
|
17316
17364
|
initPipeline() {
|
|
17317
|
-
this.subscribeTo(this._trigger$.pipe((0, import_cjs$
|
|
17365
|
+
this.subscribeTo(this._trigger$.pipe((0, import_cjs$11.tap)(() => {
|
|
17318
17366
|
if (this._recoveryState$.value === "idle") this.transitionTo("debouncing");
|
|
17319
|
-
}), (0, import_cjs$
|
|
17367
|
+
}), (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$))), {
|
|
17320
17368
|
next: () => {},
|
|
17321
17369
|
error: (err) => {
|
|
17322
|
-
logger$
|
|
17370
|
+
logger$12.error("CallRecoveryManager: pipeline error", err);
|
|
17323
17371
|
this.transitionTo("idle");
|
|
17324
17372
|
}
|
|
17325
17373
|
});
|
|
@@ -17335,10 +17383,10 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17335
17383
|
initDegradationRecoveryPipeline() {
|
|
17336
17384
|
if (!this._config.enableAutoDegradation) return;
|
|
17337
17385
|
const delayMs = this._config.packetLossRecoveryDelaySec * 1e3;
|
|
17338
|
-
this.subscribeTo((0, import_cjs$
|
|
17339
|
-
if (constrained && !hasPacketLoss) return (0, import_cjs$
|
|
17340
|
-
return import_cjs$
|
|
17341
|
-
}), (0, import_cjs$
|
|
17386
|
+
this.subscribeTo((0, import_cjs$11.combineLatest)([this._bandwidthConstrained$, this._hasPacketLoss$]).pipe((0, import_cjs$11.switchMap)(([constrained, hasPacketLoss]) => {
|
|
17387
|
+
if (constrained && !hasPacketLoss) return (0, import_cjs$11.timer)(delayMs);
|
|
17388
|
+
return import_cjs$11.EMPTY;
|
|
17389
|
+
}), (0, import_cjs$11.takeUntil)(this._destroyed$)), () => {
|
|
17342
17390
|
this._bandwidthConstrained$.next(false);
|
|
17343
17391
|
this._callbacks.enableVideo();
|
|
17344
17392
|
this.emitEvent({
|
|
@@ -17346,27 +17394,27 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17346
17394
|
reason: `no packet loss for ${this._config.packetLossRecoveryDelaySec}s — restoring video`,
|
|
17347
17395
|
timestamp: Date.now()
|
|
17348
17396
|
});
|
|
17349
|
-
logger$
|
|
17397
|
+
logger$12.info(`CallRecoveryManager: restoring video — no packet loss for ${this._config.packetLossRecoveryDelaySec}s`);
|
|
17350
17398
|
});
|
|
17351
17399
|
}
|
|
17352
|
-
passGateChecks() {
|
|
17400
|
+
passGateChecks(signalingReady) {
|
|
17353
17401
|
if (this._callbacks.isNegotiating()) {
|
|
17354
|
-
logger$
|
|
17402
|
+
logger$12.debug("CallRecoveryManager: gate blocked — negotiation in progress");
|
|
17355
17403
|
this.transitionTo("idle");
|
|
17356
17404
|
return false;
|
|
17357
17405
|
}
|
|
17358
|
-
if (!
|
|
17359
|
-
logger$
|
|
17406
|
+
if (!signalingReady) {
|
|
17407
|
+
logger$12.debug("CallRecoveryManager: gate blocked — signaling not ready");
|
|
17360
17408
|
this.transitionTo("idle");
|
|
17361
17409
|
return false;
|
|
17362
17410
|
}
|
|
17363
17411
|
if (!this._callbacks.isCallConnected()) {
|
|
17364
|
-
logger$
|
|
17412
|
+
logger$12.debug("CallRecoveryManager: gate blocked — call not connected");
|
|
17365
17413
|
this.transitionTo("idle");
|
|
17366
17414
|
return false;
|
|
17367
17415
|
}
|
|
17368
17416
|
if (this.isCooldownActive()) {
|
|
17369
|
-
logger$
|
|
17417
|
+
logger$12.debug("CallRecoveryManager: gate blocked — cooldown active");
|
|
17370
17418
|
this.transitionTo("cooldown");
|
|
17371
17419
|
return false;
|
|
17372
17420
|
}
|
|
@@ -17377,17 +17425,17 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17377
17425
|
}
|
|
17378
17426
|
executeTieredRecovery(trigger) {
|
|
17379
17427
|
this.transitionTo("recovering");
|
|
17380
|
-
logger$
|
|
17381
|
-
return (0, import_cjs$
|
|
17382
|
-
logger$
|
|
17428
|
+
logger$12.info(`CallRecoveryManager: starting tiered recovery — source=${trigger.source} detail=${trigger.detail}`);
|
|
17429
|
+
return (0, import_cjs$11.from)(this.runTiers(trigger)).pipe((0, import_cjs$11.tap)(() => this.startCooldown()), (0, import_cjs$11.catchError)((err) => {
|
|
17430
|
+
logger$12.error("CallRecoveryManager: tiered recovery failed", err);
|
|
17383
17431
|
this.startCooldown();
|
|
17384
|
-
return import_cjs$
|
|
17432
|
+
return import_cjs$11.EMPTY;
|
|
17385
17433
|
}));
|
|
17386
17434
|
}
|
|
17387
17435
|
async runTiers(trigger) {
|
|
17388
17436
|
this.executeKeyframe(trigger.detail);
|
|
17389
17437
|
if (trigger.issueType && DEGRADATION_ONLY_ISSUES.has(trigger.issueType)) {
|
|
17390
|
-
logger$
|
|
17438
|
+
logger$12.debug(`CallRecoveryManager: degradation-only issue (${trigger.issueType}) — Tier 1 only, skipping ICE restart`);
|
|
17391
17439
|
return;
|
|
17392
17440
|
}
|
|
17393
17441
|
if (this._attemptCount < this._config.maxAttempts) {
|
|
@@ -17404,13 +17452,13 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17404
17452
|
maxAttempts: this._config.maxAttempts,
|
|
17405
17453
|
timestamp: Date.now()
|
|
17406
17454
|
});
|
|
17407
|
-
logger$
|
|
17455
|
+
logger$12.warn("CallRecoveryManager: max recovery attempts reached");
|
|
17408
17456
|
}
|
|
17409
17457
|
}
|
|
17410
17458
|
executeKeyframe(reason) {
|
|
17411
17459
|
const now = Date.now();
|
|
17412
17460
|
if (now < this._keyframeCooldownUntil) {
|
|
17413
|
-
logger$
|
|
17461
|
+
logger$12.debug("CallRecoveryManager: keyframe request skipped — cooldown active");
|
|
17414
17462
|
return;
|
|
17415
17463
|
}
|
|
17416
17464
|
if (now - this._keyframeBurstStart > this._config.keyframeBurstWindowMs) {
|
|
@@ -17419,7 +17467,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17419
17467
|
}
|
|
17420
17468
|
if (this._keyframeBurstCount >= this._config.keyframeMaxBurst) {
|
|
17421
17469
|
this._keyframeCooldownUntil = now + this._config.keyframeCooldownMs;
|
|
17422
|
-
logger$
|
|
17470
|
+
logger$12.debug(`CallRecoveryManager: keyframe burst limit reached (${this._config.keyframeMaxBurst}), cooldown until ${this._keyframeCooldownUntil}`);
|
|
17423
17471
|
return;
|
|
17424
17472
|
}
|
|
17425
17473
|
this._keyframeBurstCount += 1;
|
|
@@ -17429,12 +17477,12 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17429
17477
|
reason,
|
|
17430
17478
|
timestamp: now
|
|
17431
17479
|
});
|
|
17432
|
-
logger$
|
|
17480
|
+
logger$12.debug(`CallRecoveryManager: keyframe requested (burst ${this._keyframeBurstCount}/${this._config.keyframeMaxBurst})`);
|
|
17433
17481
|
}
|
|
17434
17482
|
async executeIceRestart(relayOnly) {
|
|
17435
17483
|
this._attemptCount += 1;
|
|
17436
17484
|
const tier = relayOnly ? "Tier 3 (relay-only)" : "Tier 2 (standard)";
|
|
17437
|
-
logger$
|
|
17485
|
+
logger$12.info(`CallRecoveryManager: ${tier} ICE restart — attempt ${this._attemptCount}/${this._config.maxAttempts}`);
|
|
17438
17486
|
this.emitEvent({
|
|
17439
17487
|
action: "reinvite_started",
|
|
17440
17488
|
reason: `${tier} ICE restart`,
|
|
@@ -17451,7 +17499,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17451
17499
|
maxAttempts: this._config.maxAttempts,
|
|
17452
17500
|
timestamp: Date.now()
|
|
17453
17501
|
});
|
|
17454
|
-
logger$
|
|
17502
|
+
logger$12.info(`CallRecoveryManager: ${tier} ICE restart succeeded`);
|
|
17455
17503
|
this._attemptCount = 0;
|
|
17456
17504
|
return true;
|
|
17457
17505
|
}
|
|
@@ -17462,7 +17510,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17462
17510
|
maxAttempts: this._config.maxAttempts,
|
|
17463
17511
|
timestamp: Date.now()
|
|
17464
17512
|
});
|
|
17465
|
-
logger$
|
|
17513
|
+
logger$12.warn(`CallRecoveryManager: ${tier} ICE restart failed`);
|
|
17466
17514
|
return false;
|
|
17467
17515
|
} catch {
|
|
17468
17516
|
this.emitEvent({
|
|
@@ -17472,7 +17520,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17472
17520
|
maxAttempts: this._config.maxAttempts,
|
|
17473
17521
|
timestamp: Date.now()
|
|
17474
17522
|
});
|
|
17475
|
-
logger$
|
|
17523
|
+
logger$12.warn(`CallRecoveryManager: ${tier} ICE restart timed out`);
|
|
17476
17524
|
return false;
|
|
17477
17525
|
}
|
|
17478
17526
|
}
|
|
@@ -17493,7 +17541,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17493
17541
|
transitionTo(state) {
|
|
17494
17542
|
const prev = this._recoveryState$.value;
|
|
17495
17543
|
if (prev !== state) {
|
|
17496
|
-
logger$
|
|
17544
|
+
logger$12.debug(`CallRecoveryManager: state ${prev} -> ${state}`);
|
|
17497
17545
|
this._recoveryState$.next(state);
|
|
17498
17546
|
}
|
|
17499
17547
|
}
|
|
@@ -17501,7 +17549,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17501
17549
|
this._cooldownUntil = Date.now() + this._config.cooldownMs;
|
|
17502
17550
|
this.transitionTo("cooldown");
|
|
17503
17551
|
if (this._cooldownSubscription) this._cooldownSubscription.unsubscribe();
|
|
17504
|
-
this._cooldownSubscription = (0, import_cjs$
|
|
17552
|
+
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"));
|
|
17505
17553
|
}
|
|
17506
17554
|
emitEvent(event) {
|
|
17507
17555
|
this._recoveryEvent$.next(event);
|
|
@@ -17595,8 +17643,8 @@ function mosToQualityLevel(mos) {
|
|
|
17595
17643
|
|
|
17596
17644
|
//#endregion
|
|
17597
17645
|
//#region src/core/entities/Call.ts
|
|
17598
|
-
var import_cjs$
|
|
17599
|
-
const logger$
|
|
17646
|
+
var import_cjs$10 = require_cjs();
|
|
17647
|
+
const logger$11 = getLogger();
|
|
17600
17648
|
/**
|
|
17601
17649
|
* Ratio between the critical and warning RTT spike multipliers.
|
|
17602
17650
|
* Warning threshold = baseline * warningMultiplier (default 3x)
|
|
@@ -17614,7 +17662,7 @@ const fromDestinationParams = (destination) => {
|
|
|
17614
17662
|
});
|
|
17615
17663
|
return params;
|
|
17616
17664
|
} catch (error) {
|
|
17617
|
-
logger$
|
|
17665
|
+
logger$11.warn(`Failed to parse destination URI: ${destination}`, error);
|
|
17618
17666
|
return {};
|
|
17619
17667
|
}
|
|
17620
17668
|
};
|
|
@@ -17670,10 +17718,13 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17670
17718
|
const { deviceController, networkChange$ } = initialization;
|
|
17671
17719
|
this._networkChange$ = networkChange$;
|
|
17672
17720
|
this.participantFactory = new ParticipantFactory(this.executeMethod.bind(this), this.vertoManager, deviceController);
|
|
17673
|
-
this.subscribeTo((0, import_cjs$
|
|
17721
|
+
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) => {
|
|
17674
17722
|
this._lastMergedStatus = status;
|
|
17675
17723
|
if (status === "connected" && !this._statsMonitor) this.initResilienceSubsystems();
|
|
17676
|
-
else if (status === "disconnected"
|
|
17724
|
+
else if (status === "disconnected") {
|
|
17725
|
+
this._statsMonitor?.destroy();
|
|
17726
|
+
this._statsMonitor = void 0;
|
|
17727
|
+
} else if (status === "destroyed" || status === "failed") this.stopResilienceSubsystems();
|
|
17677
17728
|
});
|
|
17678
17729
|
}
|
|
17679
17730
|
/** Observable stream of errors from media, signaling, and peer connection layers. */
|
|
@@ -17692,13 +17743,17 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17692
17743
|
this.destroy();
|
|
17693
17744
|
}
|
|
17694
17745
|
}
|
|
17746
|
+
/** Notify the recovery manager that a verto.modify signaling exchange failed. */
|
|
17747
|
+
notifyModifyFailed() {
|
|
17748
|
+
this._recoveryManager?.notifyModifyFailed();
|
|
17749
|
+
}
|
|
17695
17750
|
/** Whether this call is `'inbound'` or `'outbound'`. */
|
|
17696
17751
|
get direction() {
|
|
17697
17752
|
return this.options.initOffer ? "inbound" : "outbound";
|
|
17698
17753
|
}
|
|
17699
17754
|
/** Observable of the address associated with this call. */
|
|
17700
17755
|
get address$() {
|
|
17701
|
-
return this.deferEmission((0, import_cjs$
|
|
17756
|
+
return this.deferEmission((0, import_cjs$10.from)([this.address])).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17702
17757
|
}
|
|
17703
17758
|
/** Display name of the caller. */
|
|
17704
17759
|
get fromName() {
|
|
@@ -17777,7 +17832,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17777
17832
|
}
|
|
17778
17833
|
/** Observable of layout layer positions for all participants. */
|
|
17779
17834
|
get layoutLayers$() {
|
|
17780
|
-
return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, import_cjs$
|
|
17835
|
+
return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17781
17836
|
}
|
|
17782
17837
|
/** Current snapshot of layout layers. */
|
|
17783
17838
|
get layoutLayers() {
|
|
@@ -17805,7 +17860,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17805
17860
|
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);
|
|
17806
17861
|
return response;
|
|
17807
17862
|
} catch (error) {
|
|
17808
|
-
logger$
|
|
17863
|
+
logger$11.error(`[Call] Error executing method ${method} with params`, params, error);
|
|
17809
17864
|
throw error;
|
|
17810
17865
|
}
|
|
17811
17866
|
}
|
|
@@ -17832,45 +17887,45 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17832
17887
|
}
|
|
17833
17888
|
/** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
|
|
17834
17889
|
get status$() {
|
|
17835
|
-
return this.publicCachedObservable("status$", () => (0, import_cjs$
|
|
17890
|
+
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) => {
|
|
17836
17891
|
this._lastMergedStatus = status;
|
|
17837
17892
|
})));
|
|
17838
17893
|
}
|
|
17839
17894
|
/** Observable of the participants list, emits on join/leave/update. */
|
|
17840
17895
|
get participants$() {
|
|
17841
|
-
return this.deferEmission(this.callEventsManager.participants$).pipe((0, import_cjs$
|
|
17896
|
+
return this.deferEmission(this.callEventsManager.participants$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17842
17897
|
}
|
|
17843
17898
|
/** Observable of the local (self) participant. */
|
|
17844
17899
|
get self$() {
|
|
17845
|
-
return this.deferEmission(this.callEventsManager.self$).pipe((0, import_cjs$
|
|
17900
|
+
return this.deferEmission(this.callEventsManager.self$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17846
17901
|
}
|
|
17847
17902
|
/** Observable indicating whether the call is being recorded. */
|
|
17848
17903
|
get recording$() {
|
|
17849
|
-
return this.deferEmission(this.callEventsManager.recording$).pipe((0, import_cjs$
|
|
17904
|
+
return this.deferEmission(this.callEventsManager.recording$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17850
17905
|
}
|
|
17851
17906
|
/** Observable indicating whether the call is being streamed. */
|
|
17852
17907
|
get streaming$() {
|
|
17853
|
-
return this.deferEmission(this.callEventsManager.streaming$).pipe((0, import_cjs$
|
|
17908
|
+
return this.deferEmission(this.callEventsManager.streaming$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17854
17909
|
}
|
|
17855
17910
|
/** Observable indicating whether raise-hand priority is active. */
|
|
17856
17911
|
get raiseHandPriority$() {
|
|
17857
|
-
return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, import_cjs$
|
|
17912
|
+
return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17858
17913
|
}
|
|
17859
17914
|
/** Observable indicating whether the call room is locked. */
|
|
17860
17915
|
get locked$() {
|
|
17861
|
-
return this.deferEmission(this.callEventsManager.locked$).pipe((0, import_cjs$
|
|
17916
|
+
return this.deferEmission(this.callEventsManager.locked$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17862
17917
|
}
|
|
17863
17918
|
/** Observable of custom metadata associated with the call. */
|
|
17864
17919
|
get meta$() {
|
|
17865
|
-
return this.deferEmission(this.callEventsManager.meta$).pipe((0, import_cjs$
|
|
17920
|
+
return this.deferEmission(this.callEventsManager.meta$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17866
17921
|
}
|
|
17867
17922
|
/** Observable of the call's capability flags. */
|
|
17868
17923
|
get capabilities$() {
|
|
17869
|
-
return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, import_cjs$
|
|
17924
|
+
return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17870
17925
|
}
|
|
17871
17926
|
/** Observable of the current layout name. */
|
|
17872
17927
|
get layout$() {
|
|
17873
|
-
return this.deferEmission(this.callEventsManager.layout$).pipe((0, import_cjs$
|
|
17928
|
+
return this.deferEmission(this.callEventsManager.layout$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17874
17929
|
}
|
|
17875
17930
|
/** Current call status. */
|
|
17876
17931
|
get status() {
|
|
@@ -17902,7 +17957,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17902
17957
|
}
|
|
17903
17958
|
/** Observable of available layout names. */
|
|
17904
17959
|
get layouts$() {
|
|
17905
|
-
return this.deferEmission(this.callEventsManager.layouts$).pipe((0, import_cjs$
|
|
17960
|
+
return this.deferEmission(this.callEventsManager.layouts$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17906
17961
|
}
|
|
17907
17962
|
/** Current snapshot of available layout names. */
|
|
17908
17963
|
get layouts() {
|
|
@@ -17910,7 +17965,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17910
17965
|
}
|
|
17911
17966
|
/** Observable of the local media stream (camera/microphone). */
|
|
17912
17967
|
get localStream$() {
|
|
17913
|
-
return this.deferEmission(this.vertoManager.localStream$).pipe((0, import_cjs$
|
|
17968
|
+
return this.deferEmission(this.vertoManager.localStream$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17914
17969
|
}
|
|
17915
17970
|
/** Current local media stream, or `null` if not available. */
|
|
17916
17971
|
get localStream() {
|
|
@@ -17918,7 +17973,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17918
17973
|
}
|
|
17919
17974
|
/** Observable of the remote media stream from the far end. */
|
|
17920
17975
|
get remoteStream$() {
|
|
17921
|
-
return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, import_cjs$
|
|
17976
|
+
return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17922
17977
|
}
|
|
17923
17978
|
/** Current remote media stream, or `null` if not available. */
|
|
17924
17979
|
get remoteStream() {
|
|
@@ -18008,9 +18063,9 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18008
18063
|
*/
|
|
18009
18064
|
initResilienceSubsystems() {
|
|
18010
18065
|
const pc = this.rtcPeerConnection;
|
|
18011
|
-
logger$
|
|
18066
|
+
logger$11.debug(`[Call] initResilienceSubsystems: pc=${pc ? "exists" : "undefined"}, connectionState=${pc?.connectionState}`);
|
|
18012
18067
|
if (!pc) {
|
|
18013
|
-
logger$
|
|
18068
|
+
logger$11.warn("[Call] No peer connection available, skipping resilience init");
|
|
18014
18069
|
return;
|
|
18015
18070
|
}
|
|
18016
18071
|
try {
|
|
@@ -18045,21 +18100,20 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18045
18100
|
disableVideo: () => {
|
|
18046
18101
|
try {
|
|
18047
18102
|
this.vertoManager.muteMainVideoInputDevice();
|
|
18048
|
-
logger$
|
|
18103
|
+
logger$11.debug("[Call] Recovery manager disabled video");
|
|
18049
18104
|
} catch {
|
|
18050
|
-
logger$
|
|
18105
|
+
logger$11.debug("[Call] Recovery manager failed to disable video");
|
|
18051
18106
|
}
|
|
18052
18107
|
},
|
|
18053
18108
|
enableVideo: () => {
|
|
18054
18109
|
this.vertoManager.unmuteMainVideoInputDevice().catch(() => {
|
|
18055
|
-
logger$
|
|
18110
|
+
logger$11.debug("[Call] Recovery manager failed to enable video");
|
|
18056
18111
|
});
|
|
18057
18112
|
},
|
|
18058
18113
|
isNegotiating: () => this.vertoManager.mainPeerConnection.isNegotiating,
|
|
18059
|
-
isWebSocketConnected: () => this._lastMergedStatus !== "disconnected",
|
|
18060
18114
|
isCallConnected: () => this._lastMergedStatus === "connected",
|
|
18061
18115
|
getPeerConnectionState: () => pc.connectionState
|
|
18062
|
-
}, {
|
|
18116
|
+
}, { signalingReady$: this.clientSession.authenticated$ }, {
|
|
18063
18117
|
debounceTimeMs: prefs.recoveryDebounceTime,
|
|
18064
18118
|
cooldownMs: prefs.recoveryCooldown,
|
|
18065
18119
|
iceGracePeriodMs: prefs.iceDisconnectedGracePeriod,
|
|
@@ -18102,6 +18156,15 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18102
18156
|
});
|
|
18103
18157
|
this.subscribeTo(this._recoveryManager.recoveryEvent$, (event) => {
|
|
18104
18158
|
this._recoveryEvent$.next(event);
|
|
18159
|
+
if (event.action === "max_attempts_reached") {
|
|
18160
|
+
logger$11.warn("[Call] All recovery attempts exhausted, terminating call");
|
|
18161
|
+
this.emitError({
|
|
18162
|
+
kind: "network",
|
|
18163
|
+
fatal: true,
|
|
18164
|
+
error: /* @__PURE__ */ new Error("Call recovery failed: all attempts exhausted"),
|
|
18165
|
+
callId: this.id
|
|
18166
|
+
});
|
|
18167
|
+
}
|
|
18105
18168
|
});
|
|
18106
18169
|
this.subscribeTo(this._recoveryManager.bandwidthConstrained$, (constrained) => {
|
|
18107
18170
|
this._bandwidthConstrained$.next(constrained);
|
|
@@ -18113,14 +18176,14 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18113
18176
|
});
|
|
18114
18177
|
else if (event.type === "online") this._recoveryManager?.handleWebSocketReconnect();
|
|
18115
18178
|
});
|
|
18116
|
-
this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$
|
|
18117
|
-
logger$
|
|
18179
|
+
this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$10.skip)(1), (0, import_cjs$10.filter)(Boolean)), () => {
|
|
18180
|
+
logger$11.debug("[Call] WebSocket reconnected — notifying recovery manager");
|
|
18118
18181
|
this._recoveryManager?.handleWebSocketReconnect();
|
|
18119
18182
|
});
|
|
18120
18183
|
this._statsMonitor.start();
|
|
18121
|
-
logger$
|
|
18184
|
+
logger$11.debug("[Call] Resilience subsystems initialized for call", this.id);
|
|
18122
18185
|
} catch (error) {
|
|
18123
|
-
logger$
|
|
18186
|
+
logger$11.warn("[Call] Failed to initialize resilience subsystems:", error);
|
|
18124
18187
|
}
|
|
18125
18188
|
}
|
|
18126
18189
|
/**
|
|
@@ -18142,14 +18205,14 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18142
18205
|
}
|
|
18143
18206
|
/** Observable of the current audio/video send/receive directions. */
|
|
18144
18207
|
get mediaDirections$() {
|
|
18145
|
-
return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, import_cjs$
|
|
18208
|
+
return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
18146
18209
|
}
|
|
18147
18210
|
/** Current audio/video send/receive directions. */
|
|
18148
18211
|
get mediaDirections() {
|
|
18149
18212
|
return this.vertoManager.mediaDirections;
|
|
18150
18213
|
}
|
|
18151
18214
|
get participantsId$() {
|
|
18152
|
-
return this.cachedObservable("participantsId$", () => this.participants$.pipe((0, import_cjs$
|
|
18215
|
+
return this.cachedObservable("participantsId$", () => this.participants$.pipe((0, import_cjs$10.map)((participants) => participants.map((participant) => participant.id))));
|
|
18153
18216
|
}
|
|
18154
18217
|
/**
|
|
18155
18218
|
* Executes a raw JSON-RPC request on the client session.
|
|
@@ -18182,48 +18245,48 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18182
18245
|
}
|
|
18183
18246
|
isCallSessionEvent(event) {
|
|
18184
18247
|
try {
|
|
18185
|
-
logger$
|
|
18248
|
+
logger$11.debug("[Call] Checking if event is for this call session:", event);
|
|
18186
18249
|
const callId = getValueFrom(event, "params.params.callID") ?? getValueFrom(event, "params.call_id");
|
|
18187
18250
|
const roomSessionId = getValueFrom(event, "params.room_session_id");
|
|
18188
|
-
logger$
|
|
18251
|
+
logger$11.debug(`[Call] Extracted session identifiers callID: ${callId} and roomSessionID: ${roomSessionId} from event:`);
|
|
18189
18252
|
return callId === this.id || !!callId && this.callEventsManager.isCallIdValid(callId) || !!roomSessionId && this.callEventsManager.isRoomSessionIdValid(roomSessionId);
|
|
18190
18253
|
} catch (error) {
|
|
18191
|
-
logger$
|
|
18254
|
+
logger$11.error("[Call] Error checking if event is for this call session:", error);
|
|
18192
18255
|
return false;
|
|
18193
18256
|
}
|
|
18194
18257
|
}
|
|
18195
18258
|
get callSessionEvents$() {
|
|
18196
|
-
return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$
|
|
18197
|
-
logger$
|
|
18198
|
-
}), (0, import_cjs$
|
|
18259
|
+
return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$10.filter)((event) => this.isCallSessionEvent(event)), (0, import_cjs$10.tap)((event) => {
|
|
18260
|
+
logger$11.debug("[Call] Received call session event:", event);
|
|
18261
|
+
}), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
|
|
18199
18262
|
}
|
|
18200
18263
|
/** Observable of call-updated events. */
|
|
18201
18264
|
get callUpdated$() {
|
|
18202
|
-
return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(filterAs(isCallUpdatedMetadata, "params"), (0, import_cjs$
|
|
18265
|
+
return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(filterAs(isCallUpdatedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18203
18266
|
}
|
|
18204
18267
|
/** Observable of member-joined events, emitted when a remote participant joins the call. */
|
|
18205
18268
|
get memberJoined$() {
|
|
18206
|
-
return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(filterAs(isMemberJoinedMetadata, "params"), (0, import_cjs$
|
|
18269
|
+
return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(filterAs(isMemberJoinedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18207
18270
|
}
|
|
18208
18271
|
/** Observable of member-left events, emitted when a participant leaves the call. */
|
|
18209
18272
|
get memberLeft$() {
|
|
18210
|
-
return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(filterAs(isMemberLeftMetadata, "params"), (0, import_cjs$
|
|
18273
|
+
return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(filterAs(isMemberLeftMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18211
18274
|
}
|
|
18212
18275
|
/** Observable of member-updated events (mute, volume, etc.). */
|
|
18213
18276
|
get memberUpdated$() {
|
|
18214
|
-
return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(filterAs(isMemberUpdatedMetadata, "params"), (0, import_cjs$
|
|
18277
|
+
return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(filterAs(isMemberUpdatedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18215
18278
|
}
|
|
18216
18279
|
/** Observable of member-talking events (speech start/stop). */
|
|
18217
18280
|
get memberTalking$() {
|
|
18218
|
-
return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(filterAs(isMemberTalkingMetadata, "params"), (0, import_cjs$
|
|
18281
|
+
return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(filterAs(isMemberTalkingMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18219
18282
|
}
|
|
18220
18283
|
/** Observable of call state-change events. */
|
|
18221
18284
|
get callStates$() {
|
|
18222
|
-
return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(filterAs(isCallStateMetadata, "params"), (0, import_cjs$
|
|
18285
|
+
return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(filterAs(isCallStateMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18223
18286
|
}
|
|
18224
18287
|
/** Observable of layout-changed events. */
|
|
18225
18288
|
get layoutUpdates$() {
|
|
18226
|
-
return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(filterAs(isLayoutChangedMetadata, "params"), (0, import_cjs$
|
|
18289
|
+
return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(filterAs(isLayoutChangedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18227
18290
|
}
|
|
18228
18291
|
/** Underlying `RTCPeerConnection`, for advanced use cases. */
|
|
18229
18292
|
get rtcPeerConnection() {
|
|
@@ -18231,7 +18294,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18231
18294
|
}
|
|
18232
18295
|
/** Observable of raw signaling events as plain objects. */
|
|
18233
18296
|
get signalingEvent$() {
|
|
18234
|
-
return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, import_cjs$
|
|
18297
|
+
return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, import_cjs$10.map)((event) => JSON.parse(JSON.stringify(event)))));
|
|
18235
18298
|
}
|
|
18236
18299
|
/**
|
|
18237
18300
|
* Subscribe to a custom signaling event type on this call.
|
|
@@ -18259,16 +18322,16 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18259
18322
|
subscribe(eventType) {
|
|
18260
18323
|
const cached = this._customSubscriptions.get(eventType);
|
|
18261
18324
|
if (cached) return cached;
|
|
18262
|
-
const filtered$ = this.callSessionEvents$.pipe((0, import_cjs$
|
|
18325
|
+
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$));
|
|
18263
18326
|
this._customSubscriptions.set(eventType, filtered$);
|
|
18264
18327
|
this._sendVertoSubscribe(eventType);
|
|
18265
18328
|
return filtered$;
|
|
18266
18329
|
}
|
|
18267
18330
|
get webrtcMessages$() {
|
|
18268
|
-
return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(filterAs(isWebrtcMessageMetadata, "params"), (0, import_cjs$
|
|
18331
|
+
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)()));
|
|
18269
18332
|
}
|
|
18270
18333
|
get callEvent$() {
|
|
18271
|
-
return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(filterAs(isSignalwireCallMetadata, "params"), (0, import_cjs$
|
|
18334
|
+
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)()));
|
|
18272
18335
|
}
|
|
18273
18336
|
get layoutEvent$() {
|
|
18274
18337
|
return this.cachedObservable("layoutEvent$", () => this.callEvent$.pipe(filterAs(isLayoutChangedMetadata, "params")));
|
|
@@ -18361,7 +18424,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18361
18424
|
*/
|
|
18362
18425
|
async setLayout(layout, positions) {
|
|
18363
18426
|
if (!this.layouts.includes(layout)) throw new InvalidParams(`Layout ${layout} is not available in the current call layouts: ${this.layouts.join(", ")}`);
|
|
18364
|
-
const selfId = await (0, import_cjs$
|
|
18427
|
+
const selfId = await (0, import_cjs$10.firstValueFrom)(this.selfId$.pipe((0, import_cjs$10.filter)((id) => id !== null)));
|
|
18365
18428
|
await this.executeMethod(selfId, "call.layout.set", {
|
|
18366
18429
|
layout,
|
|
18367
18430
|
positions
|
|
@@ -18402,10 +18465,10 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18402
18465
|
message
|
|
18403
18466
|
};
|
|
18404
18467
|
this.clientSession.execute(WebrtcVerto(params)).catch((error) => {
|
|
18405
|
-
logger$
|
|
18468
|
+
logger$11.warn(`[Call] verto.subscribe for '${eventType}' failed (non-fatal):`, error);
|
|
18406
18469
|
});
|
|
18407
18470
|
} catch (error) {
|
|
18408
|
-
logger$
|
|
18471
|
+
logger$11.warn(`[Call] Failed to send verto.subscribe for '${eventType}':`, error);
|
|
18409
18472
|
}
|
|
18410
18473
|
}
|
|
18411
18474
|
};
|
|
@@ -18427,6 +18490,7 @@ function inferCallErrorKind(error) {
|
|
|
18427
18490
|
function isFatalError(error) {
|
|
18428
18491
|
if (error instanceof VertoPongError) return false;
|
|
18429
18492
|
if (error instanceof MediaTrackError) return false;
|
|
18493
|
+
if (error instanceof RPCTimeoutError) return false;
|
|
18430
18494
|
return true;
|
|
18431
18495
|
}
|
|
18432
18496
|
/**
|
|
@@ -18458,6 +18522,9 @@ var CallFactory = class {
|
|
|
18458
18522
|
callId: callInstance.id
|
|
18459
18523
|
};
|
|
18460
18524
|
callInstance.emitError(callError);
|
|
18525
|
+
},
|
|
18526
|
+
onModifyFailed: () => {
|
|
18527
|
+
callInstance.notifyModifyFailed();
|
|
18461
18528
|
}
|
|
18462
18529
|
}),
|
|
18463
18530
|
callEventsManager: new CallEventsManager(callInstance)
|
|
@@ -18471,8 +18538,8 @@ var CallFactory = class {
|
|
|
18471
18538
|
|
|
18472
18539
|
//#endregion
|
|
18473
18540
|
//#region src/behaviors/Collection.ts
|
|
18474
|
-
var import_cjs$
|
|
18475
|
-
const logger$
|
|
18541
|
+
var import_cjs$9 = require_cjs();
|
|
18542
|
+
const logger$10 = getLogger();
|
|
18476
18543
|
var Fetcher = class {
|
|
18477
18544
|
constructor(endpoint, params, http) {
|
|
18478
18545
|
this.endpoint = endpoint;
|
|
@@ -18496,7 +18563,7 @@ var Fetcher = class {
|
|
|
18496
18563
|
this.hasMore = !!this.nextUrl;
|
|
18497
18564
|
return result.data.filter(this.filter).map(this.mapper);
|
|
18498
18565
|
}
|
|
18499
|
-
logger$
|
|
18566
|
+
logger$10.error("Failed to fetch entity");
|
|
18500
18567
|
return [];
|
|
18501
18568
|
}
|
|
18502
18569
|
async id(v) {
|
|
@@ -18537,10 +18604,10 @@ var EntityCollection = class extends Destroyable {
|
|
|
18537
18604
|
this.values$.next(Array.from(this.collectionData.values()));
|
|
18538
18605
|
};
|
|
18539
18606
|
this._hasMore$ = this.createBehaviorSubject(true);
|
|
18540
|
-
this._destroy$ = new import_cjs$
|
|
18607
|
+
this._destroy$ = new import_cjs$9.Subject();
|
|
18541
18608
|
this.updateSubscription = this.update$.subscribe(this.upsertData);
|
|
18542
18609
|
this.loading$.next(false);
|
|
18543
|
-
this.hasMore$ = (0, import_cjs$
|
|
18610
|
+
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$));
|
|
18544
18611
|
}
|
|
18545
18612
|
get loading() {
|
|
18546
18613
|
return this.loading$.value;
|
|
@@ -18549,7 +18616,7 @@ var EntityCollection = class extends Destroyable {
|
|
|
18549
18616
|
return this.fetchController.hasMore ?? true;
|
|
18550
18617
|
}
|
|
18551
18618
|
get updated$() {
|
|
18552
|
-
return this.cachedObservable("updated$", () => this.loading$.pipe((0, import_cjs$
|
|
18619
|
+
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$)));
|
|
18553
18620
|
}
|
|
18554
18621
|
get values() {
|
|
18555
18622
|
return Array.from(this.collectionData.values());
|
|
@@ -18568,7 +18635,7 @@ var EntityCollection = class extends Destroyable {
|
|
|
18568
18635
|
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
18569
18636
|
this.loading$.next(false);
|
|
18570
18637
|
} catch (error) {
|
|
18571
|
-
logger$
|
|
18638
|
+
logger$10.error(`Failed to fetch initial collection data`, error);
|
|
18572
18639
|
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
18573
18640
|
this.loading$.next(false);
|
|
18574
18641
|
this.onError?.(new CollectionFetchError("fetchMore", error));
|
|
@@ -18582,14 +18649,14 @@ var EntityCollection = class extends Destroyable {
|
|
|
18582
18649
|
if (data) this.upsertData(data);
|
|
18583
18650
|
return data;
|
|
18584
18651
|
} catch (error) {
|
|
18585
|
-
logger$
|
|
18652
|
+
logger$10.error(`Failed to fetch data for (${String(key)}:${String(value)}) :`, error);
|
|
18586
18653
|
this.loading$.next(false);
|
|
18587
18654
|
this.onError?.(new CollectionFetchError(`tryFetch(${String(key)})`, error));
|
|
18588
18655
|
}
|
|
18589
18656
|
}
|
|
18590
18657
|
get$(id) {
|
|
18591
18658
|
if (!this.observablesRegistry.has(id)) {
|
|
18592
|
-
this.observablesRegistry.set(id, new import_cjs$
|
|
18659
|
+
this.observablesRegistry.set(id, new import_cjs$9.ReplaySubject(1));
|
|
18593
18660
|
const data = this.collectionData.get(id);
|
|
18594
18661
|
if (data) this.observablesRegistry.get(id)?.next(data);
|
|
18595
18662
|
else this.tryFetch("id", id);
|
|
@@ -18613,9 +18680,9 @@ var EntityCollection = class extends Destroyable {
|
|
|
18613
18680
|
}
|
|
18614
18681
|
};
|
|
18615
18682
|
var EntityCollectionTransformed = class {
|
|
18616
|
-
constructor(originalCollection, filter$
|
|
18683
|
+
constructor(originalCollection, filter$17 = (i) => !!i, mapper = (item) => item) {
|
|
18617
18684
|
this.originalCollection = originalCollection;
|
|
18618
|
-
this.filter = filter$
|
|
18685
|
+
this.filter = filter$17;
|
|
18619
18686
|
this.mapper = mapper;
|
|
18620
18687
|
}
|
|
18621
18688
|
get loading$() {
|
|
@@ -18634,15 +18701,15 @@ var EntityCollectionTransformed = class {
|
|
|
18634
18701
|
return this.originalCollection.values.filter(this.filter).map(this.mapper);
|
|
18635
18702
|
}
|
|
18636
18703
|
get values$() {
|
|
18637
|
-
return this._values$ ??= this.originalCollection.values$.pipe((0, import_cjs$
|
|
18704
|
+
return this._values$ ??= this.originalCollection.values$.pipe((0, import_cjs$9.map)((values) => values.filter(this.filter).map(this.mapper)));
|
|
18638
18705
|
}
|
|
18639
18706
|
get$(id) {
|
|
18640
18707
|
const original$ = this.originalCollection.get$(id);
|
|
18641
|
-
return !original$ ? original$ : original$.pipe((0, import_cjs$
|
|
18708
|
+
return !original$ ? original$ : original$.pipe((0, import_cjs$9.pipe)((0, import_cjs$9.filter)(this.filter), (0, import_cjs$9.map)(this.mapper)));
|
|
18642
18709
|
}
|
|
18643
18710
|
async find$(key, value) {
|
|
18644
18711
|
const original$ = await this.originalCollection.find$(key, value);
|
|
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
|
loadMore() {
|
|
18648
18715
|
this.originalCollection.loadMore();
|
|
@@ -18654,7 +18721,7 @@ var EntityCollectionTransformed = class {
|
|
|
18654
18721
|
|
|
18655
18722
|
//#endregion
|
|
18656
18723
|
//#region src/core/entities/Address.ts
|
|
18657
|
-
var import_cjs$
|
|
18724
|
+
var import_cjs$8 = require_cjs();
|
|
18658
18725
|
/**
|
|
18659
18726
|
* Represents a contact or room in the directory.
|
|
18660
18727
|
*
|
|
@@ -18672,8 +18739,8 @@ var Address = class extends Destroyable {
|
|
|
18672
18739
|
if (this._conversationMessages.hasMore) this._conversationMessages.loadMore();
|
|
18673
18740
|
return this._conversationMessages;
|
|
18674
18741
|
};
|
|
18675
|
-
this.textMessages$ = (0, import_cjs$
|
|
18676
|
-
this.history$ = (0, import_cjs$
|
|
18742
|
+
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$));
|
|
18743
|
+
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$));
|
|
18677
18744
|
this._state$ = this.createBehaviorSubject(null);
|
|
18678
18745
|
}
|
|
18679
18746
|
/** @internal */
|
|
@@ -18708,7 +18775,7 @@ var Address = class extends Destroyable {
|
|
|
18708
18775
|
}
|
|
18709
18776
|
/** Observable of the human-readable display name. */
|
|
18710
18777
|
get displayName$() {
|
|
18711
|
-
return this.cachedObservable("displayName$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18778
|
+
return this.cachedObservable("displayName$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.map)((state) => state.display_name), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18712
18779
|
}
|
|
18713
18780
|
/** Human-readable display name. */
|
|
18714
18781
|
get displayName() {
|
|
@@ -18717,7 +18784,7 @@ var Address = class extends Destroyable {
|
|
|
18717
18784
|
}
|
|
18718
18785
|
/** Observable of the preview image URL. */
|
|
18719
18786
|
get previewUrl$() {
|
|
18720
|
-
return this.cachedObservable("previewUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18787
|
+
return this.cachedObservable("previewUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.map)((state) => state.preview_url), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18721
18788
|
}
|
|
18722
18789
|
/** Preview image URL. */
|
|
18723
18790
|
get previewUrl() {
|
|
@@ -18726,7 +18793,7 @@ var Address = class extends Destroyable {
|
|
|
18726
18793
|
}
|
|
18727
18794
|
/** Observable of the cover image URL. */
|
|
18728
18795
|
get coverUrl$() {
|
|
18729
|
-
return this.cachedObservable("coverUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18796
|
+
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$)));
|
|
18730
18797
|
}
|
|
18731
18798
|
/** Cover image URL. */
|
|
18732
18799
|
get coverUrl() {
|
|
@@ -18735,7 +18802,7 @@ var Address = class extends Destroyable {
|
|
|
18735
18802
|
}
|
|
18736
18803
|
/** Observable of the underlying resource ID. */
|
|
18737
18804
|
get resourceId$() {
|
|
18738
|
-
return this.cachedObservable("resourceId$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18805
|
+
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$)));
|
|
18739
18806
|
}
|
|
18740
18807
|
/** Underlying resource ID. */
|
|
18741
18808
|
get resourceId() {
|
|
@@ -18744,7 +18811,7 @@ var Address = class extends Destroyable {
|
|
|
18744
18811
|
}
|
|
18745
18812
|
/** Observable of the resource type (e.g. `'room'`, `'subscriber'`). */
|
|
18746
18813
|
get type$() {
|
|
18747
|
-
return this.cachedObservable("type$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18814
|
+
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$)));
|
|
18748
18815
|
}
|
|
18749
18816
|
/** Resource type (e.g. `'room'`, `'subscriber'`). */
|
|
18750
18817
|
get type() {
|
|
@@ -18753,7 +18820,7 @@ var Address = class extends Destroyable {
|
|
|
18753
18820
|
}
|
|
18754
18821
|
/** Observable of available communication channels (audio, video, messaging). */
|
|
18755
18822
|
get channels$() {
|
|
18756
|
-
return this.cachedObservable("channels$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18823
|
+
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$)));
|
|
18757
18824
|
}
|
|
18758
18825
|
/** Available communication channels. */
|
|
18759
18826
|
get channels() {
|
|
@@ -18767,7 +18834,7 @@ var Address = class extends Destroyable {
|
|
|
18767
18834
|
}
|
|
18768
18835
|
/** Observable indicating whether the address (room) is locked. */
|
|
18769
18836
|
get locked$() {
|
|
18770
|
-
return this.cachedObservable("locked$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18837
|
+
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$)));
|
|
18771
18838
|
}
|
|
18772
18839
|
/**
|
|
18773
18840
|
* Sends a text message to this address.
|
|
@@ -18833,14 +18900,14 @@ var Address = class extends Destroyable {
|
|
|
18833
18900
|
|
|
18834
18901
|
//#endregion
|
|
18835
18902
|
//#region src/core/utils.ts
|
|
18836
|
-
var import_cjs$
|
|
18837
|
-
const logger$
|
|
18903
|
+
var import_cjs$7 = require_cjs();
|
|
18904
|
+
const logger$9 = getLogger();
|
|
18838
18905
|
const isRPCConnectResult = (e) => {
|
|
18839
|
-
logger$
|
|
18906
|
+
logger$9.debug("isRPCConnectResult check:", e);
|
|
18840
18907
|
if (!e || typeof e !== "object") return false;
|
|
18841
18908
|
const result = e;
|
|
18842
18909
|
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";
|
|
18843
|
-
logger$
|
|
18910
|
+
logger$9.debug("isRPCConnectResult check result:", is);
|
|
18844
18911
|
return is;
|
|
18845
18912
|
};
|
|
18846
18913
|
var PendingRPC = class PendingRPC {
|
|
@@ -18849,7 +18916,7 @@ var PendingRPC = class PendingRPC {
|
|
|
18849
18916
|
}
|
|
18850
18917
|
constructor(request, responses$, options) {
|
|
18851
18918
|
this.id = v4_default();
|
|
18852
|
-
logger$
|
|
18919
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}: method:${request.method}] Creating PendingRPC`);
|
|
18853
18920
|
this.request = request;
|
|
18854
18921
|
const timeoutMs = options?.timeoutMs ?? PendingRPC.defaultTimeoutMs;
|
|
18855
18922
|
const signal = options?.signal;
|
|
@@ -18859,38 +18926,38 @@ var PendingRPC = class PendingRPC {
|
|
|
18859
18926
|
return;
|
|
18860
18927
|
}
|
|
18861
18928
|
let isSettled = false;
|
|
18862
|
-
const subscription = (0, import_cjs$
|
|
18863
|
-
const timer$
|
|
18929
|
+
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) => {
|
|
18930
|
+
const timer$3 = setTimeout(() => {
|
|
18864
18931
|
subscriber.error(new RPCTimeoutError(request.id, timeoutMs));
|
|
18865
18932
|
}, timeoutMs);
|
|
18866
|
-
return () => clearTimeout(timer$
|
|
18867
|
-
}), signal ? new import_cjs$
|
|
18933
|
+
return () => clearTimeout(timer$3);
|
|
18934
|
+
}), signal ? new import_cjs$7.Observable((subscriber) => {
|
|
18868
18935
|
const abortHandler = () => {
|
|
18869
18936
|
subscriber.error(new DOMException("The operation was aborted", "AbortError"));
|
|
18870
18937
|
};
|
|
18871
18938
|
signal.addEventListener("abort", abortHandler);
|
|
18872
18939
|
return () => signal.removeEventListener("abort", abortHandler);
|
|
18873
|
-
}) : import_cjs$
|
|
18940
|
+
}) : import_cjs$7.NEVER).subscribe({
|
|
18874
18941
|
next: (response) => {
|
|
18875
18942
|
isSettled = true;
|
|
18876
18943
|
if (response.error) {
|
|
18877
18944
|
const rpcError = new JSONRPCError(response.error.code, response.error.message, response.error.data, void 0, request.id);
|
|
18878
|
-
logger$
|
|
18945
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
|
|
18879
18946
|
reject(rpcError);
|
|
18880
18947
|
} else {
|
|
18881
|
-
logger$
|
|
18948
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
18882
18949
|
resolve(response);
|
|
18883
18950
|
}
|
|
18884
18951
|
subscription.unsubscribe();
|
|
18885
18952
|
},
|
|
18886
18953
|
error: (error) => {
|
|
18887
|
-
logger$
|
|
18954
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with error:`, error);
|
|
18888
18955
|
isSettled = true;
|
|
18889
18956
|
reject(error);
|
|
18890
18957
|
subscription.unsubscribe();
|
|
18891
18958
|
},
|
|
18892
18959
|
complete: () => {
|
|
18893
|
-
logger$
|
|
18960
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
|
|
18894
18961
|
if (!isSettled) reject(new RPCTimeoutError(request.id, timeoutMs));
|
|
18895
18962
|
subscription.unsubscribe();
|
|
18896
18963
|
}
|
|
@@ -18910,8 +18977,8 @@ var PendingRPC = class PendingRPC {
|
|
|
18910
18977
|
|
|
18911
18978
|
//#endregion
|
|
18912
18979
|
//#region src/managers/ClientSessionManager.ts
|
|
18913
|
-
var import_cjs$
|
|
18914
|
-
const logger$
|
|
18980
|
+
var import_cjs$6 = require_cjs();
|
|
18981
|
+
const logger$8 = getLogger();
|
|
18915
18982
|
const getAddressSearchURI = (options) => {
|
|
18916
18983
|
const to = options.to?.split("?")[0];
|
|
18917
18984
|
const from$9 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
|
|
@@ -18946,10 +19013,10 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
18946
19013
|
this._iceServers$ = this.createBehaviorSubject([]);
|
|
18947
19014
|
attachManager.setSession(this);
|
|
18948
19015
|
this.callFactory = new CallFactory(this, deviceController, attachManager, webRTCApiProvider, networkChange$);
|
|
18949
|
-
this.initialized$ = (0, import_cjs$
|
|
19016
|
+
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$));
|
|
18950
19017
|
}
|
|
18951
19018
|
get incomingCalls$() {
|
|
18952
|
-
return this.cachedObservable("incomingCalls$", () => this.calls$.pipe((0, import_cjs$
|
|
19019
|
+
return this.cachedObservable("incomingCalls$", () => this.calls$.pipe((0, import_cjs$6.map)((calls) => calls.filter((call) => call.direction === "inbound"))));
|
|
18953
19020
|
}
|
|
18954
19021
|
get incomingCalls() {
|
|
18955
19022
|
return Object.values(this._calls$.value).filter((call) => call.direction === "inbound");
|
|
@@ -18961,7 +19028,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
18961
19028
|
return this._subscriberInfo$.value;
|
|
18962
19029
|
}
|
|
18963
19030
|
get calls$() {
|
|
18964
|
-
return this.cachedObservable("calls$", () => this._calls$.pipe((0, import_cjs$
|
|
19031
|
+
return this.cachedObservable("calls$", () => this._calls$.pipe((0, import_cjs$6.map)((calls) => Object.values(calls))));
|
|
18965
19032
|
}
|
|
18966
19033
|
get calls() {
|
|
18967
19034
|
return Object.values(this._calls$.value);
|
|
@@ -19005,7 +19072,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19005
19072
|
try {
|
|
19006
19073
|
return await this.transport.execute(request, options);
|
|
19007
19074
|
} catch (error) {
|
|
19008
|
-
logger$
|
|
19075
|
+
logger$8.debug("[Session] Execute Error", error);
|
|
19009
19076
|
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
19010
19077
|
throw error;
|
|
19011
19078
|
}
|
|
@@ -19019,40 +19086,40 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19019
19086
|
return true;
|
|
19020
19087
|
}
|
|
19021
19088
|
setupMessageHandlers() {
|
|
19022
|
-
logger$
|
|
19089
|
+
logger$8.debug("[Session] Setting up message handlers");
|
|
19023
19090
|
this.subscribeTo(this.authStateEvent$, async (authStateEvent) => {
|
|
19024
|
-
logger$
|
|
19091
|
+
logger$8.debug("[Session] Authorization state event received:", authStateEvent);
|
|
19025
19092
|
try {
|
|
19026
19093
|
await this.updateAuthorizationStateInStorage(authStateEvent.authorization_state);
|
|
19027
19094
|
} catch (error) {
|
|
19028
|
-
logger$
|
|
19095
|
+
logger$8.error("[Session] Failed to handle authorization state update:", error);
|
|
19029
19096
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19030
19097
|
}
|
|
19031
19098
|
});
|
|
19032
|
-
this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$
|
|
19033
|
-
logger$
|
|
19034
|
-
return (0, import_cjs$
|
|
19099
|
+
this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$6.filter)((status) => status === "connected"), (0, import_cjs$6.exhaustMap)(() => {
|
|
19100
|
+
logger$8.debug("[Session] Connection established, initiating authentication");
|
|
19101
|
+
return (0, import_cjs$6.from)(this.authenticate()).pipe((0, import_cjs$6.catchError)((error) => {
|
|
19035
19102
|
this.handleAuthenticationError(error).catch((err) => {
|
|
19036
|
-
logger$
|
|
19103
|
+
logger$8.error("[Session] Error handling authentication failure:", err);
|
|
19037
19104
|
});
|
|
19038
|
-
return import_cjs$
|
|
19105
|
+
return import_cjs$6.EMPTY;
|
|
19039
19106
|
}));
|
|
19040
19107
|
})), void 0);
|
|
19041
19108
|
this.subscribeTo(this.vertoInvite$, async (invite) => {
|
|
19042
|
-
logger$
|
|
19109
|
+
logger$8.debug("[Session] Verto invite received:", invite);
|
|
19043
19110
|
try {
|
|
19044
19111
|
await this.createInboundCall(invite);
|
|
19045
19112
|
} catch (error) {
|
|
19046
|
-
logger$
|
|
19113
|
+
logger$8.error("[Session] Error handling Verto invite:", error);
|
|
19047
19114
|
this._errors$.next(new VertoInviteHandlerError(error));
|
|
19048
19115
|
}
|
|
19049
19116
|
});
|
|
19050
19117
|
this.subscribeTo(this.vertoAttach$, async (attach) => {
|
|
19051
|
-
logger$
|
|
19118
|
+
logger$8.debug("[Session] Verto attach received:", attach);
|
|
19052
19119
|
try {
|
|
19053
19120
|
await this.handleVertoAttach(attach);
|
|
19054
19121
|
} catch (error) {
|
|
19055
|
-
logger$
|
|
19122
|
+
logger$8.error("[Session] Error handling Verto attach:", error);
|
|
19056
19123
|
this._errors$.next(new VertoAttachHandlerError(error));
|
|
19057
19124
|
}
|
|
19058
19125
|
});
|
|
@@ -19062,49 +19129,49 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19062
19129
|
const storedState = await this.storage.getItem(this.authorizationStateKey);
|
|
19063
19130
|
this.authorizationState$.next(storedState ?? void 0);
|
|
19064
19131
|
} catch (error) {
|
|
19065
|
-
logger$
|
|
19132
|
+
logger$8.error("Failed to retrieve authorization state from storage:", error);
|
|
19066
19133
|
this.authorizationState$.next(void 0);
|
|
19067
19134
|
}
|
|
19068
19135
|
}
|
|
19069
19136
|
async updateAuthorizationStateInStorage(authorizationState) {
|
|
19070
19137
|
if (!authorizationState) {
|
|
19071
|
-
logger$
|
|
19138
|
+
logger$8.debug("[Session] Removing authorization state from storage");
|
|
19072
19139
|
try {
|
|
19073
19140
|
await this.storage.removeItem(this.authorizationStateKey);
|
|
19074
19141
|
this.authorizationState$.next(void 0);
|
|
19075
19142
|
} catch (error) {
|
|
19076
|
-
logger$
|
|
19143
|
+
logger$8.error("Failed to remove authorization state from storage:", error);
|
|
19077
19144
|
throw error;
|
|
19078
19145
|
}
|
|
19079
19146
|
return;
|
|
19080
19147
|
}
|
|
19081
19148
|
try {
|
|
19082
|
-
logger$
|
|
19149
|
+
logger$8.debug("[Session] Updating authorization state in storage");
|
|
19083
19150
|
await this.storage.setItem(this.authorizationStateKey, authorizationState);
|
|
19084
19151
|
this.authorizationState$.next(authorizationState);
|
|
19085
19152
|
} catch (error) {
|
|
19086
|
-
logger$
|
|
19153
|
+
logger$8.error("Failed to retrieve authorization state from storage:", error);
|
|
19087
19154
|
throw error;
|
|
19088
19155
|
}
|
|
19089
19156
|
}
|
|
19090
19157
|
get authStateEvent$() {
|
|
19091
|
-
return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$
|
|
19092
|
-
logger$
|
|
19093
|
-
}), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$
|
|
19094
|
-
logger$
|
|
19158
|
+
return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$6.tap)((msg) => {
|
|
19159
|
+
logger$8.debug("[Session] Received incoming message:", msg);
|
|
19160
|
+
}), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$6.tap)((event) => {
|
|
19161
|
+
logger$8.debug("[Session] Authorization state event received:", event.authorization_state);
|
|
19095
19162
|
})));
|
|
19096
19163
|
}
|
|
19097
19164
|
get signalingEvent$() {
|
|
19098
|
-
return this.cachedObservable("signalingEvent$", () => this.transport.incomingEvent$.pipe(filterAs(isSignalwireRequest, "params"), (0, import_cjs$
|
|
19165
|
+
return this.cachedObservable("signalingEvent$", () => this.transport.incomingEvent$.pipe(filterAs(isSignalwireRequest, "params"), (0, import_cjs$6.share)()));
|
|
19099
19166
|
}
|
|
19100
19167
|
get vertoInvite$() {
|
|
19101
|
-
return this.cachedObservable("vertoInvite$", () => this.signalingEvent$.pipe((0, import_cjs$
|
|
19168
|
+
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) => ({
|
|
19102
19169
|
node_id: event.node_id,
|
|
19103
19170
|
...event.params.params
|
|
19104
19171
|
}))));
|
|
19105
19172
|
}
|
|
19106
19173
|
get vertoAttach$() {
|
|
19107
|
-
return this.cachedObservable("vertoAttach$", () => this.signalingEvent$.pipe((0, import_cjs$
|
|
19174
|
+
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) => ({
|
|
19108
19175
|
node_id: event.node_id,
|
|
19109
19176
|
...event.params.params
|
|
19110
19177
|
}))));
|
|
@@ -19124,20 +19191,20 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19124
19191
|
return { jwt_token: credential.token };
|
|
19125
19192
|
}
|
|
19126
19193
|
async connect() {
|
|
19127
|
-
await (0, import_cjs$
|
|
19194
|
+
await (0, import_cjs$6.firstValueFrom)(this.initialized$);
|
|
19128
19195
|
await this.transport.connect();
|
|
19129
|
-
await (0, import_cjs$
|
|
19196
|
+
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 })));
|
|
19130
19197
|
}
|
|
19131
19198
|
async handleAuthenticationError(error) {
|
|
19132
|
-
logger$
|
|
19199
|
+
logger$8.error("Authentication error:", error);
|
|
19133
19200
|
const isRecoverableAuthError = error instanceof JSONRPCError && (error.code === RPC_ERROR_REQUESTER_VALIDATION_FAILED || error.code === RPC_ERROR_INVALID_PARAMS || error.code === RPC_ERROR_AUTHENTICATION_FAILED);
|
|
19134
|
-
const hasStoredState = await (0, import_cjs$
|
|
19201
|
+
const hasStoredState = await (0, import_cjs$6.firstValueFrom)(this.authorizationState$.pipe((0, import_cjs$6.take)(1))) !== void 0;
|
|
19135
19202
|
if (isRecoverableAuthError && hasStoredState) {
|
|
19136
|
-
logger$
|
|
19203
|
+
logger$8.debug("[Session] Recoverable auth error — cleaning up stored state and reconnecting fresh");
|
|
19137
19204
|
try {
|
|
19138
19205
|
await this.cleanupStoredConnectionParams();
|
|
19139
19206
|
} catch (cleanupError) {
|
|
19140
|
-
logger$
|
|
19207
|
+
logger$8.error("Failed to cleanup stored connection params:", cleanupError);
|
|
19141
19208
|
} finally {
|
|
19142
19209
|
this.transport.reconnect();
|
|
19143
19210
|
}
|
|
@@ -19152,44 +19219,44 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19152
19219
|
try {
|
|
19153
19220
|
await this.storage.setItem(this.authorizationStateKey, authorization_state);
|
|
19154
19221
|
} catch (error) {
|
|
19155
|
-
logger$
|
|
19222
|
+
logger$8.error("Failed to update authorization state in storage:", error);
|
|
19156
19223
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19157
19224
|
}
|
|
19158
19225
|
}
|
|
19159
19226
|
async reauthenticate(token, dpopToken, options) {
|
|
19160
|
-
logger$
|
|
19227
|
+
logger$8.debug("[Session] Re-authenticating session");
|
|
19161
19228
|
try {
|
|
19162
19229
|
let resolvedDpopToken = dpopToken;
|
|
19163
19230
|
if (!resolvedDpopToken && this.dpopManager?.initialized) try {
|
|
19164
19231
|
resolvedDpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19165
19232
|
} catch (error) {
|
|
19166
19233
|
if (this._clientBound) throw error;
|
|
19167
|
-
logger$
|
|
19234
|
+
logger$8.warn("[Session] Failed to create DPoP proof for reauthenticate:", error);
|
|
19168
19235
|
}
|
|
19169
19236
|
const request = RPCReauthenticate({
|
|
19170
19237
|
project: this._authorization$.value?.project_id ?? "",
|
|
19171
19238
|
jwt_token: token,
|
|
19172
19239
|
...resolvedDpopToken ? { dpop_token: resolvedDpopToken } : {}
|
|
19173
19240
|
});
|
|
19174
|
-
await (0, import_cjs$
|
|
19175
|
-
logger$
|
|
19241
|
+
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) => {
|
|
19242
|
+
logger$8.error("[Session] Re-authentication RPC failed:", err);
|
|
19176
19243
|
throw err;
|
|
19177
19244
|
})));
|
|
19178
19245
|
if (options?.clientBound) this._clientBound = true;
|
|
19179
|
-
logger$
|
|
19246
|
+
logger$8.debug("[Session] Re-authentication successful, updating stored auth state");
|
|
19180
19247
|
} catch (error) {
|
|
19181
|
-
logger$
|
|
19248
|
+
logger$8.error("[Session] Re-authentication failed:", error);
|
|
19182
19249
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19183
19250
|
throw error;
|
|
19184
19251
|
}
|
|
19185
19252
|
}
|
|
19186
19253
|
async authenticate() {
|
|
19187
|
-
logger$
|
|
19188
|
-
const persistedParams = await (0, import_cjs$
|
|
19254
|
+
logger$8.debug("[Session] Starting authentication process");
|
|
19255
|
+
const persistedParams = await (0, import_cjs$6.firstValueFrom)((0, import_cjs$6.combineLatest)({
|
|
19189
19256
|
protocol: this.transport.protocol$,
|
|
19190
19257
|
authorization_state: this.authorizationState$
|
|
19191
|
-
}).pipe((0, import_cjs$
|
|
19192
|
-
logger$
|
|
19258
|
+
}).pipe((0, import_cjs$6.take)(1)));
|
|
19259
|
+
logger$8.debug("[Session] Persisted params:\n", {
|
|
19193
19260
|
protocol: persistedParams.protocol,
|
|
19194
19261
|
authStateLength: persistedParams.authorization_state?.length
|
|
19195
19262
|
});
|
|
@@ -19197,16 +19264,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19197
19264
|
const storedToken = this.getCredential().token;
|
|
19198
19265
|
const isReconnect = hasReconnectState && storedToken;
|
|
19199
19266
|
let dpopToken;
|
|
19200
|
-
if (isReconnect) logger$
|
|
19267
|
+
if (isReconnect) logger$8.debug("[Session] Reconnecting with stored jwt_token + authorization_state");
|
|
19201
19268
|
else if (this.onBeforeReconnect && this._clientBound) {
|
|
19202
|
-
logger$
|
|
19269
|
+
logger$8.debug("[Session] Refreshing credentials before fresh connect");
|
|
19203
19270
|
await this.onBeforeReconnect();
|
|
19204
19271
|
}
|
|
19205
19272
|
if ((!isReconnect || this._clientBound) && this.dpopManager?.initialized) try {
|
|
19206
19273
|
dpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.connect" });
|
|
19207
19274
|
} catch (error) {
|
|
19208
19275
|
if (this._clientBound) throw error;
|
|
19209
|
-
logger$
|
|
19276
|
+
logger$8.warn("[Session] Failed to create DPoP proof for connect, proceeding without:", error);
|
|
19210
19277
|
}
|
|
19211
19278
|
const rpcConnectRequest = RPCConnect({
|
|
19212
19279
|
authentication: isReconnect ? { jwt_token: storedToken } : this.authentication,
|
|
@@ -19222,13 +19289,13 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19222
19289
|
protocol: persistedParams.protocol
|
|
19223
19290
|
} : {}
|
|
19224
19291
|
});
|
|
19225
|
-
const response = await (0, import_cjs$
|
|
19226
|
-
logger$
|
|
19227
|
-
}), (0, import_cjs$
|
|
19228
|
-
logger$
|
|
19292
|
+
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)(() => {
|
|
19293
|
+
logger$8.debug("[Session] Response passed filter, processing authentication result");
|
|
19294
|
+
}), (0, import_cjs$6.take)(1), (0, import_cjs$6.catchError)((err) => {
|
|
19295
|
+
logger$8.error("[Session] Authentication RPC failed:", err);
|
|
19229
19296
|
throw err;
|
|
19230
19297
|
})));
|
|
19231
|
-
logger$
|
|
19298
|
+
logger$8.debug("[Session] Processing authentication result:", {
|
|
19232
19299
|
hasProtocol: !!response.protocol,
|
|
19233
19300
|
hasAuthorization: !!response.authorization,
|
|
19234
19301
|
hasIceServers: !!response.ice_servers
|
|
@@ -19237,7 +19304,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19237
19304
|
this._authorization$.next(response.authorization);
|
|
19238
19305
|
this._iceServers$.next(response.ice_servers ?? []);
|
|
19239
19306
|
this._authenticated$.next(true);
|
|
19240
|
-
logger$
|
|
19307
|
+
logger$8.debug("[Session] Authentication completed successfully");
|
|
19241
19308
|
}
|
|
19242
19309
|
async disconnect() {
|
|
19243
19310
|
this.transport.disconnect();
|
|
@@ -19256,7 +19323,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19256
19323
|
displayDirection: invite.display_direction,
|
|
19257
19324
|
userVariables: invite.userVariables
|
|
19258
19325
|
});
|
|
19259
|
-
await (0, import_cjs$
|
|
19326
|
+
await (0, import_cjs$6.firstValueFrom)(callSession.status$);
|
|
19260
19327
|
this._calls$.next({
|
|
19261
19328
|
[`${callSession.id}`]: callSession,
|
|
19262
19329
|
...this._calls$.value
|
|
@@ -19274,11 +19341,11 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19274
19341
|
async handleVertoAttach(attach) {
|
|
19275
19342
|
const { callID } = attach;
|
|
19276
19343
|
if (callID in this._calls$.value) {
|
|
19277
|
-
logger$
|
|
19344
|
+
logger$8.debug(`[Session] Verto attach for existing call ${callID}, deferring to per-call handler`);
|
|
19278
19345
|
return;
|
|
19279
19346
|
}
|
|
19280
19347
|
const storedOptions = this.attachManager.consumePendingAttachment(callID);
|
|
19281
|
-
logger$
|
|
19348
|
+
logger$8.debug(`[Session] Creating reattached call for callID: ${callID}`);
|
|
19282
19349
|
const callSession = await this.createCall({
|
|
19283
19350
|
nodeId: attach.node_id,
|
|
19284
19351
|
callId: callID,
|
|
@@ -19289,7 +19356,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19289
19356
|
reattach: true,
|
|
19290
19357
|
...storedOptions
|
|
19291
19358
|
});
|
|
19292
|
-
await (0, import_cjs$
|
|
19359
|
+
await (0, import_cjs$6.firstValueFrom)(callSession.status$);
|
|
19293
19360
|
this._calls$.next({
|
|
19294
19361
|
[`${callSession.id}`]: callSession,
|
|
19295
19362
|
...this._calls$.value
|
|
@@ -19303,16 +19370,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19303
19370
|
to: destinationURI,
|
|
19304
19371
|
...options
|
|
19305
19372
|
});
|
|
19306
|
-
await (0, import_cjs$
|
|
19373
|
+
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)))));
|
|
19307
19374
|
this._calls$.next({
|
|
19308
19375
|
[`${callSession.id}`]: callSession,
|
|
19309
19376
|
...this._calls$.value
|
|
19310
19377
|
});
|
|
19311
19378
|
return callSession;
|
|
19312
19379
|
} catch (error) {
|
|
19313
|
-
logger$
|
|
19380
|
+
logger$8.error("[Session] Error creating outbound call:", error);
|
|
19314
19381
|
callSession?.destroy();
|
|
19315
|
-
const callError = new CallCreateError(error instanceof import_cjs$
|
|
19382
|
+
const callError = new CallCreateError(error instanceof import_cjs$6.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
|
|
19316
19383
|
this._errors$.next(callError);
|
|
19317
19384
|
throw callError;
|
|
19318
19385
|
}
|
|
@@ -19328,16 +19395,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19328
19395
|
address = this._directory.get(addressId);
|
|
19329
19396
|
if (!address) throw new DependencyError(`Address ID: ${addressId} not found`);
|
|
19330
19397
|
} catch {
|
|
19331
|
-
logger$
|
|
19398
|
+
logger$8.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
|
|
19332
19399
|
}
|
|
19333
19400
|
const callSession = this.callFactory.createCall(address, { ...options });
|
|
19334
|
-
this.subscribeTo(callSession.status$.pipe((0, import_cjs$
|
|
19401
|
+
this.subscribeTo(callSession.status$.pipe((0, import_cjs$6.filter)((status) => status === "destroyed"), (0, import_cjs$6.take)(1)), () => {
|
|
19335
19402
|
const { [`${callSession.id}`]: _, ...remainingCalls } = this._calls$.value;
|
|
19336
19403
|
this._calls$.next(remainingCalls);
|
|
19337
19404
|
});
|
|
19338
19405
|
return callSession;
|
|
19339
19406
|
} catch (error) {
|
|
19340
|
-
logger$
|
|
19407
|
+
logger$8.error("[Session] Error creating call session:", error);
|
|
19341
19408
|
throw new CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
|
|
19342
19409
|
}
|
|
19343
19410
|
}
|
|
@@ -19385,8 +19452,8 @@ const isString = (obj) => typeof obj === "string";
|
|
|
19385
19452
|
|
|
19386
19453
|
//#endregion
|
|
19387
19454
|
//#region src/managers/ConversationsManager.ts
|
|
19388
|
-
var import_cjs$
|
|
19389
|
-
const logger$
|
|
19455
|
+
var import_cjs$5 = require_cjs();
|
|
19456
|
+
const logger$7 = getLogger();
|
|
19390
19457
|
var ConversationMessagesFetcher = class extends Fetcher {
|
|
19391
19458
|
constructor(groupId, http) {
|
|
19392
19459
|
super(`/api/fabric/conversations/${groupId}/messages`, "page_size=100", http);
|
|
@@ -19426,13 +19493,13 @@ var ConversationsManager = class {
|
|
|
19426
19493
|
}
|
|
19427
19494
|
throw new ConversationError("Join Failed - Unexpected response");
|
|
19428
19495
|
} catch (error) {
|
|
19429
|
-
logger$
|
|
19496
|
+
logger$7.error("[ConversationsManager] Failed to join conversation:", error);
|
|
19430
19497
|
throw error;
|
|
19431
19498
|
}
|
|
19432
19499
|
}
|
|
19433
19500
|
async getConversationMessageCollection(addressId) {
|
|
19434
19501
|
const groupId = this.groupIds.get(addressId) ?? await this.join(addressId);
|
|
19435
|
-
return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(filterAs(isConversationMessageMetadata, "params"), (0, import_cjs$
|
|
19502
|
+
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));
|
|
19436
19503
|
}
|
|
19437
19504
|
async sendText(text, destinationAddressId) {
|
|
19438
19505
|
const groupId = this.groupIds.get(destinationAddressId) ?? await this.join(destinationAddressId);
|
|
@@ -19449,12 +19516,222 @@ var ConversationsManager = class {
|
|
|
19449
19516
|
})).ok) return;
|
|
19450
19517
|
throw new ConversationError("Send Text Failed - Unexpected response");
|
|
19451
19518
|
} catch (error) {
|
|
19452
|
-
logger$
|
|
19519
|
+
logger$7.error("[ConversationsManager] Failed to send text message:", error);
|
|
19453
19520
|
throw error;
|
|
19454
19521
|
}
|
|
19455
19522
|
}
|
|
19456
19523
|
};
|
|
19457
19524
|
|
|
19525
|
+
//#endregion
|
|
19526
|
+
//#region src/managers/DeviceTokenManager.ts
|
|
19527
|
+
var import_cjs$4 = require_cjs();
|
|
19528
|
+
const logger$6 = getLogger();
|
|
19529
|
+
/**
|
|
19530
|
+
* Resolves the token expiry timestamp (epoch seconds) using a 3-tier priority chain:
|
|
19531
|
+
* 1. `data.expires_at` — server-provided absolute timestamp
|
|
19532
|
+
* 2. `data.expires_in` — server-provided relative lifetime
|
|
19533
|
+
* 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN` with a warning
|
|
19534
|
+
*/
|
|
19535
|
+
function resolveExpiresAt(data) {
|
|
19536
|
+
if (data.expires_at) return data.expires_at;
|
|
19537
|
+
if (data.expires_in) return Math.floor(Date.now() / 1e3) + data.expires_in;
|
|
19538
|
+
logger$6.warn("[DeviceToken] Could not determine token expiry, using default");
|
|
19539
|
+
return Math.floor(Date.now() / 1e3) + DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
19540
|
+
}
|
|
19541
|
+
/**
|
|
19542
|
+
* Resolves the token TTL in seconds from a fresh response.
|
|
19543
|
+
* Called at token receive time so `expires_at - now` reflects the original lifetime.
|
|
19544
|
+
*
|
|
19545
|
+
* 1. `data.expires_in` — server-provided TTL directly
|
|
19546
|
+
* 2. `data.expires_at - now` — derive TTL from absolute timestamp
|
|
19547
|
+
* 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN`
|
|
19548
|
+
*/
|
|
19549
|
+
function resolveExpireIn(data) {
|
|
19550
|
+
if (data.expires_in) return data.expires_in;
|
|
19551
|
+
if (data.expires_at) return Math.max(data.expires_at - Math.floor(Date.now() / 1e3), 1);
|
|
19552
|
+
return DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
19553
|
+
}
|
|
19554
|
+
/**
|
|
19555
|
+
* Manages the Client Bound SAT lifecycle: activation, token exchange,
|
|
19556
|
+
* reauthentication, and automatic refresh scheduling.
|
|
19557
|
+
*
|
|
19558
|
+
* Extends {@link Destroyable} for automatic RxJS subscription and subject cleanup.
|
|
19559
|
+
* Uses a reactive pipeline (`BehaviorSubject` + `switchMap(timer())`) instead of
|
|
19560
|
+
* raw `setTimeout` for refresh scheduling.
|
|
19561
|
+
*/
|
|
19562
|
+
var DeviceTokenManager = class extends Destroyable {
|
|
19563
|
+
constructor(dpopManager, http, errorHandler, getCredential) {
|
|
19564
|
+
super();
|
|
19565
|
+
this.dpopManager = dpopManager;
|
|
19566
|
+
this.http = http;
|
|
19567
|
+
this.errorHandler = errorHandler;
|
|
19568
|
+
this.getCredential = getCredential;
|
|
19569
|
+
this._currentToken$ = this.createBehaviorSubject(null);
|
|
19570
|
+
this._refreshInProgress = false;
|
|
19571
|
+
this._effectiveExpireIn = DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
19572
|
+
this.subscribeTo(this._currentToken$.pipe((0, import_cjs$4.filter)(Boolean), (0, import_cjs$4.switchMap)((tokenData) => {
|
|
19573
|
+
const expiresAt = resolveExpiresAt(tokenData);
|
|
19574
|
+
const refreshIn = Math.max(expiresAt * 1e3 - Date.now() - DEVICE_TOKEN_REFRESH_BUFFER_MS, 1e3);
|
|
19575
|
+
logger$6.debug(`[DeviceToken] Scheduling Client Bound SAT refresh in ${refreshIn}ms`);
|
|
19576
|
+
return (0, import_cjs$4.timer)(refreshIn);
|
|
19577
|
+
})), () => {
|
|
19578
|
+
this.executeRefresh();
|
|
19579
|
+
});
|
|
19580
|
+
}
|
|
19581
|
+
/** Current token TTL in milliseconds. Used to extend cached credential expiry on refresh. */
|
|
19582
|
+
get effectiveExpireIn() {
|
|
19583
|
+
return this._effectiveExpireIn;
|
|
19584
|
+
}
|
|
19585
|
+
/**
|
|
19586
|
+
* Activates the Client Bound SAT flow when the subscriber's token has
|
|
19587
|
+
* `sat:refresh` scope.
|
|
19588
|
+
*
|
|
19589
|
+
* Steps:
|
|
19590
|
+
* 1. Check subscriber's `sat_claims` for `sat:refresh` scope
|
|
19591
|
+
* 2. Call `/api/fabric/subscriber/devices/token` with a DPoP proof
|
|
19592
|
+
* 3. Reauthenticate the session with the Client Bound SAT + DPoP proof
|
|
19593
|
+
* 4. Emit token to trigger the reactive refresh pipeline
|
|
19594
|
+
*/
|
|
19595
|
+
async activate(subscriber, session, updateCredential) {
|
|
19596
|
+
const { satClaims } = subscriber;
|
|
19597
|
+
if (!satClaims?.scope?.includes(SAT_REFRESH_SCOPE)) {
|
|
19598
|
+
logger$6.debug("[DeviceToken] No sat:refresh scope, skipping Client Bound SAT activation");
|
|
19599
|
+
return;
|
|
19600
|
+
}
|
|
19601
|
+
this._session = session;
|
|
19602
|
+
this._updateCredential = updateCredential;
|
|
19603
|
+
try {
|
|
19604
|
+
const tokenData = await this.obtainToken();
|
|
19605
|
+
if (!tokenData.expires_at && !tokenData.expires_in && satClaims.expires_at) tokenData.expires_at = satClaims.expires_at;
|
|
19606
|
+
this._effectiveExpireIn = resolveExpireIn(tokenData);
|
|
19607
|
+
const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19608
|
+
await session.reauthenticate(tokenData.token, rpcProof, { clientBound: true });
|
|
19609
|
+
updateCredential({ token: tokenData.token });
|
|
19610
|
+
logger$6.info("[DeviceToken] Client Bound SAT activated successfully");
|
|
19611
|
+
this._currentToken$.next(tokenData);
|
|
19612
|
+
} catch (error) {
|
|
19613
|
+
logger$6.error("[DeviceToken] Failed to activate Client Bound SAT:", error);
|
|
19614
|
+
this.errorHandler(new DPoPInitError(error, "Failed to activate Client Bound SAT"));
|
|
19615
|
+
const credential = this.getCredential();
|
|
19616
|
+
const expiresAt = satClaims.expires_at ?? (credential.expiry_at ? credential.expiry_at / 1e3 : Date.now() / 1e3 + DEVICE_TOKEN_DEFAULT_EXPIRE_IN / 1e3);
|
|
19617
|
+
this._currentToken$.next({
|
|
19618
|
+
token: credential.token ?? "",
|
|
19619
|
+
expires_at: expiresAt
|
|
19620
|
+
});
|
|
19621
|
+
}
|
|
19622
|
+
}
|
|
19623
|
+
/**
|
|
19624
|
+
* Obtains a Client Bound SAT from `/api/fabric/subscriber/devices/token`.
|
|
19625
|
+
* Returns the full {@link DeviceTokenResponse} including expiry metadata.
|
|
19626
|
+
*/
|
|
19627
|
+
async obtainToken() {
|
|
19628
|
+
const dpopProof = await this.dpopManager.createHttpProof({
|
|
19629
|
+
method: "POST",
|
|
19630
|
+
uri: DEVICE_TOKEN_ENDPOINT
|
|
19631
|
+
});
|
|
19632
|
+
const response = await this.http.request({
|
|
19633
|
+
url: DEVICE_TOKEN_ENDPOINT,
|
|
19634
|
+
...POST_PARAMS,
|
|
19635
|
+
body: JSON.stringify({
|
|
19636
|
+
dpop_token: dpopProof,
|
|
19637
|
+
expire_in: DEVICE_TOKEN_DEFAULT_EXPIRE_IN
|
|
19638
|
+
})
|
|
19639
|
+
});
|
|
19640
|
+
if (!response.ok || !response.body) throw new DeviceTokenError(`Failed to obtain device token: ${response.status} ${response.statusText}`);
|
|
19641
|
+
const data = JSON.parse(response.body);
|
|
19642
|
+
if (!data.token) throw new DeviceTokenError("Device token response missing token field");
|
|
19643
|
+
return data;
|
|
19644
|
+
}
|
|
19645
|
+
/**
|
|
19646
|
+
* Refreshes the Client Bound SAT via `/api/fabric/subscriber/devices/refresh`.
|
|
19647
|
+
*
|
|
19648
|
+
* Creates a fresh DPoP proof, calls the refresh endpoint, reauthenticates
|
|
19649
|
+
* the WebSocket session, and returns the new token data (scheduling is
|
|
19650
|
+
* handled by the reactive pipeline).
|
|
19651
|
+
*/
|
|
19652
|
+
async refreshToken(session, currentToken, updateCredential) {
|
|
19653
|
+
logger$6.debug("[DeviceToken] Refreshing Client Bound SAT");
|
|
19654
|
+
const dpopProof = await this.dpopManager.createHttpProof({
|
|
19655
|
+
method: "POST",
|
|
19656
|
+
uri: DEVICE_REFRESH_ENDPOINT,
|
|
19657
|
+
accessToken: currentToken
|
|
19658
|
+
});
|
|
19659
|
+
const response = await this.http.request({
|
|
19660
|
+
url: DEVICE_REFRESH_ENDPOINT,
|
|
19661
|
+
...POST_PARAMS,
|
|
19662
|
+
body: JSON.stringify({
|
|
19663
|
+
dpop_token: dpopProof,
|
|
19664
|
+
expire_in: this._effectiveExpireIn
|
|
19665
|
+
})
|
|
19666
|
+
});
|
|
19667
|
+
if (!response.ok || !response.body) throw new TokenRefreshError(`Failed to refresh device token: ${response.status} ${response.statusText}`);
|
|
19668
|
+
const data = JSON.parse(response.body);
|
|
19669
|
+
if (!data.token) throw new TokenRefreshError("Device token refresh response missing token field");
|
|
19670
|
+
if (!data.expires_at && !data.expires_in) data.expires_in = this._effectiveExpireIn;
|
|
19671
|
+
this._effectiveExpireIn = resolveExpireIn(data);
|
|
19672
|
+
const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19673
|
+
await session.reauthenticate(data.token, rpcProof);
|
|
19674
|
+
updateCredential({ token: data.token });
|
|
19675
|
+
logger$6.info("[DeviceToken] Client Bound SAT refreshed successfully");
|
|
19676
|
+
return data;
|
|
19677
|
+
}
|
|
19678
|
+
/**
|
|
19679
|
+
* Executes a refresh with retry and exponential backoff.
|
|
19680
|
+
* On success, emits to `_currentToken$` to schedule the next refresh.
|
|
19681
|
+
* On all retries exhausted, emits to `errorHandler`.
|
|
19682
|
+
*/
|
|
19683
|
+
async executeRefresh() {
|
|
19684
|
+
if (this._refreshInProgress) {
|
|
19685
|
+
logger$6.debug("[DeviceToken] Refresh already in progress, skipping");
|
|
19686
|
+
return;
|
|
19687
|
+
}
|
|
19688
|
+
const session = this._session;
|
|
19689
|
+
const updateCredential = this._updateCredential;
|
|
19690
|
+
if (!session || !updateCredential) {
|
|
19691
|
+
logger$6.warn("[DeviceToken] Cannot refresh: session or updateCredential not set");
|
|
19692
|
+
return;
|
|
19693
|
+
}
|
|
19694
|
+
if (!session.authenticated) {
|
|
19695
|
+
logger$6.debug("[DeviceToken] Session not authenticated, deferring refresh");
|
|
19696
|
+
return;
|
|
19697
|
+
}
|
|
19698
|
+
this._refreshInProgress = true;
|
|
19699
|
+
try {
|
|
19700
|
+
const currentToken = this.getCredential().token;
|
|
19701
|
+
if (!currentToken) throw new TokenRefreshError("No current token available for refresh");
|
|
19702
|
+
const newTokenData = await this.retryRefresh(session, currentToken, updateCredential);
|
|
19703
|
+
this._currentToken$.next(newTokenData);
|
|
19704
|
+
} catch (error) {
|
|
19705
|
+
logger$6.error("[DeviceToken] Automatic Client Bound SAT refresh failed:", error);
|
|
19706
|
+
this.errorHandler(error instanceof TokenRefreshError ? error : new TokenRefreshError("Automatic token refresh failed", error));
|
|
19707
|
+
} finally {
|
|
19708
|
+
this._refreshInProgress = false;
|
|
19709
|
+
}
|
|
19710
|
+
}
|
|
19711
|
+
/**
|
|
19712
|
+
* Retries `refreshToken()` up to `DEVICE_TOKEN_REFRESH_MAX_RETRIES` times
|
|
19713
|
+
* with exponential backoff (1s, 2s, 4s).
|
|
19714
|
+
*/
|
|
19715
|
+
async retryRefresh(session, currentToken, updateCredential) {
|
|
19716
|
+
let lastError;
|
|
19717
|
+
for (let attempt = 0; attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES; attempt++) try {
|
|
19718
|
+
return await this.refreshToken(session, currentToken, updateCredential);
|
|
19719
|
+
} catch (error) {
|
|
19720
|
+
lastError = error;
|
|
19721
|
+
if (attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES - 1) {
|
|
19722
|
+
const delay$1 = DEVICE_TOKEN_REFRESH_RETRY_BASE_MS * Math.pow(2, attempt);
|
|
19723
|
+
logger$6.warn(`[DeviceToken] Refresh attempt ${attempt + 1} failed, retrying in ${delay$1}ms`);
|
|
19724
|
+
await new Promise((resolve) => setTimeout(resolve, delay$1));
|
|
19725
|
+
}
|
|
19726
|
+
}
|
|
19727
|
+
throw lastError instanceof Error ? lastError : new TokenRefreshError("All refresh retries exhausted", lastError);
|
|
19728
|
+
}
|
|
19729
|
+
/** Cleans up the manager, cancelling the reactive pipeline and all subscriptions. */
|
|
19730
|
+
destroy() {
|
|
19731
|
+
super.destroy();
|
|
19732
|
+
}
|
|
19733
|
+
};
|
|
19734
|
+
|
|
19458
19735
|
//#endregion
|
|
19459
19736
|
//#region src/managers/DiagnosticsCollector.ts
|
|
19460
19737
|
const logger$5 = getLogger();
|
|
@@ -20388,13 +20665,43 @@ var SignalWire = class extends Destroyable {
|
|
|
20388
20665
|
this._errors$.next(error);
|
|
20389
20666
|
});
|
|
20390
20667
|
await this._clientSession.connect();
|
|
20391
|
-
|
|
20392
|
-
|
|
20393
|
-
|
|
20668
|
+
if (this._dpopManager?.initialized) {
|
|
20669
|
+
if (this._refreshTimerId) {
|
|
20670
|
+
clearTimeout(this._refreshTimerId);
|
|
20671
|
+
this._refreshTimerId = void 0;
|
|
20672
|
+
logger$1.debug("[SignalWire] Developer refresh disabled — Client Bound SAT activation starting");
|
|
20673
|
+
}
|
|
20674
|
+
this._deviceTokenManager = new DeviceTokenManager(this._dpopManager, this._deps.http, (error) => this._errors$.next(error), () => this._deps.credential);
|
|
20675
|
+
await this._deviceTokenManager.activate(this._deps.subscriber, this._clientSession, (cred) => {
|
|
20676
|
+
this._deps.credential = {
|
|
20677
|
+
...this._deps.credential,
|
|
20678
|
+
...cred
|
|
20679
|
+
};
|
|
20680
|
+
});
|
|
20681
|
+
}
|
|
20682
|
+
this.subscribeTo(this._clientSession.authenticated$.pipe((0, import_cjs.skip)(1), (0, import_cjs.filter)(Boolean)), async () => {
|
|
20683
|
+
try {
|
|
20684
|
+
if (this._deviceTokenManager) {
|
|
20685
|
+
await this._deviceTokenManager.activate(this._deps.subscriber, this._clientSession, (cred) => {
|
|
20686
|
+
this._deps.credential = {
|
|
20687
|
+
...this._deps.credential,
|
|
20688
|
+
...cred
|
|
20689
|
+
};
|
|
20690
|
+
});
|
|
20691
|
+
logger$1.debug("[SignalWire] Client Bound SAT re-activated after reconnect");
|
|
20692
|
+
}
|
|
20693
|
+
} catch (error) {
|
|
20694
|
+
logger$1.error("[SignalWire] Client Bound SAT re-activation failed (non-fatal):", error);
|
|
20695
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
20696
|
+
}
|
|
20697
|
+
try {
|
|
20698
|
+
logger$1.debug("[SignalWire] Re-registering subscriber after reconnect");
|
|
20699
|
+
await this.register();
|
|
20394
20700
|
logger$1.debug("[SignalWire] Subscriber re-registered successfully after reconnect");
|
|
20395
|
-
}
|
|
20701
|
+
} catch (error) {
|
|
20396
20702
|
logger$1.error("[SignalWire] Re-registration failed after reconnect:", error);
|
|
20397
|
-
|
|
20703
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
20704
|
+
}
|
|
20398
20705
|
});
|
|
20399
20706
|
const conversationManager = new ConversationsManager(this._clientSession, this._deps.http, () => this._deps.getSubscriberFromAddressId(), errorHandler);
|
|
20400
20707
|
const directory = new DirectoryManager(this._deps.http, this._clientSession, conversationManager, errorHandler);
|