@signalwire/js 4.0.0-dev-20260511184148 → 4.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.mjs +666 -444
- package/dist/browser.mjs.map +1 -1
- package/dist/browser.umd.js +666 -444
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +656 -434
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +92 -16
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +92 -16
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +656 -434
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser.mjs
CHANGED
|
@@ -9464,9 +9464,9 @@ var require_loglevel = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
9464
9464
|
defaultLogger$1 = new Logger();
|
|
9465
9465
|
defaultLogger$1.getLogger = function getLogger$1(name) {
|
|
9466
9466
|
if (typeof name !== "symbol" && typeof name !== "string" || name === "") throw new TypeError("You must supply a name when creating a logger.");
|
|
9467
|
-
var logger$
|
|
9468
|
-
if (!logger$
|
|
9469
|
-
return logger$
|
|
9467
|
+
var logger$33 = _loggersByName[name];
|
|
9468
|
+
if (!logger$33) logger$33 = _loggersByName[name] = new Logger(name, defaultLogger$1.methodFactory);
|
|
9469
|
+
return logger$33;
|
|
9470
9470
|
};
|
|
9471
9471
|
var _log = typeof window !== undefinedType ? window.log : void 0;
|
|
9472
9472
|
defaultLogger$1.noConflict = function() {
|
|
@@ -9502,8 +9502,8 @@ const defaultLoggerLevel = defaultLogger.levels.WARN;
|
|
|
9502
9502
|
defaultLogger.setLevel(defaultLoggerLevel);
|
|
9503
9503
|
let userLogger = null;
|
|
9504
9504
|
/** Replace the built-in logger with a custom implementation. Pass `null` to restore defaults. */
|
|
9505
|
-
const setLogger = (logger$
|
|
9506
|
-
userLogger = logger$
|
|
9505
|
+
const setLogger = (logger$33) => {
|
|
9506
|
+
userLogger = logger$33;
|
|
9507
9507
|
};
|
|
9508
9508
|
let debugOptions = {};
|
|
9509
9509
|
/** Configure debug options (e.g., `{ logWsTraffic: true }`). */
|
|
@@ -9547,8 +9547,8 @@ const wsTraffic = (options) => {
|
|
|
9547
9547
|
loggerInstance.debug(`${options.type.toUpperCase()}: \n`, msg, "\n");
|
|
9548
9548
|
};
|
|
9549
9549
|
const getLogger = () => {
|
|
9550
|
-
const logger$
|
|
9551
|
-
return new Proxy(logger$
|
|
9550
|
+
const logger$33 = getLoggerInstance();
|
|
9551
|
+
return new Proxy(logger$33, { get(_target, prop, _receiver) {
|
|
9552
9552
|
if (prop === "wsTraffic") return wsTraffic;
|
|
9553
9553
|
const instance = getLoggerInstance();
|
|
9554
9554
|
const value = Reflect.get(instance, prop);
|
|
@@ -9600,7 +9600,7 @@ const asyncRetry = async ({ asyncCallable, maxRetries: retries = DEFAULT_MAX_RET
|
|
|
9600
9600
|
|
|
9601
9601
|
//#endregion
|
|
9602
9602
|
//#region src/controllers/HTTPRequestController.ts
|
|
9603
|
-
const logger$
|
|
9603
|
+
const logger$32 = getLogger();
|
|
9604
9604
|
const GET_PARAMS = {
|
|
9605
9605
|
method: "GET",
|
|
9606
9606
|
headers: { Accept: "application/json" }
|
|
@@ -9664,7 +9664,7 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9664
9664
|
this._responses$.next(response);
|
|
9665
9665
|
return response;
|
|
9666
9666
|
} catch (error) {
|
|
9667
|
-
logger$
|
|
9667
|
+
logger$32.error("[HTTPRequestController] Request error:", error);
|
|
9668
9668
|
this._status$.next("error");
|
|
9669
9669
|
const err = error instanceof Error ? error : new Error("HTTP request failed", { cause: error });
|
|
9670
9670
|
this._errors$.next(err);
|
|
@@ -9691,7 +9691,7 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9691
9691
|
const url = this.buildURL(request.url);
|
|
9692
9692
|
const headers = this.buildHeaders(request.headers);
|
|
9693
9693
|
const timeout$5 = request.timeout ?? this.requestTimeout;
|
|
9694
|
-
logger$
|
|
9694
|
+
logger$32.debug("[HTTPRequestController] Executing request:", {
|
|
9695
9695
|
method: request.method,
|
|
9696
9696
|
url,
|
|
9697
9697
|
headers: Object.keys(headers).reduce((acc, key) => {
|
|
@@ -9711,7 +9711,7 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9711
9711
|
});
|
|
9712
9712
|
clearTimeout(timeoutId);
|
|
9713
9713
|
const httpResponse = await this.convertResponse(response);
|
|
9714
|
-
logger$
|
|
9714
|
+
logger$32.debug("[HTTPRequestController] Response received:", {
|
|
9715
9715
|
status: response.status,
|
|
9716
9716
|
statusText: response.statusText,
|
|
9717
9717
|
headers: [...response.headers.entries()],
|
|
@@ -9721,7 +9721,7 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9721
9721
|
} catch (error) {
|
|
9722
9722
|
clearTimeout(timeoutId);
|
|
9723
9723
|
if (error instanceof Error && error.name === "AbortError") throw new RequestTimeoutError(`Request timeout after ${timeout$5}ms`, { cause: error });
|
|
9724
|
-
logger$
|
|
9724
|
+
logger$32.error("[HTTPRequestController] Request failed:", error);
|
|
9725
9725
|
throw error;
|
|
9726
9726
|
}
|
|
9727
9727
|
}
|
|
@@ -9735,8 +9735,8 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9735
9735
|
const credential = this.getCredential();
|
|
9736
9736
|
if (credential.token) {
|
|
9737
9737
|
headers.Authorization = `Bearer ${credential.token}`;
|
|
9738
|
-
logger$
|
|
9739
|
-
} else logger$
|
|
9738
|
+
logger$32.debug("[HTTPRequestController] Using Bearer token auth, token length:", credential.token.length);
|
|
9739
|
+
} else logger$32.warn("[HTTPRequestController] No credentials available for authentication");
|
|
9740
9740
|
return headers;
|
|
9741
9741
|
}
|
|
9742
9742
|
/**
|
|
@@ -9906,6 +9906,13 @@ const CREDENTIAL_REFRESH_RETRY_BASE_MS = 1e3;
|
|
|
9906
9906
|
const CREDENTIAL_REFRESH_MAX_DELAY_MS = 3e4;
|
|
9907
9907
|
/** Buffer in milliseconds before token expiry to trigger refresh. */
|
|
9908
9908
|
const CREDENTIAL_REFRESH_BUFFER_MS = 5e3;
|
|
9909
|
+
/**
|
|
9910
|
+
* Maximum time the coordinator will wait for `DeviceTokenManager.activate()`
|
|
9911
|
+
* to resolve before treating the activation as failed and falling back to
|
|
9912
|
+
* the developer-provided refresh path. Prevents a wedged HTTP layer from
|
|
9913
|
+
* leaving the session with no active refresh mechanism.
|
|
9914
|
+
*/
|
|
9915
|
+
const CREDENTIAL_ACTIVATE_TIMEOUT_MS = 3e4;
|
|
9909
9916
|
/** JSON-RPC error code for requester validation failure (corrupted auth state). */
|
|
9910
9917
|
const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
|
|
9911
9918
|
/** JSON-RPC error code for invalid params (e.g., missing authentication block). */
|
|
@@ -10008,7 +10015,7 @@ function fromMsToSec(milliseconds) {
|
|
|
10008
10015
|
|
|
10009
10016
|
//#endregion
|
|
10010
10017
|
//#region src/containers/PreferencesContainer.ts
|
|
10011
|
-
const logger$
|
|
10018
|
+
const logger$31 = getLogger();
|
|
10012
10019
|
var PreferencesContainer = class PreferencesContainer {
|
|
10013
10020
|
static get instance() {
|
|
10014
10021
|
this._instance ??= new PreferencesContainer();
|
|
@@ -10670,7 +10677,7 @@ var ClientPreferences = class {
|
|
|
10670
10677
|
if (!this._storage) return;
|
|
10671
10678
|
const data = collectStoredPreferences();
|
|
10672
10679
|
this._storage.setItem(PREFERENCES_STORAGE_KEY, data, "local").catch((error) => {
|
|
10673
|
-
logger$
|
|
10680
|
+
logger$31.error(`[ClientPreferences] Failed to save preferences: ${String(error)}`);
|
|
10674
10681
|
});
|
|
10675
10682
|
}
|
|
10676
10683
|
/** Loads preferences from storage and applies them to the container. */
|
|
@@ -10679,7 +10686,7 @@ var ClientPreferences = class {
|
|
|
10679
10686
|
this._storage.getItem(PREFERENCES_STORAGE_KEY, "local").then((stored) => {
|
|
10680
10687
|
if (stored) applyStoredPreferences(stored);
|
|
10681
10688
|
}).catch((error) => {
|
|
10682
|
-
logger$
|
|
10689
|
+
logger$31.error(`[ClientPreferences] Failed to load preferences: ${String(error)}`);
|
|
10683
10690
|
});
|
|
10684
10691
|
}
|
|
10685
10692
|
};
|
|
@@ -10701,7 +10708,7 @@ function toError(value) {
|
|
|
10701
10708
|
//#endregion
|
|
10702
10709
|
//#region src/controllers/NavigatorDeviceController.ts
|
|
10703
10710
|
var import_cjs$29 = require_cjs();
|
|
10704
|
-
const logger$
|
|
10711
|
+
const logger$30 = getLogger();
|
|
10705
10712
|
/** Maps a device kind to its storage key. */
|
|
10706
10713
|
const DEVICE_STORAGE_KEYS = {
|
|
10707
10714
|
audioinput: DEVICE_STORAGE_KEY_AUDIO_INPUT,
|
|
@@ -10723,7 +10730,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10723
10730
|
super();
|
|
10724
10731
|
this.webRTCApiProvider = webRTCApiProvider;
|
|
10725
10732
|
this.deviceChangeHandler = () => {
|
|
10726
|
-
logger$
|
|
10733
|
+
logger$30.debug("[DeviceController] Device change detected");
|
|
10727
10734
|
this.enumerateDevices();
|
|
10728
10735
|
};
|
|
10729
10736
|
this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
|
|
@@ -10788,13 +10795,13 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10788
10795
|
return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, import_cjs$29.map)((state) => state.videoinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$)));
|
|
10789
10796
|
}
|
|
10790
10797
|
get selectedAudioInputDevice$() {
|
|
10791
|
-
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.audioinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$
|
|
10798
|
+
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.audioinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$30.debug("[DeviceController] Selected audio input device changed:", info))));
|
|
10792
10799
|
}
|
|
10793
10800
|
get selectedAudioOutputDevice$() {
|
|
10794
|
-
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.audiooutput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$
|
|
10801
|
+
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.audiooutput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$30.debug("[DeviceController] Selected audio output device changed:", info))));
|
|
10795
10802
|
}
|
|
10796
10803
|
get selectedVideoInputDevice$() {
|
|
10797
|
-
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.videoinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$
|
|
10804
|
+
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.videoinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$30.debug("[DeviceController] Selected video input device changed:", info))));
|
|
10798
10805
|
}
|
|
10799
10806
|
get selectedAudioInputDevice() {
|
|
10800
10807
|
if (this._audioInputDisabled$.value) return null;
|
|
@@ -10869,7 +10876,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10869
10876
|
if (device) this.persistDeviceSelection("audioinput", device);
|
|
10870
10877
|
}
|
|
10871
10878
|
selectVideoInputDevice(device) {
|
|
10872
|
-
logger$
|
|
10879
|
+
logger$30.debug("[DeviceController] Setting selected video input device:", device);
|
|
10873
10880
|
if (this._videoInputDisabled$.value && device) this._videoInputDisabled$.next(false);
|
|
10874
10881
|
const previous = this._selectedDevicesState$.value.videoinput;
|
|
10875
10882
|
if (previous && previous.deviceId !== device?.deviceId) this._deviceHistory.push("videoinput", previous);
|
|
@@ -10926,7 +10933,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10926
10933
|
}
|
|
10927
10934
|
const fromHistory = this._deviceHistory.findInHistory(kind, devices);
|
|
10928
10935
|
if (fromHistory) {
|
|
10929
|
-
logger$
|
|
10936
|
+
logger$30.debug(`[DeviceController] Device disappeared, falling back to history: ${fromHistory.label}`);
|
|
10930
10937
|
this.emitDeviceRecovered(kind, selected, fromHistory, "device_disconnected");
|
|
10931
10938
|
return fromHistory;
|
|
10932
10939
|
}
|
|
@@ -10979,7 +10986,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10979
10986
|
try {
|
|
10980
10987
|
await this._storageManager.setItem(DEVICE_STORAGE_KEYS[kind], stored, "local");
|
|
10981
10988
|
} catch (error) {
|
|
10982
|
-
logger$
|
|
10989
|
+
logger$30.error(`[DeviceController] Failed to persist device selection for ${kind}:`, error);
|
|
10983
10990
|
}
|
|
10984
10991
|
}
|
|
10985
10992
|
async loadPersistedDevices() {
|
|
@@ -10995,7 +11002,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10995
11002
|
[kind]: stored
|
|
10996
11003
|
};
|
|
10997
11004
|
} catch (error) {
|
|
10998
|
-
logger$
|
|
11005
|
+
logger$30.error(`[DeviceController] Failed to load persisted device for ${kind}:`, error);
|
|
10999
11006
|
}
|
|
11000
11007
|
}
|
|
11001
11008
|
/** Clears device history, persisted selections, and re-enumerates devices. */
|
|
@@ -11013,7 +11020,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
11013
11020
|
this.disableDeviceMonitoring();
|
|
11014
11021
|
this.webRTCApiProvider.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
|
|
11015
11022
|
if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$29.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
|
|
11016
|
-
logger$
|
|
11023
|
+
logger$30.debug("[DeviceController] Polling devices due to interval");
|
|
11017
11024
|
this.enumerateDevices();
|
|
11018
11025
|
});
|
|
11019
11026
|
this.enumerateDevices();
|
|
@@ -11039,13 +11046,13 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
11039
11046
|
videoinput: []
|
|
11040
11047
|
});
|
|
11041
11048
|
this._devicesState$.next(devicesByKind);
|
|
11042
|
-
logger$
|
|
11049
|
+
logger$30.debug("[DeviceController] Devices enumerated:", {
|
|
11043
11050
|
audioInputs: devicesByKind.audioinput.length,
|
|
11044
11051
|
audioOutputs: devicesByKind.audiooutput.length,
|
|
11045
11052
|
videoInputs: devicesByKind.videoinput.length
|
|
11046
11053
|
});
|
|
11047
11054
|
} catch (error) {
|
|
11048
|
-
logger$
|
|
11055
|
+
logger$30.error("[DeviceController] Failed to enumerate devices:", error);
|
|
11049
11056
|
this._errors$.next(toError(error));
|
|
11050
11057
|
}
|
|
11051
11058
|
}
|
|
@@ -11061,7 +11068,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
11061
11068
|
stream.getTracks().forEach((t) => t.stop());
|
|
11062
11069
|
return capabilities;
|
|
11063
11070
|
} catch (error) {
|
|
11064
|
-
logger$
|
|
11071
|
+
logger$30.error("[DeviceController] Failed to get device capabilities:", error);
|
|
11065
11072
|
this._errors$.next(toError(error));
|
|
11066
11073
|
throw error;
|
|
11067
11074
|
}
|
|
@@ -11312,7 +11319,7 @@ var DependencyContainer = class {
|
|
|
11312
11319
|
|
|
11313
11320
|
//#endregion
|
|
11314
11321
|
//#region src/controllers/CryptoController.ts
|
|
11315
|
-
const logger$
|
|
11322
|
+
const logger$29 = getLogger();
|
|
11316
11323
|
const DPOP_DB_NAME = "sw-dpop";
|
|
11317
11324
|
const DPOP_DB_VERSION = 1;
|
|
11318
11325
|
const DPOP_STORE_NAME = "keys";
|
|
@@ -11371,7 +11378,7 @@ async function loadKeyPairFromDB() {
|
|
|
11371
11378
|
tx.oncomplete = () => db.close();
|
|
11372
11379
|
});
|
|
11373
11380
|
} catch (error) {
|
|
11374
|
-
logger$
|
|
11381
|
+
logger$29.warn("[DPoP] Failed to load key pair from IndexedDB:", error);
|
|
11375
11382
|
return null;
|
|
11376
11383
|
}
|
|
11377
11384
|
}
|
|
@@ -11391,7 +11398,7 @@ async function saveKeyPairToDB(keyPair) {
|
|
|
11391
11398
|
};
|
|
11392
11399
|
});
|
|
11393
11400
|
} catch (error) {
|
|
11394
|
-
logger$
|
|
11401
|
+
logger$29.warn("[DPoP] Failed to save key pair to IndexedDB:", error);
|
|
11395
11402
|
}
|
|
11396
11403
|
}
|
|
11397
11404
|
async function deleteKeyPairFromDB() {
|
|
@@ -11410,7 +11417,7 @@ async function deleteKeyPairFromDB() {
|
|
|
11410
11417
|
};
|
|
11411
11418
|
});
|
|
11412
11419
|
} catch (error) {
|
|
11413
|
-
logger$
|
|
11420
|
+
logger$29.warn("[DPoP] Failed to delete key pair from IndexedDB:", error);
|
|
11414
11421
|
}
|
|
11415
11422
|
}
|
|
11416
11423
|
/**
|
|
@@ -11470,13 +11477,13 @@ var CryptoController = class {
|
|
|
11470
11477
|
this._publicJwk = await crypto.subtle.exportKey("jwk", stored.publicKey);
|
|
11471
11478
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11472
11479
|
this._initialized = true;
|
|
11473
|
-
logger$
|
|
11480
|
+
logger$29.debug("[DPoP] Key pair restored from IndexedDB, fingerprint:", this._fingerprint);
|
|
11474
11481
|
return this._fingerprint;
|
|
11475
11482
|
} catch (error) {
|
|
11476
|
-
logger$
|
|
11483
|
+
logger$29.warn("[DPoP] Stored key pair unusable, generating new one:", error);
|
|
11477
11484
|
await deleteKeyPairFromDB();
|
|
11478
11485
|
}
|
|
11479
|
-
logger$
|
|
11486
|
+
logger$29.debug("[DPoP] Generating RSA key pair");
|
|
11480
11487
|
this._keyPair = await crypto.subtle.generateKey({
|
|
11481
11488
|
name: "RSASSA-PKCS1-v1_5",
|
|
11482
11489
|
modulusLength: 2048,
|
|
@@ -11491,7 +11498,7 @@ var CryptoController = class {
|
|
|
11491
11498
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11492
11499
|
this._initialized = true;
|
|
11493
11500
|
await saveKeyPairToDB(this._keyPair);
|
|
11494
|
-
logger$
|
|
11501
|
+
logger$29.debug("[DPoP] Key pair generated and persisted, fingerprint:", this._fingerprint);
|
|
11495
11502
|
return this._fingerprint;
|
|
11496
11503
|
}
|
|
11497
11504
|
/**
|
|
@@ -11557,7 +11564,7 @@ var CryptoController = class {
|
|
|
11557
11564
|
this._fingerprint = null;
|
|
11558
11565
|
this._initialized = false;
|
|
11559
11566
|
deleteKeyPairFromDB();
|
|
11560
|
-
logger$
|
|
11567
|
+
logger$29.debug("[DPoP] Controller destroyed");
|
|
11561
11568
|
}
|
|
11562
11569
|
get publicJwk() {
|
|
11563
11570
|
if (!this._publicJwk) throw new DPoPInitError("CryptoController not initialized. Call init() first.");
|
|
@@ -11581,7 +11588,7 @@ var CryptoController = class {
|
|
|
11581
11588
|
//#endregion
|
|
11582
11589
|
//#region src/controllers/NetworkMonitor.ts
|
|
11583
11590
|
var import_cjs$28 = require_cjs();
|
|
11584
|
-
const logger$
|
|
11591
|
+
const logger$28 = getLogger();
|
|
11585
11592
|
/**
|
|
11586
11593
|
* Safely check whether we are running in a browser environment
|
|
11587
11594
|
* with `window` and the relevant event targets.
|
|
@@ -11638,7 +11645,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11638
11645
|
}
|
|
11639
11646
|
attachListeners() {
|
|
11640
11647
|
if (!hasBrowserNetworkEvents()) {
|
|
11641
|
-
logger$
|
|
11648
|
+
logger$28.debug("NetworkMonitor: no browser environment detected, skipping event listeners");
|
|
11642
11649
|
return;
|
|
11643
11650
|
}
|
|
11644
11651
|
window.addEventListener("online", this._onOnline);
|
|
@@ -11646,7 +11653,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11646
11653
|
const connection = getNetworkConnection();
|
|
11647
11654
|
if (connection) connection.addEventListener("change", this._onConnectionChange);
|
|
11648
11655
|
this._listenersAttached = true;
|
|
11649
|
-
logger$
|
|
11656
|
+
logger$28.debug("NetworkMonitor: event listeners attached");
|
|
11650
11657
|
}
|
|
11651
11658
|
removeListeners() {
|
|
11652
11659
|
if (!this._listenersAttached) return;
|
|
@@ -11657,10 +11664,10 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11657
11664
|
if (connection) connection.removeEventListener("change", this._onConnectionChange);
|
|
11658
11665
|
}
|
|
11659
11666
|
this._listenersAttached = false;
|
|
11660
|
-
logger$
|
|
11667
|
+
logger$28.debug("NetworkMonitor: event listeners removed");
|
|
11661
11668
|
}
|
|
11662
11669
|
handleOnline() {
|
|
11663
|
-
logger$
|
|
11670
|
+
logger$28.info("NetworkMonitor: browser went online");
|
|
11664
11671
|
this._isOnline$.next(true);
|
|
11665
11672
|
this._networkChange$.next({
|
|
11666
11673
|
type: "online",
|
|
@@ -11669,7 +11676,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11669
11676
|
});
|
|
11670
11677
|
}
|
|
11671
11678
|
handleOffline() {
|
|
11672
|
-
logger$
|
|
11679
|
+
logger$28.info("NetworkMonitor: browser went offline");
|
|
11673
11680
|
this._isOnline$.next(false);
|
|
11674
11681
|
this._networkChange$.next({
|
|
11675
11682
|
type: "offline",
|
|
@@ -11678,7 +11685,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11678
11685
|
}
|
|
11679
11686
|
handleConnectionChange() {
|
|
11680
11687
|
const networkType = getNetworkType();
|
|
11681
|
-
logger$
|
|
11688
|
+
logger$28.info(`NetworkMonitor: connection changed — effectiveType=${networkType ?? "unknown"}`);
|
|
11682
11689
|
this._networkChange$.next({
|
|
11683
11690
|
type: "connection_change",
|
|
11684
11691
|
timestamp: Date.now(),
|
|
@@ -11794,7 +11801,7 @@ function getNavigatorMediaDevices() {
|
|
|
11794
11801
|
//#endregion
|
|
11795
11802
|
//#region src/controllers/PreflightRunner.ts
|
|
11796
11803
|
var import_cjs$27 = require_cjs();
|
|
11797
|
-
const logger$
|
|
11804
|
+
const logger$27 = getLogger();
|
|
11798
11805
|
const DEFAULT_MEDIA_TEST_DURATION_S = 10;
|
|
11799
11806
|
const ICE_GATHERING_TIMEOUT_MS = 1e4;
|
|
11800
11807
|
const SIGNALING_RTT_TIMEOUT_MS = 5e3;
|
|
@@ -11843,7 +11850,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11843
11850
|
if (!this._options.skipMediaTest) try {
|
|
11844
11851
|
bandwidth = await this.testMediaBandwidth(destination);
|
|
11845
11852
|
} catch (error) {
|
|
11846
|
-
logger$
|
|
11853
|
+
logger$27.warn("[PreflightRunner] Media bandwidth test failed:", error);
|
|
11847
11854
|
warnings.push("Media bandwidth test failed");
|
|
11848
11855
|
}
|
|
11849
11856
|
return {
|
|
@@ -11855,7 +11862,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11855
11862
|
warnings
|
|
11856
11863
|
};
|
|
11857
11864
|
} catch (error) {
|
|
11858
|
-
logger$
|
|
11865
|
+
logger$27.error("[PreflightRunner] Preflight test failed:", error);
|
|
11859
11866
|
throw new PreflightError("preflight", error instanceof Error ? error : new Error(String(error)));
|
|
11860
11867
|
} finally {
|
|
11861
11868
|
this.destroy();
|
|
@@ -11886,7 +11893,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11886
11893
|
if (track.kind === "video" && track.readyState === "live") videoWorking = true;
|
|
11887
11894
|
}
|
|
11888
11895
|
} catch (error) {
|
|
11889
|
-
logger$
|
|
11896
|
+
logger$27.warn("[PreflightRunner] Device test failed:", error);
|
|
11890
11897
|
} finally {
|
|
11891
11898
|
if (audioStream) audioStream.getTracks().forEach((t) => t.stop());
|
|
11892
11899
|
}
|
|
@@ -11944,7 +11951,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11944
11951
|
rttMs
|
|
11945
11952
|
};
|
|
11946
11953
|
} catch (error) {
|
|
11947
|
-
logger$
|
|
11954
|
+
logger$27.warn("[PreflightRunner] ICE connectivity test failed:", error);
|
|
11948
11955
|
return {
|
|
11949
11956
|
type: "failed",
|
|
11950
11957
|
turnReachable: false,
|
|
@@ -11992,7 +11999,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11992
11999
|
//#endregion
|
|
11993
12000
|
//#region src/controllers/VisibilityController.ts
|
|
11994
12001
|
var import_cjs$26 = require_cjs();
|
|
11995
|
-
const logger$
|
|
12002
|
+
const logger$26 = getLogger();
|
|
11996
12003
|
/**
|
|
11997
12004
|
* Checks whether the document visibility API is available.
|
|
11998
12005
|
*/
|
|
@@ -12029,8 +12036,8 @@ var VisibilityController = class extends Destroyable {
|
|
|
12029
12036
|
this._boundHandler = this._handleVisibilityChange.bind(this);
|
|
12030
12037
|
if (this._hasVisibilityApi) {
|
|
12031
12038
|
document.addEventListener("visibilitychange", this._boundHandler);
|
|
12032
|
-
logger$
|
|
12033
|
-
} else logger$
|
|
12039
|
+
logger$26.debug("VisibilityController: listening for visibilitychange events");
|
|
12040
|
+
} else logger$26.debug("VisibilityController: document visibility API not available, defaulting to visible");
|
|
12034
12041
|
}
|
|
12035
12042
|
/**
|
|
12036
12043
|
* Observable of the current visibility state.
|
|
@@ -12055,7 +12062,7 @@ var VisibilityController = class extends Destroyable {
|
|
|
12055
12062
|
destroy() {
|
|
12056
12063
|
if (this._hasVisibilityApi) {
|
|
12057
12064
|
document.removeEventListener("visibilitychange", this._boundHandler);
|
|
12058
|
-
logger$
|
|
12065
|
+
logger$26.debug("VisibilityController: removed visibilitychange listener");
|
|
12059
12066
|
}
|
|
12060
12067
|
super.destroy();
|
|
12061
12068
|
}
|
|
@@ -12073,7 +12080,7 @@ var VisibilityController = class extends Destroyable {
|
|
|
12073
12080
|
timestamp: Date.now()
|
|
12074
12081
|
};
|
|
12075
12082
|
this._visibilityChange$.next(changeEvent);
|
|
12076
|
-
logger$
|
|
12083
|
+
logger$26.debug("VisibilityController: visibility changed", {
|
|
12077
12084
|
from: previousState,
|
|
12078
12085
|
to: newState
|
|
12079
12086
|
});
|
|
@@ -12314,7 +12321,7 @@ const RPCEventAckResponse = (id) => makeRPCResponse({
|
|
|
12314
12321
|
|
|
12315
12322
|
//#endregion
|
|
12316
12323
|
//#region src/managers/AttachManager.ts
|
|
12317
|
-
const logger$
|
|
12324
|
+
const logger$25 = getLogger();
|
|
12318
12325
|
var AttachManager = class {
|
|
12319
12326
|
constructor(storage, deviceController, reconnectCallsTimeout, attachKey) {
|
|
12320
12327
|
this.storage = storage;
|
|
@@ -12335,7 +12342,7 @@ var AttachManager = class {
|
|
|
12335
12342
|
try {
|
|
12336
12343
|
return await this.storage.getItem(this.attachKey) ?? {};
|
|
12337
12344
|
} catch (error) {
|
|
12338
|
-
logger$
|
|
12345
|
+
logger$25.warn("[AttachManager] Failed to retrieve attached calls from storage", error);
|
|
12339
12346
|
return {};
|
|
12340
12347
|
}
|
|
12341
12348
|
}
|
|
@@ -12343,7 +12350,7 @@ var AttachManager = class {
|
|
|
12343
12350
|
try {
|
|
12344
12351
|
await this.storage.setItem(this.attachKey, attached);
|
|
12345
12352
|
} catch (error) {
|
|
12346
|
-
logger$
|
|
12353
|
+
logger$25.warn("[AttachManager] Failed to write attached calls to storage", error);
|
|
12347
12354
|
}
|
|
12348
12355
|
}
|
|
12349
12356
|
/**
|
|
@@ -12362,7 +12369,7 @@ var AttachManager = class {
|
|
|
12362
12369
|
}
|
|
12363
12370
|
async attach(call) {
|
|
12364
12371
|
if (!call.to) {
|
|
12365
|
-
logger$
|
|
12372
|
+
logger$25.warn("[AttachManager] Skip attach for calls with no destination");
|
|
12366
12373
|
return;
|
|
12367
12374
|
}
|
|
12368
12375
|
const destination = call.to;
|
|
@@ -12415,15 +12422,15 @@ var AttachManager = class {
|
|
|
12415
12422
|
callId,
|
|
12416
12423
|
...options
|
|
12417
12424
|
});
|
|
12418
|
-
logger$
|
|
12425
|
+
logger$25.info(`[AttachManager] Reattached call ${callId} (attempt ${attempt})`);
|
|
12419
12426
|
succeeded = true;
|
|
12420
12427
|
break;
|
|
12421
12428
|
} catch (error) {
|
|
12422
|
-
logger$
|
|
12429
|
+
logger$25.warn(`[AttachManager] Reattach attempt ${attempt}/3 failed for call ${callId}:`, error);
|
|
12423
12430
|
if (attempt < 3) await new Promise((r) => setTimeout(r, (attempt + 1) * 1e3));
|
|
12424
12431
|
}
|
|
12425
12432
|
if (!succeeded) {
|
|
12426
|
-
logger$
|
|
12433
|
+
logger$25.warn(`[AttachManager] Reattach failed after 3 attempts for call ${callId}, removing reference`);
|
|
12427
12434
|
await this.detach({
|
|
12428
12435
|
id: callId,
|
|
12429
12436
|
mediaDirections: attachment.mediaDirections
|
|
@@ -13590,7 +13597,7 @@ function toggleHandraiseMethod(is) {
|
|
|
13590
13597
|
|
|
13591
13598
|
//#endregion
|
|
13592
13599
|
//#region src/core/entities/Participant.ts
|
|
13593
|
-
const logger$
|
|
13600
|
+
const logger$24 = getLogger();
|
|
13594
13601
|
const initialState = {};
|
|
13595
13602
|
/**
|
|
13596
13603
|
* Represents a participant in a call.
|
|
@@ -14023,7 +14030,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14023
14030
|
try {
|
|
14024
14031
|
await this.vertoManager.addScreenMedia();
|
|
14025
14032
|
} catch (error) {
|
|
14026
|
-
logger$
|
|
14033
|
+
logger$24.error("[Participant.startScreenShare] Screen share error:", error);
|
|
14027
14034
|
}
|
|
14028
14035
|
}
|
|
14029
14036
|
/** Observable of the current screen share status. */
|
|
@@ -14043,7 +14050,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14043
14050
|
try {
|
|
14044
14051
|
await this.vertoManager.addInputDevice(options);
|
|
14045
14052
|
} catch (error) {
|
|
14046
|
-
logger$
|
|
14053
|
+
logger$24.error("[Participant.startScreenShare] Screen share error:", error);
|
|
14047
14054
|
}
|
|
14048
14055
|
}
|
|
14049
14056
|
/** Removes an additional media input device by ID. */
|
|
@@ -14105,7 +14112,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14105
14112
|
*/
|
|
14106
14113
|
exitStudioModeIfActive() {
|
|
14107
14114
|
if (this._studioAudio$.value) {
|
|
14108
|
-
logger$
|
|
14115
|
+
logger$24.debug("[SelfParticipant] Exiting studio audio mode due to individual flag toggle");
|
|
14109
14116
|
this._studioAudio$.next(false);
|
|
14110
14117
|
}
|
|
14111
14118
|
}
|
|
@@ -14129,7 +14136,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14129
14136
|
try {
|
|
14130
14137
|
await super.mute();
|
|
14131
14138
|
} catch (error) {
|
|
14132
|
-
logger$
|
|
14139
|
+
logger$24.warn("[Participant.toggleAudioInput] Server Error while muting audio input, proceeding with local toggle anyway", error);
|
|
14133
14140
|
} finally {
|
|
14134
14141
|
this.vertoManager.muteMainAudioInputDevice();
|
|
14135
14142
|
}
|
|
@@ -14139,7 +14146,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14139
14146
|
try {
|
|
14140
14147
|
await super.unmute();
|
|
14141
14148
|
} catch (error) {
|
|
14142
|
-
logger$
|
|
14149
|
+
logger$24.warn("[Participant.toggleAudioInput] Server Error while unmuting audio input, proceeding with local toggle anyway", error);
|
|
14143
14150
|
} finally {
|
|
14144
14151
|
await this.vertoManager.unmuteMainAudioInputDevice();
|
|
14145
14152
|
}
|
|
@@ -14149,7 +14156,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14149
14156
|
try {
|
|
14150
14157
|
await super.muteVideo();
|
|
14151
14158
|
} catch (error) {
|
|
14152
|
-
logger$
|
|
14159
|
+
logger$24.warn("[Participant.toggleVideoInput] Server Error while muting video input, proceeding with local toggle anyway", error);
|
|
14153
14160
|
} finally {
|
|
14154
14161
|
this.vertoManager.muteMainVideoInputDevice();
|
|
14155
14162
|
}
|
|
@@ -14159,7 +14166,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14159
14166
|
try {
|
|
14160
14167
|
await super.unmuteVideo();
|
|
14161
14168
|
} catch (error) {
|
|
14162
|
-
logger$
|
|
14169
|
+
logger$24.warn("[Participant.toggleVideoInput] Server Error while unmuting video input, proceeding with local toggle anyway", error);
|
|
14163
14170
|
} finally {
|
|
14164
14171
|
await this.vertoManager.unmuteMainVideoInputDevice();
|
|
14165
14172
|
}
|
|
@@ -14364,7 +14371,7 @@ function filterAs(predicate, resultPath) {
|
|
|
14364
14371
|
//#endregion
|
|
14365
14372
|
//#region src/operators/throwOnRPCError.ts
|
|
14366
14373
|
var import_cjs$21 = require_cjs();
|
|
14367
|
-
const logger$
|
|
14374
|
+
const logger$23 = getLogger();
|
|
14368
14375
|
/**
|
|
14369
14376
|
* RxJS operator that throws a {@link JSONRPCError} when the RPC response contains an error.
|
|
14370
14377
|
* Passes successful responses through unchanged.
|
|
@@ -14372,14 +14379,14 @@ const logger$22 = getLogger();
|
|
|
14372
14379
|
function throwOnRPCError() {
|
|
14373
14380
|
return (0, import_cjs$21.map)((response) => {
|
|
14374
14381
|
if (response.error) {
|
|
14375
|
-
logger$
|
|
14382
|
+
logger$23.error("[throwOnRPCError] RPC error response:", {
|
|
14376
14383
|
code: response.error.code,
|
|
14377
14384
|
message: response.error.message,
|
|
14378
14385
|
data: response.error.data
|
|
14379
14386
|
});
|
|
14380
14387
|
throw new JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
14381
14388
|
}
|
|
14382
|
-
logger$
|
|
14389
|
+
logger$23.debug("[throwOnRPCError] RPC successful response:", response);
|
|
14383
14390
|
return response;
|
|
14384
14391
|
});
|
|
14385
14392
|
}
|
|
@@ -14387,7 +14394,7 @@ function throwOnRPCError() {
|
|
|
14387
14394
|
//#endregion
|
|
14388
14395
|
//#region src/managers/CallEventsManager.ts
|
|
14389
14396
|
var import_cjs$20 = require_cjs();
|
|
14390
|
-
const logger$
|
|
14397
|
+
const logger$22 = getLogger();
|
|
14391
14398
|
const initialSessionState = {};
|
|
14392
14399
|
/** @internal */
|
|
14393
14400
|
var CallEventsManager = class extends Destroyable {
|
|
@@ -14491,7 +14498,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14491
14498
|
}
|
|
14492
14499
|
initSubscriptions() {
|
|
14493
14500
|
this.subscribeTo(this.callJoinedEvent$, (callJoinedEvent) => {
|
|
14494
|
-
logger$
|
|
14501
|
+
logger$22.debug("[CallEventsManager] Handling call.joined event for call/session IDs:", {
|
|
14495
14502
|
callId: callJoinedEvent.call_id,
|
|
14496
14503
|
roomSessionId: callJoinedEvent.room_session_id
|
|
14497
14504
|
});
|
|
@@ -14518,19 +14525,19 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14518
14525
|
if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
|
|
14519
14526
|
});
|
|
14520
14527
|
this.subscribeTo(this.memberUpdates$, (member) => {
|
|
14521
|
-
logger$
|
|
14528
|
+
logger$22.debug("[CallEventsManager] Handling member update event for member ID:", member);
|
|
14522
14529
|
this.upsertParticipant(member);
|
|
14523
14530
|
});
|
|
14524
14531
|
this.subscribeTo(this.webRtcCallSession.memberLeft$, (memberLeftEvent) => {
|
|
14525
|
-
logger$
|
|
14532
|
+
logger$22.debug("[CallEventsManager] Handling member.left event for member ID:", memberLeftEvent.member.member_id);
|
|
14526
14533
|
const participants = { ...this._participants$.value };
|
|
14527
14534
|
if (memberLeftEvent.member.member_id in participants) {
|
|
14528
14535
|
delete participants[memberLeftEvent.member.member_id];
|
|
14529
14536
|
this._participants$.next(participants);
|
|
14530
|
-
} else logger$
|
|
14537
|
+
} else logger$22.warn(`[CallEventsManager] Received member.left event for unknown member ID: ${memberLeftEvent.member.member_id}`);
|
|
14531
14538
|
});
|
|
14532
14539
|
this.subscribeTo(this.webRtcCallSession.callUpdated$, (callUpdatedEvent) => {
|
|
14533
|
-
logger$
|
|
14540
|
+
logger$22.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
|
|
14534
14541
|
const roomSession = callUpdatedEvent.room_session;
|
|
14535
14542
|
this._sessionState$.next({
|
|
14536
14543
|
...this._sessionState$.value,
|
|
@@ -14545,7 +14552,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14545
14552
|
});
|
|
14546
14553
|
});
|
|
14547
14554
|
this.subscribeTo(this.layoutChangedEvent$, (layoutChangedEvent) => {
|
|
14548
|
-
logger$
|
|
14555
|
+
logger$22.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
|
|
14549
14556
|
this._sessionState$.next({
|
|
14550
14557
|
...this._sessionState$.value,
|
|
14551
14558
|
layout_name: layoutChangedEvent.id,
|
|
@@ -14555,10 +14562,10 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14555
14562
|
});
|
|
14556
14563
|
}
|
|
14557
14564
|
updateParticipantPositions(layoutChangedEvent) {
|
|
14558
|
-
if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$
|
|
14565
|
+
if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$22.warn("[CallEventsManager] No layers with member_id found in layout.changed event. Nothing to update.");
|
|
14559
14566
|
layoutChangedEvent.layers.filter((layer) => !!layer.member_id).filter((layer) => {
|
|
14560
14567
|
if (!(layer.member_id in this._participants$.value)) {
|
|
14561
|
-
logger$
|
|
14568
|
+
logger$22.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
|
|
14562
14569
|
return false;
|
|
14563
14570
|
}
|
|
14564
14571
|
return true;
|
|
@@ -14581,7 +14588,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14581
14588
|
layouts: response.result.layouts
|
|
14582
14589
|
});
|
|
14583
14590
|
}).catch((error) => {
|
|
14584
|
-
logger$
|
|
14591
|
+
logger$22.error("[CallEventsManager] Error fetching layouts:", error);
|
|
14585
14592
|
});
|
|
14586
14593
|
}
|
|
14587
14594
|
updateParticipants(members) {
|
|
@@ -14597,7 +14604,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14597
14604
|
}
|
|
14598
14605
|
const participant = this._participants$.value[member.member_id];
|
|
14599
14606
|
const oldValue = participant.value;
|
|
14600
|
-
logger$
|
|
14607
|
+
logger$22.debug("[CallEventsManager] Updating participant:", member.member_id, {
|
|
14601
14608
|
oldValue,
|
|
14602
14609
|
newValue: member
|
|
14603
14610
|
});
|
|
@@ -14610,17 +14617,17 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14610
14617
|
}
|
|
14611
14618
|
get callJoinedEvent$() {
|
|
14612
14619
|
return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$20.filter)(isCallJoinedPayload), (0, import_cjs$20.tap)((event) => {
|
|
14613
|
-
logger$
|
|
14620
|
+
logger$22.debug("[CallEventsManager] Call joined event:", event);
|
|
14614
14621
|
})));
|
|
14615
14622
|
}
|
|
14616
14623
|
get layoutChangedEvent$() {
|
|
14617
14624
|
return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$20.tap)((event) => {
|
|
14618
|
-
logger$
|
|
14625
|
+
logger$22.debug("[CallEventsManager] Layout changed event:", event);
|
|
14619
14626
|
})));
|
|
14620
14627
|
}
|
|
14621
14628
|
get memberUpdates$() {
|
|
14622
14629
|
return this.cachedObservable("memberUpdates$", () => (0, import_cjs$20.merge)(this.webRtcCallSession.memberJoined$, this.webRtcCallSession.memberUpdated$, this.webRtcCallSession.memberTalking$).pipe((0, import_cjs$20.map)((event) => event.member), (0, import_cjs$20.tap)((event) => {
|
|
14623
|
-
logger$
|
|
14630
|
+
logger$22.debug("[CallEventsManager] Member update event:", event);
|
|
14624
14631
|
})));
|
|
14625
14632
|
}
|
|
14626
14633
|
destroy() {
|
|
@@ -14877,7 +14884,7 @@ function appendStereoParams(fmtpLine, maxBitrate) {
|
|
|
14877
14884
|
//#endregion
|
|
14878
14885
|
//#region src/controllers/ICEGatheringController.ts
|
|
14879
14886
|
var import_cjs$19 = require_cjs();
|
|
14880
|
-
const logger$
|
|
14887
|
+
const logger$21 = getLogger();
|
|
14881
14888
|
var ICEGatheringController = class extends Destroyable {
|
|
14882
14889
|
constructor(peerConnection, peerConnectionControllerNegotiating$, options = {}) {
|
|
14883
14890
|
super();
|
|
@@ -14885,23 +14892,23 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14885
14892
|
this.peerConnectionControllerNegotiating$ = peerConnectionControllerNegotiating$;
|
|
14886
14893
|
this.onicegatheringstatechangeHandler = () => {
|
|
14887
14894
|
const { iceGatheringState } = this.peerConnection;
|
|
14888
|
-
logger$
|
|
14895
|
+
logger$21.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
|
|
14889
14896
|
if (iceGatheringState === "gathering") this._iceCandidatesState.next({
|
|
14890
14897
|
state: "gathering",
|
|
14891
14898
|
validSDP: false
|
|
14892
14899
|
});
|
|
14893
14900
|
};
|
|
14894
14901
|
this.onicecandidateHandler = (event) => {
|
|
14895
|
-
logger$
|
|
14902
|
+
logger$21.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
|
|
14896
14903
|
this.removeTimer("iceCandidateTimer");
|
|
14897
14904
|
if (event.candidate) this.iceCandidateTimer = setTimeout(() => {
|
|
14898
14905
|
if (this.peerConnection.iceGatheringState !== "complete") {
|
|
14899
|
-
logger$
|
|
14906
|
+
logger$21.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
|
|
14900
14907
|
this.handleICECandidateTimeout();
|
|
14901
14908
|
}
|
|
14902
14909
|
}, this.iceCandidateTimeout);
|
|
14903
14910
|
else {
|
|
14904
|
-
logger$
|
|
14911
|
+
logger$21.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
|
|
14905
14912
|
this.removeTimer("iceGatheringTimer");
|
|
14906
14913
|
this.handleICEGatheringComplete();
|
|
14907
14914
|
}
|
|
@@ -14919,7 +14926,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14919
14926
|
this.setupEventListeners();
|
|
14920
14927
|
this.iceGatheringTimer = setTimeout(() => {
|
|
14921
14928
|
if (this.peerConnection.iceGatheringState !== "complete") {
|
|
14922
|
-
logger$
|
|
14929
|
+
logger$21.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
|
|
14923
14930
|
this.handleICEGatheringTimeout();
|
|
14924
14931
|
}
|
|
14925
14932
|
}, this.iceGatheringTimeout);
|
|
@@ -14946,9 +14953,9 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14946
14953
|
this.relayOnly = value;
|
|
14947
14954
|
}
|
|
14948
14955
|
handleICEGatheringComplete() {
|
|
14949
|
-
logger$
|
|
14950
|
-
logger$
|
|
14951
|
-
logger$
|
|
14956
|
+
logger$21.debug("[ICEGatheringController] Handling ICE gathering complete");
|
|
14957
|
+
logger$21.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`);
|
|
14958
|
+
logger$21.debug("[ICEGatheringController] ICE gathering complete");
|
|
14952
14959
|
this._iceCandidatesState.next({
|
|
14953
14960
|
state: "complete",
|
|
14954
14961
|
validSDP: this.hasValidLocalDescriptionSDP
|
|
@@ -14964,21 +14971,21 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14964
14971
|
this.removeTimer("iceGatheringTimer");
|
|
14965
14972
|
const validSDP = this.hasValidLocalDescriptionSDP;
|
|
14966
14973
|
if (validSDP) {
|
|
14967
|
-
logger$
|
|
14974
|
+
logger$21.debug("[ICEGatheringController] Local SDP is valid");
|
|
14968
14975
|
this._iceCandidatesState.next({
|
|
14969
14976
|
state: "timeout",
|
|
14970
14977
|
validSDP
|
|
14971
14978
|
});
|
|
14972
14979
|
this.stopGathering();
|
|
14973
|
-
} else logger$
|
|
14980
|
+
} else logger$21.debug("### ICE gathering timeout\n", this.peerConnection.localDescription?.sdp);
|
|
14974
14981
|
}
|
|
14975
14982
|
handleICECandidateTimeout() {
|
|
14976
14983
|
if (this.iceCandidateTimer) this.removeTimer("iceCandidateTimer");
|
|
14977
|
-
logger$
|
|
14984
|
+
logger$21.warn("[ICEGatheringController] ICE candidate timeout");
|
|
14978
14985
|
const validSDP = this.hasValidLocalDescriptionSDP;
|
|
14979
14986
|
if (!validSDP && !this.relayOnly) this.restartICEGatheringWithRelayOnly();
|
|
14980
14987
|
else {
|
|
14981
|
-
logger$
|
|
14988
|
+
logger$21.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout");
|
|
14982
14989
|
this._iceCandidatesState.next({
|
|
14983
14990
|
state: "timeout",
|
|
14984
14991
|
validSDP
|
|
@@ -14987,7 +14994,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14987
14994
|
}
|
|
14988
14995
|
}
|
|
14989
14996
|
restartICEGatheringWithRelayOnly() {
|
|
14990
|
-
logger$
|
|
14997
|
+
logger$21.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
|
|
14991
14998
|
this.relayOnly = true;
|
|
14992
14999
|
this.peerConnection.setConfiguration({
|
|
14993
15000
|
...this.peerConnection.getConfiguration(),
|
|
@@ -15002,7 +15009,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
15002
15009
|
}
|
|
15003
15010
|
}
|
|
15004
15011
|
clearAllTimers() {
|
|
15005
|
-
logger$
|
|
15012
|
+
logger$21.debug("[ICEGatheringController] Clearing all timers");
|
|
15006
15013
|
this.removeTimer("iceGatheringTimer");
|
|
15007
15014
|
this.removeTimer("iceCandidateTimer");
|
|
15008
15015
|
}
|
|
@@ -15011,7 +15018,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
15011
15018
|
this.peerConnection.removeEventListener("icecandidate", this.onicecandidateHandler);
|
|
15012
15019
|
}
|
|
15013
15020
|
destroy() {
|
|
15014
|
-
logger$
|
|
15021
|
+
logger$21.debug("[ICEGatheringController] Destroying ICEGatheringController");
|
|
15015
15022
|
this.clearAllTimers();
|
|
15016
15023
|
this.removeEventListeners();
|
|
15017
15024
|
super.destroy();
|
|
@@ -15021,7 +15028,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
15021
15028
|
//#endregion
|
|
15022
15029
|
//#region src/controllers/LocalAudioPipeline.ts
|
|
15023
15030
|
var import_cjs$18 = require_cjs();
|
|
15024
|
-
const logger$
|
|
15031
|
+
const logger$20 = getLogger();
|
|
15025
15032
|
/**
|
|
15026
15033
|
* Web Audio pipeline for the local microphone stream.
|
|
15027
15034
|
*
|
|
@@ -15133,7 +15140,7 @@ var LocalAudioPipeline = class extends Destroyable {
|
|
|
15133
15140
|
try {
|
|
15134
15141
|
this._inputSource.disconnect();
|
|
15135
15142
|
} catch (error) {
|
|
15136
|
-
logger$
|
|
15143
|
+
logger$20.debug("[LocalAudioPipeline] input disconnect warning:", error);
|
|
15137
15144
|
}
|
|
15138
15145
|
this._inputSource = null;
|
|
15139
15146
|
}
|
|
@@ -15143,7 +15150,7 @@ var LocalAudioPipeline = class extends Destroyable {
|
|
|
15143
15150
|
this._inputSource = this._audioContext.createMediaStreamSource(this._inputStream);
|
|
15144
15151
|
this._inputSource.connect(this._gainNode);
|
|
15145
15152
|
if (this._audioContext.state === "suspended") this._audioContext.resume().catch((error) => {
|
|
15146
|
-
logger$
|
|
15153
|
+
logger$20.warn("[LocalAudioPipeline] AudioContext resume failed:", error);
|
|
15147
15154
|
});
|
|
15148
15155
|
}
|
|
15149
15156
|
destroy() {
|
|
@@ -15158,7 +15165,7 @@ var LocalAudioPipeline = class extends Destroyable {
|
|
|
15158
15165
|
this._analyser.disconnect();
|
|
15159
15166
|
} catch {}
|
|
15160
15167
|
this._audioContext.close().catch((error) => {
|
|
15161
|
-
logger$
|
|
15168
|
+
logger$20.debug("[LocalAudioPipeline] audio context close warning:", error);
|
|
15162
15169
|
});
|
|
15163
15170
|
super.destroy();
|
|
15164
15171
|
}
|
|
@@ -15185,7 +15192,7 @@ var LocalAudioPipeline = class extends Destroyable {
|
|
|
15185
15192
|
//#endregion
|
|
15186
15193
|
//#region src/controllers/LocalStreamController.ts
|
|
15187
15194
|
var import_cjs$17 = require_cjs();
|
|
15188
|
-
const logger$
|
|
15195
|
+
const logger$19 = getLogger();
|
|
15189
15196
|
var LocalStreamController = class extends Destroyable {
|
|
15190
15197
|
constructor(options) {
|
|
15191
15198
|
super();
|
|
@@ -15223,26 +15230,26 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15223
15230
|
* Build the local media stream based on the provided options.
|
|
15224
15231
|
*/
|
|
15225
15232
|
async buildLocalStream() {
|
|
15226
|
-
logger$
|
|
15233
|
+
logger$19.debug("[LocalStreamController] Building local media stream.");
|
|
15227
15234
|
let stream;
|
|
15228
15235
|
if (this.options.inputAudioStream ?? this.options.inputVideoStream) {
|
|
15229
15236
|
const tracks = [...this.options.inputAudioStream?.getTracks() ?? [], ...this.options.inputVideoStream?.getTracks() ?? []];
|
|
15230
15237
|
stream = new MediaStream(tracks);
|
|
15231
15238
|
} else if (this.options.propose === "screenshare") {
|
|
15232
|
-
logger$
|
|
15239
|
+
logger$19.debug("[LocalStreamController] Requesting display media for screen sharing with audio:", Boolean(this.options.inputAudioDeviceConstraints));
|
|
15233
15240
|
stream = await this.options.getDisplayMedia({
|
|
15234
15241
|
video: true,
|
|
15235
15242
|
audio: Boolean(this.options.inputAudioDeviceConstraints)
|
|
15236
15243
|
});
|
|
15237
|
-
logger$
|
|
15244
|
+
logger$19.debug("[LocalStreamController] Screen share media obtained:", stream);
|
|
15238
15245
|
} else {
|
|
15239
15246
|
const constraints = {
|
|
15240
15247
|
audio: this.options.inputAudioDeviceConstraints,
|
|
15241
15248
|
video: this.options.inputVideoDeviceConstraints
|
|
15242
15249
|
};
|
|
15243
|
-
logger$
|
|
15250
|
+
logger$19.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
|
|
15244
15251
|
stream = await this.options.getUserMedia(constraints);
|
|
15245
|
-
logger$
|
|
15252
|
+
logger$19.debug("[LocalStreamController] User media obtained:", stream);
|
|
15246
15253
|
}
|
|
15247
15254
|
this._localStream$.next(stream);
|
|
15248
15255
|
this._localAudioTracks$.next(stream.getAudioTracks());
|
|
@@ -15261,7 +15268,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15261
15268
|
this._localStream$.next(localStream);
|
|
15262
15269
|
if (track.kind === "video") this._localVideoTracks$.next(localStream.getVideoTracks());
|
|
15263
15270
|
else this._localAudioTracks$.next(localStream.getAudioTracks());
|
|
15264
|
-
logger$
|
|
15271
|
+
logger$19.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
|
|
15265
15272
|
return localStream;
|
|
15266
15273
|
}
|
|
15267
15274
|
/**
|
|
@@ -15273,7 +15280,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15273
15280
|
const stream = this._localStream$.value;
|
|
15274
15281
|
const track = stream?.getTracks().find((t) => t.id === trackId);
|
|
15275
15282
|
if (!track) {
|
|
15276
|
-
logger$
|
|
15283
|
+
logger$19.debug(`[LocalStreamController] track not found: ${trackId}`);
|
|
15277
15284
|
return;
|
|
15278
15285
|
}
|
|
15279
15286
|
track.removeEventListener("ended", this.mediaTrackEndedHandler);
|
|
@@ -15282,7 +15289,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15282
15289
|
this._localStream$.next(stream);
|
|
15283
15290
|
if (track.kind === "video") this._localVideoTracks$.next(stream?.getVideoTracks() ?? []);
|
|
15284
15291
|
else this._localAudioTracks$.next(stream?.getAudioTracks() ?? []);
|
|
15285
|
-
logger$
|
|
15292
|
+
logger$19.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
|
|
15286
15293
|
return track;
|
|
15287
15294
|
}
|
|
15288
15295
|
/**
|
|
@@ -15317,7 +15324,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15317
15324
|
*/
|
|
15318
15325
|
stopAllTracks() {
|
|
15319
15326
|
this._localStream$.value?.getTracks().forEach((track) => {
|
|
15320
|
-
logger$
|
|
15327
|
+
logger$19.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
|
|
15321
15328
|
track.removeEventListener("ended", this.mediaTrackEndedHandler);
|
|
15322
15329
|
track.stop();
|
|
15323
15330
|
});
|
|
@@ -15333,7 +15340,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15333
15340
|
|
|
15334
15341
|
//#endregion
|
|
15335
15342
|
//#region src/controllers/TransceiverController.ts
|
|
15336
|
-
const logger$
|
|
15343
|
+
const logger$18 = getLogger();
|
|
15337
15344
|
const getDirection = (send, recv) => {
|
|
15338
15345
|
if (send && recv) return "sendrecv";
|
|
15339
15346
|
else if (send && !recv) return "sendonly";
|
|
@@ -15441,7 +15448,7 @@ var TransceiverController = class extends Destroyable {
|
|
|
15441
15448
|
sendEncodings: isAudio ? void 0 : this.sendEncodings,
|
|
15442
15449
|
streams: direction === "recvonly" ? void 0 : [localStream]
|
|
15443
15450
|
};
|
|
15444
|
-
logger$
|
|
15451
|
+
logger$18.debug(`[TransceiverController] Setting up transceiver sender for local ${track.kind} track:`, {
|
|
15445
15452
|
transceiver,
|
|
15446
15453
|
transceiverParams
|
|
15447
15454
|
});
|
|
@@ -15449,11 +15456,11 @@ var TransceiverController = class extends Destroyable {
|
|
|
15449
15456
|
await transceiver.sender.replaceTrack(track);
|
|
15450
15457
|
transceiver.direction = transceiverParams.direction;
|
|
15451
15458
|
if (transceiverParams.streams?.some((stream) => Boolean(stream))) {
|
|
15452
|
-
logger$
|
|
15459
|
+
logger$18.debug(`[TransceiverController] Setting streams for transceiver sender for local ${track.kind} track:`, transceiverParams.streams);
|
|
15453
15460
|
transceiver.sender.setStreams(...transceiverParams.streams);
|
|
15454
15461
|
}
|
|
15455
15462
|
} else {
|
|
15456
|
-
logger$
|
|
15463
|
+
logger$18.debug(`[TransceiverController] Adding new transceiver for local ${track.kind} track:`, track.id);
|
|
15457
15464
|
this.peerConnection.addTransceiver(track, transceiverParams);
|
|
15458
15465
|
}
|
|
15459
15466
|
}
|
|
@@ -15467,13 +15474,13 @@ var TransceiverController = class extends Destroyable {
|
|
|
15467
15474
|
if (options.updateTransceiverDirection) transceiver.direction = "inactive";
|
|
15468
15475
|
}
|
|
15469
15476
|
} catch (error) {
|
|
15470
|
-
logger$
|
|
15477
|
+
logger$18.error("[TransceiverController] stopTrackSender error", kind, error);
|
|
15471
15478
|
this.options.onError?.(new MediaTrackError("stopTrackSender", kind, error));
|
|
15472
15479
|
}
|
|
15473
15480
|
}
|
|
15474
15481
|
async restoreTrackSender(kind) {
|
|
15475
15482
|
try {
|
|
15476
|
-
logger$
|
|
15483
|
+
logger$18.debug("[TransceiverController] restoreTrackSender called", kind);
|
|
15477
15484
|
const constraints = {};
|
|
15478
15485
|
const transceivers = this.transceiverByKind(kind);
|
|
15479
15486
|
for (const transceiver of transceivers) {
|
|
@@ -15483,23 +15490,23 @@ var TransceiverController = class extends Destroyable {
|
|
|
15483
15490
|
if (trackKind === "audio" || trackKind === "video") constraints[trackKind] = this.getConstraintsFor(trackKind);
|
|
15484
15491
|
}
|
|
15485
15492
|
}
|
|
15486
|
-
logger$
|
|
15493
|
+
logger$18.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
|
|
15487
15494
|
if (Object.keys(constraints).length === 0) {
|
|
15488
|
-
logger$
|
|
15495
|
+
logger$18.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
|
|
15489
15496
|
return;
|
|
15490
15497
|
}
|
|
15491
15498
|
const newTracks = (await this.options.getUserMedia(constraints)).getTracks();
|
|
15492
|
-
logger$
|
|
15499
|
+
logger$18.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
|
|
15493
15500
|
for (const newTrack of newTracks) {
|
|
15494
15501
|
this.options.localStreamController.addTrack(newTrack);
|
|
15495
15502
|
const trackKind = newTrack.kind;
|
|
15496
15503
|
const transceiverOfKind = this.transceiverByKind(trackKind)[0];
|
|
15497
15504
|
transceiverOfKind.direction = trackKind === "audio" ? this.audioDirection : this.videoDirection;
|
|
15498
|
-
logger$
|
|
15505
|
+
logger$18.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
|
|
15499
15506
|
await transceiverOfKind.sender.replaceTrack(newTrack);
|
|
15500
15507
|
}
|
|
15501
15508
|
} catch (error) {
|
|
15502
|
-
logger$
|
|
15509
|
+
logger$18.error("[TransceiverController] restoreTrackSender error", kind, error);
|
|
15503
15510
|
this.options.onError?.(new MediaTrackError("restoreTrackSender", kind, error));
|
|
15504
15511
|
}
|
|
15505
15512
|
}
|
|
@@ -15540,14 +15547,14 @@ var TransceiverController = class extends Destroyable {
|
|
|
15540
15547
|
};
|
|
15541
15548
|
try {
|
|
15542
15549
|
await track.applyConstraints(constraintsToApply);
|
|
15543
|
-
logger$
|
|
15544
|
-
logger$
|
|
15550
|
+
logger$18.debug(`[TransceiverController] Updated ${kind} sender constraints:`, constraintsToApply);
|
|
15551
|
+
logger$18.debug(`[TransceiverController] Updated ${kind} sender constraints:`, track.getConstraints());
|
|
15545
15552
|
} catch (error) {
|
|
15546
|
-
logger$
|
|
15553
|
+
logger$18.warn(`[TransceiverController] applyConstraints failed for ${kind} track ${track.id}, attempting track replacement fallback:`, error);
|
|
15547
15554
|
try {
|
|
15548
15555
|
await this.replaceTrackFallback(sender, track, kind, constraintsToApply);
|
|
15549
15556
|
} catch (fallbackError) {
|
|
15550
|
-
logger$
|
|
15557
|
+
logger$18.warn(`[TransceiverController] Track replacement fallback also failed for ${kind} track:`, fallbackError);
|
|
15551
15558
|
this.options.onError?.(new MediaTrackError("updateSendersConstraints", kind, fallbackError));
|
|
15552
15559
|
}
|
|
15553
15560
|
}
|
|
@@ -15575,7 +15582,7 @@ var TransceiverController = class extends Destroyable {
|
|
|
15575
15582
|
if (!newTrack) throw new MediaTrackError("replaceTrackFallback", kind, /* @__PURE__ */ new Error("getUserMedia returned no track of the requested kind"));
|
|
15576
15583
|
await sender.replaceTrack(newTrack);
|
|
15577
15584
|
this.options.localStreamController.addTrack(newTrack);
|
|
15578
|
-
logger$
|
|
15585
|
+
logger$18.debug(`[TransceiverController] Track replacement fallback succeeded for ${kind}. New track: ${newTrack.id}`);
|
|
15579
15586
|
}
|
|
15580
15587
|
getMediaDirections() {
|
|
15581
15588
|
if (this.peerConnection.connectionState === "connected") return this.peerConnection.getTransceivers().reduce((acc, transceiver) => {
|
|
@@ -15606,7 +15613,7 @@ var TransceiverController = class extends Destroyable {
|
|
|
15606
15613
|
//#endregion
|
|
15607
15614
|
//#region src/controllers/RTCPeerConnectionController.ts
|
|
15608
15615
|
var import_cjs$16 = require_cjs();
|
|
15609
|
-
const logger$
|
|
15616
|
+
const logger$17 = getLogger();
|
|
15610
15617
|
var RTCPeerConnectionController = class extends Destroyable {
|
|
15611
15618
|
constructor(options = {}, remoteSessionDescription, deviceController) {
|
|
15612
15619
|
super();
|
|
@@ -15622,43 +15629,43 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15622
15629
|
this.oniceconnectionstatechangeHandler = () => {
|
|
15623
15630
|
if (this.peerConnection) {
|
|
15624
15631
|
const { iceConnectionState } = this.peerConnection;
|
|
15625
|
-
logger$
|
|
15632
|
+
logger$17.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
|
|
15626
15633
|
this._iceConnectionState$.next(this.peerConnection.iceConnectionState);
|
|
15627
15634
|
}
|
|
15628
15635
|
};
|
|
15629
15636
|
this.onconnectionstatechangeHandler = () => {
|
|
15630
15637
|
if (this.peerConnection) {
|
|
15631
15638
|
const { connectionState } = this.peerConnection;
|
|
15632
|
-
logger$
|
|
15639
|
+
logger$17.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
|
|
15633
15640
|
if (connectionState === "connected") this.removeConnectionTimer();
|
|
15634
15641
|
this._connectionState$.next(this.peerConnection.connectionState);
|
|
15635
15642
|
}
|
|
15636
15643
|
};
|
|
15637
15644
|
this.onsignalingstatechangeHandler = () => {
|
|
15638
|
-
logger$
|
|
15645
|
+
logger$17.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
|
|
15639
15646
|
};
|
|
15640
15647
|
this.onicegatheringstatechangeHandler = () => {
|
|
15641
15648
|
if (this.peerConnection) this._iceGatheringState$.next(this.peerConnection.iceGatheringState);
|
|
15642
15649
|
};
|
|
15643
15650
|
this.onnegotiationneededHandler = (event) => {
|
|
15644
|
-
logger$
|
|
15651
|
+
logger$17.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
|
|
15645
15652
|
this.negotiationNeeded$.next();
|
|
15646
15653
|
};
|
|
15647
15654
|
this.updateSelectedInputDevice = async (kind, deviceInfo) => {
|
|
15648
15655
|
try {
|
|
15649
15656
|
const { localStream } = this;
|
|
15650
15657
|
if (!localStream) {
|
|
15651
|
-
logger$
|
|
15658
|
+
logger$17.warn("[RTCPeerConnectionController] No local stream available to update input device.");
|
|
15652
15659
|
return;
|
|
15653
15660
|
}
|
|
15654
|
-
logger$
|
|
15661
|
+
logger$17.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
|
|
15655
15662
|
const track = localStream.getTracks().find((track$1) => track$1.kind === kind);
|
|
15656
15663
|
if (track) {
|
|
15657
15664
|
this.transceiverController?.stopTrackSender(kind);
|
|
15658
15665
|
this.localStreamController.removeTrack(track.id);
|
|
15659
|
-
logger$
|
|
15666
|
+
logger$17.debug(`[RTCPeerConnectionController] Stopped existing ${kind} track: ${track.id}`, localStream.getTracks());
|
|
15660
15667
|
if (!deviceInfo) {
|
|
15661
|
-
logger$
|
|
15668
|
+
logger$17.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
|
|
15662
15669
|
return;
|
|
15663
15670
|
}
|
|
15664
15671
|
const streamTrack = (await this.getUserMedia({ [kind]: {
|
|
@@ -15666,15 +15673,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15666
15673
|
...this.deviceController.deviceInfoToConstraints(deviceInfo)
|
|
15667
15674
|
} })).getTracks().find((t) => t.kind === kind);
|
|
15668
15675
|
if (streamTrack) {
|
|
15669
|
-
logger$
|
|
15676
|
+
logger$17.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
|
|
15670
15677
|
this.localStreamController.addTrack(streamTrack);
|
|
15671
15678
|
await this.transceiverController?.replaceSenderTrack(kind, streamTrack);
|
|
15672
|
-
logger$
|
|
15679
|
+
logger$17.debug(`[RTCPeerConnectionController] Added new ${kind} track: ${streamTrack.id}`, this.localStream?.getTracks());
|
|
15673
15680
|
}
|
|
15674
15681
|
}
|
|
15675
|
-
logger$
|
|
15682
|
+
logger$17.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
|
|
15676
15683
|
} catch (error) {
|
|
15677
|
-
logger$
|
|
15684
|
+
logger$17.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
|
|
15678
15685
|
this._errors$.next(toError(error));
|
|
15679
15686
|
throw error;
|
|
15680
15687
|
}
|
|
@@ -15924,15 +15931,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15924
15931
|
this.setupPeerConnection();
|
|
15925
15932
|
this.subscribeTo(this.negotiationNeeded$.pipe((0, import_cjs$16.auditTime)(0), (0, import_cjs$16.exhaustMap)(async () => this.startNegotiation())), {
|
|
15926
15933
|
next: () => {
|
|
15927
|
-
logger$
|
|
15934
|
+
logger$17.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
|
|
15928
15935
|
},
|
|
15929
15936
|
error: (error) => {
|
|
15930
|
-
logger$
|
|
15937
|
+
logger$17.error("[RTCPeerConnectionController] Start Negotiation error:", error);
|
|
15931
15938
|
this._errors$.next(toError(error));
|
|
15932
15939
|
}
|
|
15933
15940
|
});
|
|
15934
15941
|
this.subscribeTo((0, import_cjs$16.merge)(this.deviceController.selectedAudioInputDevice$.pipe((0, import_cjs$16.map)((deviceInfo) => ["audio", deviceInfo])), this.deviceController.selectedVideoInputDevice$.pipe((0, import_cjs$16.map)((deviceInfo) => ["video", deviceInfo]))).pipe((0, import_cjs$16.skipWhile)(() => !this.localStreamController.localStream)), async ([kind, deviceInfo]) => {
|
|
15935
|
-
logger$
|
|
15942
|
+
logger$17.debug(`[RTCPeerConnectionController] Selected input device changed for:`, {
|
|
15936
15943
|
kind,
|
|
15937
15944
|
deviceInfo
|
|
15938
15945
|
});
|
|
@@ -15949,7 +15956,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15949
15956
|
this._initialized$.next(true);
|
|
15950
15957
|
}
|
|
15951
15958
|
} catch (error) {
|
|
15952
|
-
logger$
|
|
15959
|
+
logger$17.error("[RTCPeerConnectionController] Initialization error:", error);
|
|
15953
15960
|
this._errors$.next(toError(error));
|
|
15954
15961
|
this.destroy();
|
|
15955
15962
|
}
|
|
@@ -15981,22 +15988,22 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15981
15988
|
}
|
|
15982
15989
|
async startNegotiation() {
|
|
15983
15990
|
if (this.isNegotiating) {
|
|
15984
|
-
logger$
|
|
15991
|
+
logger$17.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
|
|
15985
15992
|
return;
|
|
15986
15993
|
}
|
|
15987
15994
|
this.setupEventListeners();
|
|
15988
15995
|
if (this.type === "answer") {
|
|
15989
|
-
logger$
|
|
15996
|
+
logger$17.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");
|
|
15990
15997
|
return;
|
|
15991
15998
|
}
|
|
15992
15999
|
this._isNegotiating$.next(true);
|
|
15993
|
-
logger$
|
|
16000
|
+
logger$17.debug("[RTCPeerConnectionController] Starting negotiation.");
|
|
15994
16001
|
try {
|
|
15995
16002
|
const { offerOptions } = this;
|
|
15996
|
-
logger$
|
|
16003
|
+
logger$17.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
|
|
15997
16004
|
await this.createOffer(offerOptions);
|
|
15998
16005
|
} catch (error) {
|
|
15999
|
-
logger$
|
|
16006
|
+
logger$17.error("[RTCPeerConnectionController] Error during negotiation:", error);
|
|
16000
16007
|
this._errors$.next(toError(error));
|
|
16001
16008
|
}
|
|
16002
16009
|
}
|
|
@@ -16012,14 +16019,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16012
16019
|
let readyToConnect = status !== "failed";
|
|
16013
16020
|
try {
|
|
16014
16021
|
if (status === "received" && sdp) {
|
|
16015
|
-
logger$
|
|
16022
|
+
logger$17.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
|
|
16016
16023
|
await this._setRemoteDescription({
|
|
16017
16024
|
type: "answer",
|
|
16018
16025
|
sdp
|
|
16019
16026
|
});
|
|
16020
16027
|
}
|
|
16021
16028
|
} catch (error) {
|
|
16022
|
-
logger$
|
|
16029
|
+
logger$17.error("[RTCPeerConnectionController] Error updating answer status:", error);
|
|
16023
16030
|
this._errors$.next(toError(error));
|
|
16024
16031
|
readyToConnect = false;
|
|
16025
16032
|
} finally {
|
|
@@ -16038,7 +16045,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16038
16045
|
await this.handleOfferReceived();
|
|
16039
16046
|
break;
|
|
16040
16047
|
case "failed":
|
|
16041
|
-
logger$
|
|
16048
|
+
logger$17.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
|
|
16042
16049
|
break;
|
|
16043
16050
|
case "sent":
|
|
16044
16051
|
default:
|
|
@@ -16070,7 +16077,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16070
16077
|
}
|
|
16071
16078
|
await this.setupLocalTracks();
|
|
16072
16079
|
const { answerOptions } = this;
|
|
16073
|
-
logger$
|
|
16080
|
+
logger$17.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
|
|
16074
16081
|
await this.createAnswer(answerOptions);
|
|
16075
16082
|
}
|
|
16076
16083
|
async handleOfferReceived() {
|
|
@@ -16078,7 +16085,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16078
16085
|
this._isNegotiating$.next(true);
|
|
16079
16086
|
await this._setRemoteDescription(this.sdpInit);
|
|
16080
16087
|
const { answerOptions } = this;
|
|
16081
|
-
logger$
|
|
16088
|
+
logger$17.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
|
|
16082
16089
|
await this.createAnswer(answerOptions);
|
|
16083
16090
|
}
|
|
16084
16091
|
readyToConnect() {
|
|
@@ -16086,7 +16093,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16086
16093
|
this.connectionTimer = setTimeout(() => {
|
|
16087
16094
|
this.removeConnectionTimer();
|
|
16088
16095
|
if (this.peerConnection?.connectionState !== "connected") {
|
|
16089
|
-
logger$
|
|
16096
|
+
logger$17.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only.");
|
|
16090
16097
|
this.iceGatheringController.restartICEGatheringWithRelayOnly();
|
|
16091
16098
|
}
|
|
16092
16099
|
}, this.connectionTimeout);
|
|
@@ -16108,14 +16115,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16108
16115
|
const stereo = this.options.stereo ?? PreferencesContainer.instance.stereoAudio;
|
|
16109
16116
|
if (preferredAudioCodecs.length > 0 || preferredVideoCodecs.length > 0) {
|
|
16110
16117
|
result = setCodecPreferences(result, preferredAudioCodecs, preferredVideoCodecs);
|
|
16111
|
-
logger$
|
|
16118
|
+
logger$17.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
|
|
16112
16119
|
preferredAudioCodecs,
|
|
16113
16120
|
preferredVideoCodecs
|
|
16114
16121
|
});
|
|
16115
16122
|
}
|
|
16116
16123
|
if (stereo) {
|
|
16117
16124
|
result = enableStereoOpus(result);
|
|
16118
|
-
logger$
|
|
16125
|
+
logger$17.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP");
|
|
16119
16126
|
}
|
|
16120
16127
|
return Promise.resolve(result);
|
|
16121
16128
|
}
|
|
@@ -16171,25 +16178,25 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16171
16178
|
...this.peerConnection.getConfiguration(),
|
|
16172
16179
|
iceTransportPolicy: "relay"
|
|
16173
16180
|
});
|
|
16174
|
-
logger$
|
|
16181
|
+
logger$17.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only");
|
|
16175
16182
|
} catch (error) {
|
|
16176
|
-
logger$
|
|
16183
|
+
logger$17.warn("[RTCPeerConnectionController] Failed to set relay-only policy:", error);
|
|
16177
16184
|
}
|
|
16178
16185
|
this.setupEventListeners();
|
|
16179
16186
|
this._isNegotiating$.next(true);
|
|
16180
|
-
logger$
|
|
16187
|
+
logger$17.debug(`[RTCPeerConnectionController] Triggering ICE restart${relayOnly ? " (relay-only)" : ""}.`);
|
|
16181
16188
|
try {
|
|
16182
16189
|
const offer = await this.peerConnection.createOffer({ iceRestart: true });
|
|
16183
16190
|
await this.setLocalDescription(offer);
|
|
16184
16191
|
} catch (error) {
|
|
16185
|
-
logger$
|
|
16192
|
+
logger$17.error("[RTCPeerConnectionController] ICE restart offer failed:", error);
|
|
16186
16193
|
this._errors$.next(toError(error));
|
|
16187
16194
|
this.negotiationEnded();
|
|
16188
16195
|
if (policyChanged) this.restoreIceTransportPolicy();
|
|
16189
16196
|
throw error;
|
|
16190
16197
|
}
|
|
16191
16198
|
if (policyChanged) (0, import_cjs$16.firstValueFrom)((0, import_cjs$16.race)(this._iceGatheringState$.pipe((0, import_cjs$16.filter)((state) => state === "complete"), (0, import_cjs$16.take)(1)), (0, import_cjs$16.timer)(ICE_GATHERING_COMPLETE_TIMEOUT_MS).pipe((0, import_cjs$16.map)(() => "timeout")))).then(() => this.restoreIceTransportPolicy()).catch((error) => {
|
|
16192
|
-
logger$
|
|
16199
|
+
logger$17.warn("[RTCPeerConnectionController] Error waiting for ICE gathering to complete:", error);
|
|
16193
16200
|
this.restoreIceTransportPolicy();
|
|
16194
16201
|
});
|
|
16195
16202
|
}
|
|
@@ -16199,9 +16206,9 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16199
16206
|
...this.peerConnection.getConfiguration(),
|
|
16200
16207
|
iceTransportPolicy: this.options.relayOnly ? "relay" : "all"
|
|
16201
16208
|
});
|
|
16202
|
-
logger$
|
|
16209
|
+
logger$17.debug("[RTCPeerConnectionController] ICE transport policy restored");
|
|
16203
16210
|
} catch (error) {
|
|
16204
|
-
logger$
|
|
16211
|
+
logger$17.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:", error);
|
|
16205
16212
|
}
|
|
16206
16213
|
}
|
|
16207
16214
|
/**
|
|
@@ -16213,13 +16220,13 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16213
16220
|
await this.setupRemoteTracks();
|
|
16214
16221
|
}
|
|
16215
16222
|
async setupLocalTracks() {
|
|
16216
|
-
logger$
|
|
16223
|
+
logger$17.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
16217
16224
|
const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
16218
16225
|
if (this.transceiverController?.useAddStream ?? false) {
|
|
16219
|
-
logger$
|
|
16226
|
+
logger$17.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
16220
16227
|
this.peerConnection?.addStream(localStream);
|
|
16221
16228
|
if (!this.isNegotiating) {
|
|
16222
|
-
logger$
|
|
16229
|
+
logger$17.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
16223
16230
|
this.negotiationNeeded$.next();
|
|
16224
16231
|
}
|
|
16225
16232
|
return;
|
|
@@ -16235,7 +16242,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16235
16242
|
const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
|
|
16236
16243
|
await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
|
|
16237
16244
|
} else {
|
|
16238
|
-
logger$
|
|
16245
|
+
logger$17.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
|
|
16239
16246
|
this.peerConnection?.addTrack(track, localStream);
|
|
16240
16247
|
}
|
|
16241
16248
|
}
|
|
@@ -16252,7 +16259,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16252
16259
|
async setupRemoteTracks() {
|
|
16253
16260
|
if (!this.peerConnection) throw new DependencyError("RTCPeerConnection is not initialized");
|
|
16254
16261
|
this.peerConnection.ontrack = (event) => {
|
|
16255
|
-
logger$
|
|
16262
|
+
logger$17.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
|
|
16256
16263
|
if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
|
|
16257
16264
|
else {
|
|
16258
16265
|
const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
|
|
@@ -16276,7 +16283,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16276
16283
|
try {
|
|
16277
16284
|
stream = await this.getUserMedia({ audio: constraints });
|
|
16278
16285
|
} catch (error) {
|
|
16279
|
-
logger$
|
|
16286
|
+
logger$17.error("[RTCPeerConnectionController] Failed to re-acquire mic for pipeline restore:", error);
|
|
16280
16287
|
this._errors$.next(toError(error));
|
|
16281
16288
|
return;
|
|
16282
16289
|
}
|
|
@@ -16298,7 +16305,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16298
16305
|
try {
|
|
16299
16306
|
this._localAudioPipeline = new LocalAudioPipeline();
|
|
16300
16307
|
} catch (error) {
|
|
16301
|
-
logger$
|
|
16308
|
+
logger$17.warn("[RTCPeerConnectionController] Failed to create LocalAudioPipeline:", error);
|
|
16302
16309
|
return null;
|
|
16303
16310
|
}
|
|
16304
16311
|
this.subscribeTo(this.localStreamController.localAudioTracks$, () => {
|
|
@@ -16320,7 +16327,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16320
16327
|
try {
|
|
16321
16328
|
await sender.replaceTrack(this._localAudioPipeline.outputTrack);
|
|
16322
16329
|
} catch (error) {
|
|
16323
|
-
logger$
|
|
16330
|
+
logger$17.warn("[RTCPeerConnectionController] Failed to route audio sender through pipeline:", error);
|
|
16324
16331
|
}
|
|
16325
16332
|
}
|
|
16326
16333
|
/**
|
|
@@ -16336,9 +16343,9 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16336
16343
|
try {
|
|
16337
16344
|
const localStream = this.localStreamController.addTrack(track);
|
|
16338
16345
|
this.peerConnection.addTrack(track, localStream);
|
|
16339
|
-
logger$
|
|
16346
|
+
logger$17.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
|
|
16340
16347
|
} catch (error) {
|
|
16341
|
-
logger$
|
|
16348
|
+
logger$17.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
|
|
16342
16349
|
this._errors$.next(toError(error));
|
|
16343
16350
|
throw error;
|
|
16344
16351
|
}
|
|
@@ -16355,15 +16362,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16355
16362
|
}
|
|
16356
16363
|
const sender = this.peerConnection.getSenders().find((sender$1) => sender$1.track?.id === trackId);
|
|
16357
16364
|
if (!sender) {
|
|
16358
|
-
logger$
|
|
16365
|
+
logger$17.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
|
|
16359
16366
|
return;
|
|
16360
16367
|
}
|
|
16361
16368
|
try {
|
|
16362
16369
|
this.peerConnection.removeTrack(sender);
|
|
16363
16370
|
this.localStreamController.removeTrack(trackId);
|
|
16364
|
-
logger$
|
|
16371
|
+
logger$17.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
|
|
16365
16372
|
} catch (error) {
|
|
16366
|
-
logger$
|
|
16373
|
+
logger$17.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
|
|
16367
16374
|
this._errors$.next(toError(error));
|
|
16368
16375
|
throw error;
|
|
16369
16376
|
}
|
|
@@ -16390,7 +16397,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16390
16397
|
async replaceAudioTrackWithConstraints(constraints) {
|
|
16391
16398
|
const senders = this.peerConnection?.getSenders().filter((s) => s.track?.kind === "audio" && s.track.readyState === "live");
|
|
16392
16399
|
if (!senders || senders.length === 0) {
|
|
16393
|
-
logger$
|
|
16400
|
+
logger$17.warn("[RTCPeerConnectionController] No live audio sender to replace");
|
|
16394
16401
|
return;
|
|
16395
16402
|
}
|
|
16396
16403
|
for (const sender of senders) {
|
|
@@ -16408,7 +16415,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16408
16415
|
const newTrack = (await this.getUserMedia({ audio: mergedConstraints })).getAudioTracks()[0];
|
|
16409
16416
|
await sender.replaceTrack(newTrack);
|
|
16410
16417
|
this.localStreamController.addTrack(newTrack);
|
|
16411
|
-
logger$
|
|
16418
|
+
logger$17.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
|
|
16412
16419
|
}
|
|
16413
16420
|
}
|
|
16414
16421
|
/**
|
|
@@ -16416,7 +16423,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16416
16423
|
* Completes all observables to prevent memory leaks.
|
|
16417
16424
|
*/
|
|
16418
16425
|
destroy() {
|
|
16419
|
-
logger$
|
|
16426
|
+
logger$17.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
|
|
16420
16427
|
this.removeConnectionTimer();
|
|
16421
16428
|
this._iceGatheringController?.destroy();
|
|
16422
16429
|
this._localAudioPipeline?.destroy();
|
|
@@ -16442,7 +16449,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16442
16449
|
}
|
|
16443
16450
|
stopRemoteTracks() {
|
|
16444
16451
|
this._remoteStream$.value?.getTracks().forEach((track) => {
|
|
16445
|
-
logger$
|
|
16452
|
+
logger$17.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
|
|
16446
16453
|
track.stop();
|
|
16447
16454
|
});
|
|
16448
16455
|
}
|
|
@@ -16459,7 +16466,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16459
16466
|
...params,
|
|
16460
16467
|
sdp: finalRemote
|
|
16461
16468
|
};
|
|
16462
|
-
logger$
|
|
16469
|
+
logger$17.debug("[RTCPeerConnectionController] Setting remote description:", answer);
|
|
16463
16470
|
return this.peerConnection.setRemoteDescription(answer);
|
|
16464
16471
|
}
|
|
16465
16472
|
};
|
|
@@ -16498,7 +16505,7 @@ function isVertoPingInnerParams(value) {
|
|
|
16498
16505
|
//#endregion
|
|
16499
16506
|
//#region src/managers/VertoManager.ts
|
|
16500
16507
|
var import_cjs$15 = require_cjs();
|
|
16501
|
-
const logger$
|
|
16508
|
+
const logger$16 = getLogger();
|
|
16502
16509
|
/**
|
|
16503
16510
|
* Decide what value goes on the `node_id` field of a `webrtc.verto` envelope.
|
|
16504
16511
|
*
|
|
@@ -16554,7 +16561,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16554
16561
|
try {
|
|
16555
16562
|
await this.executeVerto(vertoModifyMessage);
|
|
16556
16563
|
} catch (error) {
|
|
16557
|
-
logger$
|
|
16564
|
+
logger$16.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:", error);
|
|
16558
16565
|
throw error;
|
|
16559
16566
|
}
|
|
16560
16567
|
}
|
|
@@ -16567,7 +16574,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16567
16574
|
try {
|
|
16568
16575
|
await this.executeVerto(vertoModifyMessage);
|
|
16569
16576
|
} catch (error) {
|
|
16570
|
-
logger$
|
|
16577
|
+
logger$16.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:", error);
|
|
16571
16578
|
throw error;
|
|
16572
16579
|
}
|
|
16573
16580
|
}
|
|
@@ -16620,7 +16627,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16620
16627
|
if (event.member_id) this.setSelfIdIfNull(event.member_id);
|
|
16621
16628
|
});
|
|
16622
16629
|
this.subscribeTo(this.vertoMedia$, (event) => {
|
|
16623
|
-
logger$
|
|
16630
|
+
logger$16.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
|
|
16624
16631
|
const { sdp, callID } = event;
|
|
16625
16632
|
this.emitMainSignalingStatus(callID, "ringing");
|
|
16626
16633
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
@@ -16629,7 +16636,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16629
16636
|
});
|
|
16630
16637
|
});
|
|
16631
16638
|
this.subscribeTo(this.vertoAnswer$, (event) => {
|
|
16632
|
-
logger$
|
|
16639
|
+
logger$16.debug("[WebRTCManager] Received Verto answer event:", event);
|
|
16633
16640
|
const { sdp, callID } = event;
|
|
16634
16641
|
this.emitMainSignalingStatus(callID, "connecting");
|
|
16635
16642
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
@@ -16638,7 +16645,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16638
16645
|
});
|
|
16639
16646
|
});
|
|
16640
16647
|
this.subscribeTo(this.vertoMediaParams$, (event) => {
|
|
16641
|
-
logger$
|
|
16648
|
+
logger$16.debug("[WebRTCManager] Received Verto mediaParams event:", event);
|
|
16642
16649
|
const { mediaParams, callID } = event;
|
|
16643
16650
|
const rtcPeerConnController = this._rtcPeerConnectionsMap.get(callID);
|
|
16644
16651
|
const { audio, video } = mediaParams;
|
|
@@ -16652,7 +16659,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16652
16659
|
timestamp: Date.now()
|
|
16653
16660
|
});
|
|
16654
16661
|
} catch (error) {
|
|
16655
|
-
logger$
|
|
16662
|
+
logger$16.warn("[WebRTCManager] Error applying server-pushed media params:", error);
|
|
16656
16663
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16657
16664
|
}
|
|
16658
16665
|
})();
|
|
@@ -16674,13 +16681,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16674
16681
|
*/
|
|
16675
16682
|
setNodeIdIfNull(nodeId) {
|
|
16676
16683
|
if (!this._nodeId$.value && nodeId) {
|
|
16677
|
-
logger$
|
|
16684
|
+
logger$16.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
|
|
16678
16685
|
this._nodeId$.next(nodeId);
|
|
16679
16686
|
}
|
|
16680
16687
|
}
|
|
16681
16688
|
setSelfIdIfNull(selfId) {
|
|
16682
16689
|
if (!this._selfId$.value && selfId) {
|
|
16683
|
-
logger$
|
|
16690
|
+
logger$16.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
|
|
16684
16691
|
this._selfId$.next(selfId);
|
|
16685
16692
|
}
|
|
16686
16693
|
}
|
|
@@ -16689,7 +16696,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16689
16696
|
const vertoPongMessage = VertoPong({ ...vertoPing });
|
|
16690
16697
|
await this.executeVerto(vertoPongMessage);
|
|
16691
16698
|
} catch (error) {
|
|
16692
|
-
logger$
|
|
16699
|
+
logger$16.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:", error);
|
|
16693
16700
|
this.onError?.(new VertoPongError(error));
|
|
16694
16701
|
}
|
|
16695
16702
|
}
|
|
@@ -16699,7 +16706,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16699
16706
|
if (audio) await this.mainPeerConnection.updateSendersConstraints("audio", audio);
|
|
16700
16707
|
if (video) await this.mainPeerConnection.updateSendersConstraints("video", video);
|
|
16701
16708
|
} catch (error) {
|
|
16702
|
-
logger$
|
|
16709
|
+
logger$16.warn("[WebRTCManager] Error updating media constraints:", error);
|
|
16703
16710
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16704
16711
|
throw error;
|
|
16705
16712
|
}
|
|
@@ -16729,20 +16736,20 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16729
16736
|
try {
|
|
16730
16737
|
const pc = this.mainPeerConnection.peerConnection;
|
|
16731
16738
|
if (!pc) {
|
|
16732
|
-
logger$
|
|
16739
|
+
logger$16.warn("[WebRTCManager] No peer connection for keyframe request");
|
|
16733
16740
|
return;
|
|
16734
16741
|
}
|
|
16735
16742
|
const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
|
|
16736
16743
|
if (!videoReceiver) {
|
|
16737
|
-
logger$
|
|
16744
|
+
logger$16.warn("[WebRTCManager] No video receiver for keyframe request");
|
|
16738
16745
|
return;
|
|
16739
16746
|
}
|
|
16740
16747
|
if (typeof videoReceiver.requestKeyFrame === "function") {
|
|
16741
16748
|
videoReceiver.requestKeyFrame();
|
|
16742
|
-
logger$
|
|
16743
|
-
} else logger$
|
|
16749
|
+
logger$16.debug("[WebRTCManager] Keyframe requested via RTCRtpReceiver.requestKeyFrame()");
|
|
16750
|
+
} else logger$16.debug("[WebRTCManager] requestKeyFrame() not supported, skipping");
|
|
16744
16751
|
} catch (error) {
|
|
16745
|
-
logger$
|
|
16752
|
+
logger$16.warn("[WebRTCManager] Keyframe request failed (non-fatal):", error);
|
|
16746
16753
|
}
|
|
16747
16754
|
}
|
|
16748
16755
|
/**
|
|
@@ -16760,13 +16767,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16760
16767
|
try {
|
|
16761
16768
|
const controller = this.mainPeerConnection;
|
|
16762
16769
|
if (!controller.peerConnection) {
|
|
16763
|
-
logger$
|
|
16770
|
+
logger$16.warn("[WebRTCManager] No peer connection for ICE restart");
|
|
16764
16771
|
return;
|
|
16765
16772
|
}
|
|
16766
16773
|
await controller.triggerIceRestart(relayOnly);
|
|
16767
|
-
logger$
|
|
16774
|
+
logger$16.info(`[WebRTCManager] ICE restart initiated${relayOnly ? " (relay-only)" : ""}`);
|
|
16768
16775
|
} catch (error) {
|
|
16769
|
-
logger$
|
|
16776
|
+
logger$16.error("[WebRTCManager] ICE restart failed:", error);
|
|
16770
16777
|
throw error;
|
|
16771
16778
|
}
|
|
16772
16779
|
}
|
|
@@ -16784,13 +16791,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16784
16791
|
const entries = Array.from(this._rtcPeerConnectionsMap.entries());
|
|
16785
16792
|
for (const [id, controller] of entries) try {
|
|
16786
16793
|
if (!controller.peerConnection) {
|
|
16787
|
-
logger$
|
|
16794
|
+
logger$16.debug(`[WebRTCManager] No peer connection for leg ${id}, skipping ICE restart`);
|
|
16788
16795
|
continue;
|
|
16789
16796
|
}
|
|
16790
16797
|
await controller.triggerIceRestart(relayOnly);
|
|
16791
|
-
logger$
|
|
16798
|
+
logger$16.info(`[WebRTCManager] ICE restart initiated for leg ${id}${relayOnly ? " (relay-only)" : ""}`);
|
|
16792
16799
|
} catch (error) {
|
|
16793
|
-
logger$
|
|
16800
|
+
logger$16.warn(`[WebRTCManager] ICE restart failed for leg ${id}:`, error);
|
|
16794
16801
|
}
|
|
16795
16802
|
}
|
|
16796
16803
|
/**
|
|
@@ -16802,7 +16809,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16802
16809
|
requestKeyframeAll() {
|
|
16803
16810
|
for (const [id, controller] of this._rtcPeerConnectionsMap) {
|
|
16804
16811
|
if (controller.isScreenShare) {
|
|
16805
|
-
logger$
|
|
16812
|
+
logger$16.debug(`[WebRTCManager] Skipping keyframe for send-only screen share leg ${id}`);
|
|
16806
16813
|
continue;
|
|
16807
16814
|
}
|
|
16808
16815
|
try {
|
|
@@ -16812,10 +16819,10 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16812
16819
|
if (!videoReceiver) continue;
|
|
16813
16820
|
if (typeof videoReceiver.requestKeyFrame === "function") {
|
|
16814
16821
|
videoReceiver.requestKeyFrame();
|
|
16815
|
-
logger$
|
|
16822
|
+
logger$16.debug(`[WebRTCManager] Keyframe requested for leg ${id}`);
|
|
16816
16823
|
}
|
|
16817
16824
|
} catch (error) {
|
|
16818
|
-
logger$
|
|
16825
|
+
logger$16.warn(`[WebRTCManager] Keyframe request failed for leg ${id} (non-fatal):`, error);
|
|
16819
16826
|
}
|
|
16820
16827
|
}
|
|
16821
16828
|
}
|
|
@@ -16876,7 +16883,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16876
16883
|
default:
|
|
16877
16884
|
}
|
|
16878
16885
|
} catch (error) {
|
|
16879
|
-
logger$
|
|
16886
|
+
logger$16.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
|
|
16880
16887
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16881
16888
|
if (vertoMethod === "verto.modify") this.onModifyFailed?.();
|
|
16882
16889
|
}
|
|
@@ -16891,7 +16898,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16891
16898
|
sdp
|
|
16892
16899
|
});
|
|
16893
16900
|
} catch (error) {
|
|
16894
|
-
logger$
|
|
16901
|
+
logger$16.warn("[WebRTCManager] Error processing modify response:", error);
|
|
16895
16902
|
const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
16896
16903
|
this.onError?.(modifyError);
|
|
16897
16904
|
}
|
|
@@ -16901,7 +16908,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16901
16908
|
const rtcPeerConnController = this._rtcPeerConnectionsMap.get(callId);
|
|
16902
16909
|
if (!rtcPeerConnController) {
|
|
16903
16910
|
const signalingError = new DependencyError(`Cannot emit signaling status, RTCPeerConnectionController not found for callID: ${callId}`);
|
|
16904
|
-
logger$
|
|
16911
|
+
logger$16.error("[WebRTCManager] Failed to emit signaling status:", {
|
|
16905
16912
|
callId,
|
|
16906
16913
|
status,
|
|
16907
16914
|
signalingError
|
|
@@ -16917,7 +16924,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16917
16924
|
this._nodeId$.next(getValueFrom(response, "result.node_id") ?? null);
|
|
16918
16925
|
const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
|
|
16919
16926
|
const callId = getValueFrom(response, "result.result.result.callID") ?? null;
|
|
16920
|
-
logger$
|
|
16927
|
+
logger$16.debug("[WebRTCManager] Verto invite response:", {
|
|
16921
16928
|
callId,
|
|
16922
16929
|
memberId,
|
|
16923
16930
|
response
|
|
@@ -16927,14 +16934,14 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16927
16934
|
if (callId) {
|
|
16928
16935
|
this.webRtcCallSession.addCallId(callId);
|
|
16929
16936
|
this.attachManager.attach(this.buildAttachableCall(callId));
|
|
16930
|
-
} else logger$
|
|
16937
|
+
} else logger$16.warn("[WebRTCManager] Cannot attach call, missing callId:", {
|
|
16931
16938
|
nodeId: this.nodeId,
|
|
16932
16939
|
callId
|
|
16933
16940
|
});
|
|
16934
|
-
logger$
|
|
16935
|
-
logger$
|
|
16941
|
+
logger$16.info("[WebRTCManager] Verto invite successful");
|
|
16942
|
+
logger$16.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
|
|
16936
16943
|
} else {
|
|
16937
|
-
logger$
|
|
16944
|
+
logger$16.error("[WebRTCManager] Verto invite failed:", response);
|
|
16938
16945
|
const inviteError = response.error ? new JSONRPCError(response.error.code, response.error.message, response.error.data) : /* @__PURE__ */ new Error("Verto invite failed: unexpected response");
|
|
16939
16946
|
this.onError?.(inviteError);
|
|
16940
16947
|
}
|
|
@@ -16979,17 +16986,17 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16979
16986
|
if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
|
|
16980
16987
|
}
|
|
16981
16988
|
async handleInboundAnswer(rtcPeerConnController) {
|
|
16982
|
-
logger$
|
|
16989
|
+
logger$16.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
|
|
16983
16990
|
const vertoByeOrAccepted = await (0, import_cjs$15.firstValueFrom)((0, import_cjs$15.race)(this.vertoBye$, this.webRtcCallSession.answered$).pipe((0, import_cjs$15.takeUntil)(this.destroyed$))).catch(() => null);
|
|
16984
16991
|
if (vertoByeOrAccepted === null) {
|
|
16985
|
-
logger$
|
|
16992
|
+
logger$16.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
|
|
16986
16993
|
return;
|
|
16987
16994
|
}
|
|
16988
16995
|
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
16989
|
-
logger$
|
|
16996
|
+
logger$16.info("[WebRTCManager] Inbound call ended by remote before answer.");
|
|
16990
16997
|
this.callSession?.destroy();
|
|
16991
16998
|
} else if (!vertoByeOrAccepted) {
|
|
16992
|
-
logger$
|
|
16999
|
+
logger$16.info("[WebRTCManager] Inbound call rejected by user.");
|
|
16993
17000
|
try {
|
|
16994
17001
|
await this.bye("USER_BUSY");
|
|
16995
17002
|
} finally {
|
|
@@ -16997,19 +17004,19 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16997
17004
|
this.callSession?.destroy();
|
|
16998
17005
|
}
|
|
16999
17006
|
} else {
|
|
17000
|
-
logger$
|
|
17007
|
+
logger$16.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
|
|
17001
17008
|
const answerOptions = this.webRtcCallSession.answerMediaOptions;
|
|
17002
17009
|
try {
|
|
17003
17010
|
await rtcPeerConnController.acceptInbound(answerOptions);
|
|
17004
17011
|
} catch (error) {
|
|
17005
|
-
logger$
|
|
17012
|
+
logger$16.error("[WebRTCManager] Error creating inbound answer:", error);
|
|
17006
17013
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
17007
17014
|
}
|
|
17008
17015
|
}
|
|
17009
17016
|
}
|
|
17010
17017
|
setupVertoAttachHandler() {
|
|
17011
17018
|
this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
|
|
17012
|
-
logger$
|
|
17019
|
+
logger$16.debug("[WebRTCManager] Received Verto attach event for existing call:", vertoAttach);
|
|
17013
17020
|
const { callID } = vertoAttach;
|
|
17014
17021
|
await this.attachManager.attach({
|
|
17015
17022
|
nodeId: this.nodeId ?? void 0,
|
|
@@ -17081,17 +17088,17 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17081
17088
|
};
|
|
17082
17089
|
}
|
|
17083
17090
|
async sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnectionController) {
|
|
17084
|
-
logger$
|
|
17091
|
+
logger$16.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");
|
|
17085
17092
|
const vertoByeOrAccepted = await (0, import_cjs$15.firstValueFrom)((0, import_cjs$15.race)(this.vertoBye$, this.webRtcCallSession.answered$).pipe((0, import_cjs$15.takeUntil)(this.destroyed$))).catch(() => null);
|
|
17086
17093
|
if (vertoByeOrAccepted === null) {
|
|
17087
|
-
logger$
|
|
17094
|
+
logger$16.debug("[WebRTCManager] Destroyed while waiting for call acceptance");
|
|
17088
17095
|
return;
|
|
17089
17096
|
}
|
|
17090
17097
|
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
17091
|
-
logger$
|
|
17098
|
+
logger$16.info("[WebRTCManager] Call ended before answer was sent.");
|
|
17092
17099
|
this.callSession?.destroy();
|
|
17093
17100
|
} else if (!vertoByeOrAccepted) {
|
|
17094
|
-
logger$
|
|
17101
|
+
logger$16.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
|
|
17095
17102
|
try {
|
|
17096
17103
|
await this.bye("USER_BUSY");
|
|
17097
17104
|
} finally {
|
|
@@ -17099,14 +17106,14 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17099
17106
|
this.callSession?.destroy();
|
|
17100
17107
|
}
|
|
17101
17108
|
} else {
|
|
17102
|
-
logger$
|
|
17109
|
+
logger$16.debug("[WebRTCManager] Call accepted, sending answer");
|
|
17103
17110
|
try {
|
|
17104
17111
|
this.emitMainSignalingStatus(rtcPeerConnectionController.id, "connecting");
|
|
17105
17112
|
await this.sendLocalDescription(vertoMessageRequest, rtcPeerConnectionController);
|
|
17106
17113
|
await rtcPeerConnectionController.updateAnswerStatus({ status: "sent" });
|
|
17107
17114
|
await this.attachManager.attach(this.buildAttachableCall());
|
|
17108
17115
|
} catch (error) {
|
|
17109
|
-
logger$
|
|
17116
|
+
logger$16.error("[WebRTCManager] Error sending Verto answer:", error);
|
|
17110
17117
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
17111
17118
|
await rtcPeerConnectionController.updateAnswerStatus({ status: "failed" });
|
|
17112
17119
|
}
|
|
@@ -17205,10 +17212,10 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17205
17212
|
});
|
|
17206
17213
|
await (0, import_cjs$15.firstValueFrom)(rtcPeerConnController.connectionState$.pipe((0, import_cjs$15.filter)((state) => state === "connected"), (0, import_cjs$15.take)(1), (0, import_cjs$15.timeout)(this._screenShareTimeoutMs), (0, import_cjs$15.takeUntil)(this.destroyed$)));
|
|
17207
17214
|
this._screenShareStatus$.next("started");
|
|
17208
|
-
logger$
|
|
17215
|
+
logger$16.info("[WebRTCManager] Screen share started successfully.");
|
|
17209
17216
|
return rtcPeerConnController.id;
|
|
17210
17217
|
} catch (error) {
|
|
17211
|
-
logger$
|
|
17218
|
+
logger$16.warn("[WebRTCManager] Error initializing additional peer connection:", error);
|
|
17212
17219
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
17213
17220
|
if (rtcPeerConnController) rtcPeerConnController.destroy();
|
|
17214
17221
|
this._screenShareStatus$.next("none");
|
|
@@ -17227,9 +17234,9 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17227
17234
|
if (removeTrack) return this.mainPeerConnection.stopTrackSender(removeTrack, { updateTransceiverDirection: true });
|
|
17228
17235
|
}
|
|
17229
17236
|
async removeScreenMedia() {
|
|
17230
|
-
if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$
|
|
17237
|
+
if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$16.warn("[WebRTCManager] No active screen share to stop.");
|
|
17231
17238
|
if (!this._screenShareId) {
|
|
17232
|
-
logger$
|
|
17239
|
+
logger$16.debug("[WebRTCManager] No screen share peer connection found.");
|
|
17233
17240
|
return;
|
|
17234
17241
|
}
|
|
17235
17242
|
this._screenShareStatus$.next("stopping");
|
|
@@ -17258,7 +17265,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17258
17265
|
dialogParams: this.dialogParams(rtcPeerConnController)
|
|
17259
17266
|
}));
|
|
17260
17267
|
} catch (error) {
|
|
17261
|
-
logger$
|
|
17268
|
+
logger$16.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:", error);
|
|
17262
17269
|
throw error;
|
|
17263
17270
|
}
|
|
17264
17271
|
}
|
|
@@ -17276,7 +17283,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17276
17283
|
try {
|
|
17277
17284
|
await this.executeVerto(vertoInfoMessage);
|
|
17278
17285
|
} catch (error) {
|
|
17279
|
-
logger$
|
|
17286
|
+
logger$16.warn("[WebRTCManager] Error sending DTMF digits:", error);
|
|
17280
17287
|
throw error;
|
|
17281
17288
|
}
|
|
17282
17289
|
}
|
|
@@ -17287,10 +17294,10 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17287
17294
|
action: "transfer"
|
|
17288
17295
|
});
|
|
17289
17296
|
try {
|
|
17290
|
-
logger$
|
|
17297
|
+
logger$16.debug("[WebRTCManager] Transferring call with options:", options);
|
|
17291
17298
|
await this.executeVerto(message);
|
|
17292
17299
|
} catch (error) {
|
|
17293
|
-
logger$
|
|
17300
|
+
logger$16.error("[WebRTCManager] Error transferring call:", error);
|
|
17294
17301
|
throw error;
|
|
17295
17302
|
}
|
|
17296
17303
|
}
|
|
@@ -17307,7 +17314,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17307
17314
|
//#endregion
|
|
17308
17315
|
//#region src/controllers/RemoteAudioMeter.ts
|
|
17309
17316
|
var import_cjs$14 = require_cjs();
|
|
17310
|
-
const logger$
|
|
17317
|
+
const logger$15 = getLogger();
|
|
17311
17318
|
/**
|
|
17312
17319
|
* Read-only audio level meter for a remote MediaStream. Attaches an
|
|
17313
17320
|
* AnalyserNode to a MediaStreamAudioSourceNode so it observes the stream
|
|
@@ -17342,7 +17349,7 @@ var RemoteAudioMeter = class extends Destroyable {
|
|
|
17342
17349
|
try {
|
|
17343
17350
|
this._source.disconnect();
|
|
17344
17351
|
} catch (error) {
|
|
17345
|
-
logger$
|
|
17352
|
+
logger$15.debug("[RemoteAudioMeter] source disconnect warning:", error);
|
|
17346
17353
|
}
|
|
17347
17354
|
this._source = null;
|
|
17348
17355
|
this._stream = null;
|
|
@@ -17359,7 +17366,7 @@ var RemoteAudioMeter = class extends Destroyable {
|
|
|
17359
17366
|
this._source = null;
|
|
17360
17367
|
}
|
|
17361
17368
|
this._audioContext.close().catch((error) => {
|
|
17362
|
-
logger$
|
|
17369
|
+
logger$15.debug("[RemoteAudioMeter] audio context close warning:", error);
|
|
17363
17370
|
});
|
|
17364
17371
|
super.destroy();
|
|
17365
17372
|
}
|
|
@@ -17378,7 +17385,7 @@ var RemoteAudioMeter = class extends Destroyable {
|
|
|
17378
17385
|
//#endregion
|
|
17379
17386
|
//#region src/controllers/RTCStatsMonitor.ts
|
|
17380
17387
|
var import_cjs$13 = require_cjs();
|
|
17381
|
-
const logger$
|
|
17388
|
+
const logger$14 = getLogger();
|
|
17382
17389
|
const DEFAULT_POLLING_INTERVAL_MS = 1e3;
|
|
17383
17390
|
const DEFAULT_BASELINE_SAMPLES = 10;
|
|
17384
17391
|
const DEFAULT_NO_AUDIO_PACKET_THRESHOLD_MS = 2e3;
|
|
@@ -17468,9 +17475,9 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
17468
17475
|
const now = Date.now();
|
|
17469
17476
|
this.lastAudioPacketChangeTime = now;
|
|
17470
17477
|
this.lastVideoPacketChangeTime = now;
|
|
17471
|
-
logger$
|
|
17478
|
+
logger$14.debug("[RTCStatsMonitor] Starting stats monitoring");
|
|
17472
17479
|
this.subscribeTo((0, import_cjs$13.interval)(this.pollingIntervalMs).pipe((0, import_cjs$13.filter)(() => this.running), (0, import_cjs$13.switchMap)(() => (0, import_cjs$13.from)(this.peerConnection.getStats()).pipe((0, import_cjs$13.catchError)((err) => {
|
|
17473
|
-
logger$
|
|
17480
|
+
logger$14.warn("[RTCStatsMonitor] Failed to get stats:", err);
|
|
17474
17481
|
return import_cjs$13.EMPTY;
|
|
17475
17482
|
}))), (0, import_cjs$13.filter)(() => this.running), (0, import_cjs$13.map)((report) => this.extractSample(report))), (sample$1) => this._sample$.next(sample$1));
|
|
17476
17483
|
this.subscribeTo(this._sample$.pipe((0, import_cjs$13.take)(this.baselineSampleCount), (0, import_cjs$13.toArray)(), (0, import_cjs$13.map)((samples) => ({
|
|
@@ -17478,7 +17485,7 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
17478
17485
|
jitter: samples.reduce((s, b) => s + b.audioJitter, 0) / samples.length,
|
|
17479
17486
|
ready: true
|
|
17480
17487
|
}))), (baseline) => {
|
|
17481
|
-
logger$
|
|
17488
|
+
logger$14.debug(`[RTCStatsMonitor] Baseline established: rtt=${baseline.rtt.toFixed(1)}ms, jitter=${baseline.jitter.toFixed(1)}ms`);
|
|
17482
17489
|
this._baseline$.next(baseline);
|
|
17483
17490
|
});
|
|
17484
17491
|
this.subscribeTo(this._sample$.pipe((0, import_cjs$13.scan)((acc, sample$1) => ({
|
|
@@ -17515,10 +17522,10 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
17515
17522
|
stop() {
|
|
17516
17523
|
if (!this.running) return;
|
|
17517
17524
|
this.running = false;
|
|
17518
|
-
logger$
|
|
17525
|
+
logger$14.debug("[RTCStatsMonitor] Stopping stats monitoring");
|
|
17519
17526
|
}
|
|
17520
17527
|
destroy() {
|
|
17521
|
-
logger$
|
|
17528
|
+
logger$14.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor");
|
|
17522
17529
|
this.stop();
|
|
17523
17530
|
super.destroy();
|
|
17524
17531
|
}
|
|
@@ -17647,7 +17654,7 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
17647
17654
|
//#endregion
|
|
17648
17655
|
//#region src/managers/CallRecoveryManager.ts
|
|
17649
17656
|
var import_cjs$12 = require_cjs();
|
|
17650
|
-
const logger$
|
|
17657
|
+
const logger$13 = getLogger();
|
|
17651
17658
|
const DEFAULT_DEBOUNCE_TIME_MS = 2e3;
|
|
17652
17659
|
const DEFAULT_COOLDOWN_MS = 1e4;
|
|
17653
17660
|
const DEFAULT_ICE_GRACE_PERIOD_MS = 3e3;
|
|
@@ -17744,10 +17751,10 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17744
17751
|
*/
|
|
17745
17752
|
async requestIceRestart() {
|
|
17746
17753
|
if (this._recoveryState$.value === "recovering") {
|
|
17747
|
-
logger$
|
|
17754
|
+
logger$13.info("CallRecoveryManager: manual ICE restart skipped — recovery already in progress");
|
|
17748
17755
|
return;
|
|
17749
17756
|
}
|
|
17750
|
-
logger$
|
|
17757
|
+
logger$13.info("CallRecoveryManager: manual ICE restart requested");
|
|
17751
17758
|
this.transitionTo("recovering");
|
|
17752
17759
|
await this.executeIceRestart(false);
|
|
17753
17760
|
this.startCooldown();
|
|
@@ -17763,7 +17770,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17763
17770
|
* WebSocket reconnect or call state recovers to 'connected'.
|
|
17764
17771
|
*/
|
|
17765
17772
|
reset() {
|
|
17766
|
-
logger$
|
|
17773
|
+
logger$13.info("CallRecoveryManager: resetting counters");
|
|
17767
17774
|
this._attemptCount = 0;
|
|
17768
17775
|
this._keyframeBurstCount = 0;
|
|
17769
17776
|
this._keyframeBurstStart = 0;
|
|
@@ -17778,7 +17785,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17778
17785
|
*/
|
|
17779
17786
|
notifyModifyFailed() {
|
|
17780
17787
|
if (this._recoveryState$.value === "cooldown" || this._recoveryState$.value === "idle") {
|
|
17781
|
-
logger$
|
|
17788
|
+
logger$13.info("CallRecoveryManager: verto.modify failed — re-entering recovery");
|
|
17782
17789
|
this._cooldownUntil = 0;
|
|
17783
17790
|
this.transitionTo("idle");
|
|
17784
17791
|
this.pushTrigger({
|
|
@@ -17802,7 +17809,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17802
17809
|
reason: `bandwidth ${bitrateKbps}kbps below threshold ${this._config.degradationBitrateThreshold}kbps`,
|
|
17803
17810
|
timestamp: Date.now()
|
|
17804
17811
|
});
|
|
17805
|
-
logger$
|
|
17812
|
+
logger$13.warn(`CallRecoveryManager: disabling video — bandwidth ${bitrateKbps}kbps < ${this._config.degradationBitrateThreshold}kbps`);
|
|
17806
17813
|
} else if (wasConstrained && bitrateKbps >= this._config.degradationRecoveryThreshold) {
|
|
17807
17814
|
this._bandwidthConstrained$.next(false);
|
|
17808
17815
|
this._callbacks.enableVideo();
|
|
@@ -17811,7 +17818,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17811
17818
|
reason: `bandwidth ${bitrateKbps}kbps recovered above ${this._config.degradationRecoveryThreshold}kbps`,
|
|
17812
17819
|
timestamp: Date.now()
|
|
17813
17820
|
});
|
|
17814
|
-
logger$
|
|
17821
|
+
logger$13.info(`CallRecoveryManager: restoring video — bandwidth ${bitrateKbps}kbps >= ${this._config.degradationRecoveryThreshold}kbps`);
|
|
17815
17822
|
}
|
|
17816
17823
|
}
|
|
17817
17824
|
/**
|
|
@@ -17830,14 +17837,14 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17830
17837
|
handleWebSocketReconnect() {
|
|
17831
17838
|
const pcState = this._callbacks.getPeerConnectionState();
|
|
17832
17839
|
if (pcState === "connected" || pcState === "completed") {
|
|
17833
|
-
logger$
|
|
17840
|
+
logger$13.info("CallRecoveryManager: signal-only reconnect — peer connection still alive");
|
|
17834
17841
|
this.emitEvent({
|
|
17835
17842
|
action: "signal_reconnect",
|
|
17836
17843
|
reason: "WebSocket reconnected, peer connection still connected",
|
|
17837
17844
|
timestamp: Date.now()
|
|
17838
17845
|
});
|
|
17839
17846
|
} else {
|
|
17840
|
-
logger$
|
|
17847
|
+
logger$13.info("CallRecoveryManager: full reconnect — peer connection also down");
|
|
17841
17848
|
this.emitEvent({
|
|
17842
17849
|
action: "full_reconnect",
|
|
17843
17850
|
reason: "WebSocket reconnected, peer connection not connected — ICE restart needed",
|
|
@@ -17861,7 +17868,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17861
17868
|
}), (0, import_cjs$12.debounceTime)(this._config.debounceTimeMs), (0, import_cjs$12.withLatestFrom)(this._inputs.signalingReady$), (0, import_cjs$12.filter)(([, signalingReady]) => this.passGateChecks(signalingReady)), (0, import_cjs$12.map)(([trigger]) => trigger), (0, import_cjs$12.exhaustMap)((trigger) => this.executeTieredRecovery(trigger)), (0, import_cjs$12.takeUntil)((0, import_cjs$12.merge)(this._destroyed$, this._pipelineStop$))), {
|
|
17862
17869
|
next: () => {},
|
|
17863
17870
|
error: (err) => {
|
|
17864
|
-
logger$
|
|
17871
|
+
logger$13.error("CallRecoveryManager: pipeline error", err);
|
|
17865
17872
|
this.transitionTo("idle");
|
|
17866
17873
|
}
|
|
17867
17874
|
});
|
|
@@ -17888,27 +17895,27 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17888
17895
|
reason: `no packet loss for ${this._config.packetLossRecoveryDelaySec}s — restoring video`,
|
|
17889
17896
|
timestamp: Date.now()
|
|
17890
17897
|
});
|
|
17891
|
-
logger$
|
|
17898
|
+
logger$13.info(`CallRecoveryManager: restoring video — no packet loss for ${this._config.packetLossRecoveryDelaySec}s`);
|
|
17892
17899
|
});
|
|
17893
17900
|
}
|
|
17894
17901
|
passGateChecks(signalingReady) {
|
|
17895
17902
|
if (this._callbacks.isNegotiating()) {
|
|
17896
|
-
logger$
|
|
17903
|
+
logger$13.debug("CallRecoveryManager: gate blocked — negotiation in progress");
|
|
17897
17904
|
this.transitionTo("idle");
|
|
17898
17905
|
return false;
|
|
17899
17906
|
}
|
|
17900
17907
|
if (!signalingReady) {
|
|
17901
|
-
logger$
|
|
17908
|
+
logger$13.debug("CallRecoveryManager: gate blocked — signaling not ready");
|
|
17902
17909
|
this.transitionTo("idle");
|
|
17903
17910
|
return false;
|
|
17904
17911
|
}
|
|
17905
17912
|
if (!this._callbacks.isCallConnected()) {
|
|
17906
|
-
logger$
|
|
17913
|
+
logger$13.debug("CallRecoveryManager: gate blocked — call not connected");
|
|
17907
17914
|
this.transitionTo("idle");
|
|
17908
17915
|
return false;
|
|
17909
17916
|
}
|
|
17910
17917
|
if (this.isCooldownActive()) {
|
|
17911
|
-
logger$
|
|
17918
|
+
logger$13.debug("CallRecoveryManager: gate blocked — cooldown active");
|
|
17912
17919
|
this.transitionTo("cooldown");
|
|
17913
17920
|
return false;
|
|
17914
17921
|
}
|
|
@@ -17919,9 +17926,9 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17919
17926
|
}
|
|
17920
17927
|
executeTieredRecovery(trigger) {
|
|
17921
17928
|
this.transitionTo("recovering");
|
|
17922
|
-
logger$
|
|
17929
|
+
logger$13.info(`CallRecoveryManager: starting tiered recovery — source=${trigger.source} detail=${trigger.detail}`);
|
|
17923
17930
|
return (0, import_cjs$12.from)(this.runTiers(trigger)).pipe((0, import_cjs$12.tap)(() => this.startCooldown()), (0, import_cjs$12.catchError)((err) => {
|
|
17924
|
-
logger$
|
|
17931
|
+
logger$13.error("CallRecoveryManager: tiered recovery failed", err);
|
|
17925
17932
|
this.startCooldown();
|
|
17926
17933
|
return import_cjs$12.EMPTY;
|
|
17927
17934
|
}));
|
|
@@ -17929,7 +17936,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17929
17936
|
async runTiers(trigger) {
|
|
17930
17937
|
this.executeKeyframe(trigger.detail);
|
|
17931
17938
|
if (trigger.issueType && DEGRADATION_ONLY_ISSUES.has(trigger.issueType)) {
|
|
17932
|
-
logger$
|
|
17939
|
+
logger$13.debug(`CallRecoveryManager: degradation-only issue (${trigger.issueType}) — Tier 1 only, skipping ICE restart`);
|
|
17933
17940
|
return;
|
|
17934
17941
|
}
|
|
17935
17942
|
if (this._attemptCount < this._config.maxAttempts) {
|
|
@@ -17946,13 +17953,13 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17946
17953
|
maxAttempts: this._config.maxAttempts,
|
|
17947
17954
|
timestamp: Date.now()
|
|
17948
17955
|
});
|
|
17949
|
-
logger$
|
|
17956
|
+
logger$13.warn("CallRecoveryManager: max recovery attempts reached");
|
|
17950
17957
|
}
|
|
17951
17958
|
}
|
|
17952
17959
|
executeKeyframe(reason) {
|
|
17953
17960
|
const now = Date.now();
|
|
17954
17961
|
if (now < this._keyframeCooldownUntil) {
|
|
17955
|
-
logger$
|
|
17962
|
+
logger$13.debug("CallRecoveryManager: keyframe request skipped — cooldown active");
|
|
17956
17963
|
return;
|
|
17957
17964
|
}
|
|
17958
17965
|
if (now - this._keyframeBurstStart > this._config.keyframeBurstWindowMs) {
|
|
@@ -17961,7 +17968,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17961
17968
|
}
|
|
17962
17969
|
if (this._keyframeBurstCount >= this._config.keyframeMaxBurst) {
|
|
17963
17970
|
this._keyframeCooldownUntil = now + this._config.keyframeCooldownMs;
|
|
17964
|
-
logger$
|
|
17971
|
+
logger$13.debug(`CallRecoveryManager: keyframe burst limit reached (${this._config.keyframeMaxBurst}), cooldown until ${this._keyframeCooldownUntil}`);
|
|
17965
17972
|
return;
|
|
17966
17973
|
}
|
|
17967
17974
|
this._keyframeBurstCount += 1;
|
|
@@ -17971,12 +17978,12 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17971
17978
|
reason,
|
|
17972
17979
|
timestamp: now
|
|
17973
17980
|
});
|
|
17974
|
-
logger$
|
|
17981
|
+
logger$13.debug(`CallRecoveryManager: keyframe requested (burst ${this._keyframeBurstCount}/${this._config.keyframeMaxBurst})`);
|
|
17975
17982
|
}
|
|
17976
17983
|
async executeIceRestart(relayOnly) {
|
|
17977
17984
|
this._attemptCount += 1;
|
|
17978
17985
|
const tier = relayOnly ? "Tier 3 (relay-only)" : "Tier 2 (standard)";
|
|
17979
|
-
logger$
|
|
17986
|
+
logger$13.info(`CallRecoveryManager: ${tier} ICE restart — attempt ${this._attemptCount}/${this._config.maxAttempts}`);
|
|
17980
17987
|
this.emitEvent({
|
|
17981
17988
|
action: "reinvite_started",
|
|
17982
17989
|
reason: `${tier} ICE restart`,
|
|
@@ -17993,7 +18000,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17993
18000
|
maxAttempts: this._config.maxAttempts,
|
|
17994
18001
|
timestamp: Date.now()
|
|
17995
18002
|
});
|
|
17996
|
-
logger$
|
|
18003
|
+
logger$13.info(`CallRecoveryManager: ${tier} ICE restart succeeded`);
|
|
17997
18004
|
this._attemptCount = 0;
|
|
17998
18005
|
return true;
|
|
17999
18006
|
}
|
|
@@ -18004,7 +18011,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
18004
18011
|
maxAttempts: this._config.maxAttempts,
|
|
18005
18012
|
timestamp: Date.now()
|
|
18006
18013
|
});
|
|
18007
|
-
logger$
|
|
18014
|
+
logger$13.warn(`CallRecoveryManager: ${tier} ICE restart failed`);
|
|
18008
18015
|
return false;
|
|
18009
18016
|
} catch {
|
|
18010
18017
|
this.emitEvent({
|
|
@@ -18014,7 +18021,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
18014
18021
|
maxAttempts: this._config.maxAttempts,
|
|
18015
18022
|
timestamp: Date.now()
|
|
18016
18023
|
});
|
|
18017
|
-
logger$
|
|
18024
|
+
logger$13.warn(`CallRecoveryManager: ${tier} ICE restart timed out`);
|
|
18018
18025
|
return false;
|
|
18019
18026
|
}
|
|
18020
18027
|
}
|
|
@@ -18035,7 +18042,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
18035
18042
|
transitionTo(state) {
|
|
18036
18043
|
const prev = this._recoveryState$.value;
|
|
18037
18044
|
if (prev !== state) {
|
|
18038
|
-
logger$
|
|
18045
|
+
logger$13.debug(`CallRecoveryManager: state ${prev} -> ${state}`);
|
|
18039
18046
|
this._recoveryState$.next(state);
|
|
18040
18047
|
}
|
|
18041
18048
|
}
|
|
@@ -18138,7 +18145,7 @@ function mosToQualityLevel(mos) {
|
|
|
18138
18145
|
//#endregion
|
|
18139
18146
|
//#region src/core/entities/Call.ts
|
|
18140
18147
|
var import_cjs$11 = require_cjs();
|
|
18141
|
-
const logger$
|
|
18148
|
+
const logger$12 = getLogger();
|
|
18142
18149
|
/**
|
|
18143
18150
|
* Ratio between the critical and warning RTT spike multipliers.
|
|
18144
18151
|
* Warning threshold = baseline * warningMultiplier (default 3x)
|
|
@@ -18156,7 +18163,7 @@ const fromDestinationParams = (destination) => {
|
|
|
18156
18163
|
});
|
|
18157
18164
|
return params;
|
|
18158
18165
|
} catch (error) {
|
|
18159
|
-
logger$
|
|
18166
|
+
logger$12.warn(`Failed to parse destination URI: ${destination}`, error);
|
|
18160
18167
|
return {};
|
|
18161
18168
|
}
|
|
18162
18169
|
};
|
|
@@ -18356,7 +18363,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18356
18363
|
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);
|
|
18357
18364
|
return response;
|
|
18358
18365
|
} catch (error) {
|
|
18359
|
-
logger$
|
|
18366
|
+
logger$12.error(`[Call] Error executing method ${method} with params`, params, error);
|
|
18360
18367
|
throw error;
|
|
18361
18368
|
}
|
|
18362
18369
|
}
|
|
@@ -18559,9 +18566,9 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18559
18566
|
*/
|
|
18560
18567
|
initResilienceSubsystems() {
|
|
18561
18568
|
const pc = this.rtcPeerConnection;
|
|
18562
|
-
logger$
|
|
18569
|
+
logger$12.debug(`[Call] initResilienceSubsystems: pc=${pc ? "exists" : "undefined"}, connectionState=${pc?.connectionState}`);
|
|
18563
18570
|
if (!pc) {
|
|
18564
|
-
logger$
|
|
18571
|
+
logger$12.warn("[Call] No peer connection available, skipping resilience init");
|
|
18565
18572
|
return;
|
|
18566
18573
|
}
|
|
18567
18574
|
try {
|
|
@@ -18596,14 +18603,14 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18596
18603
|
disableVideo: () => {
|
|
18597
18604
|
try {
|
|
18598
18605
|
this.vertoManager.muteMainVideoInputDevice();
|
|
18599
|
-
logger$
|
|
18606
|
+
logger$12.debug("[Call] Recovery manager disabled video");
|
|
18600
18607
|
} catch {
|
|
18601
|
-
logger$
|
|
18608
|
+
logger$12.debug("[Call] Recovery manager failed to disable video");
|
|
18602
18609
|
}
|
|
18603
18610
|
},
|
|
18604
18611
|
enableVideo: () => {
|
|
18605
18612
|
this.vertoManager.unmuteMainVideoInputDevice().catch(() => {
|
|
18606
|
-
logger$
|
|
18613
|
+
logger$12.debug("[Call] Recovery manager failed to enable video");
|
|
18607
18614
|
});
|
|
18608
18615
|
},
|
|
18609
18616
|
isNegotiating: () => this.vertoManager.mainPeerConnection.isNegotiating,
|
|
@@ -18653,7 +18660,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18653
18660
|
this.subscribeTo(this._recoveryManager.recoveryEvent$, (event) => {
|
|
18654
18661
|
this._recoveryEvent$.next(event);
|
|
18655
18662
|
if (event.action === "max_attempts_reached") {
|
|
18656
|
-
logger$
|
|
18663
|
+
logger$12.warn("[Call] All recovery attempts exhausted, terminating call");
|
|
18657
18664
|
this.emitError({
|
|
18658
18665
|
kind: "network",
|
|
18659
18666
|
fatal: true,
|
|
@@ -18673,13 +18680,13 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18673
18680
|
else if (event.type === "online") this._recoveryManager?.handleWebSocketReconnect();
|
|
18674
18681
|
});
|
|
18675
18682
|
this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$11.skip)(1), (0, import_cjs$11.filter)(Boolean)), () => {
|
|
18676
|
-
logger$
|
|
18683
|
+
logger$12.debug("[Call] WebSocket reconnected — notifying recovery manager");
|
|
18677
18684
|
this._recoveryManager?.handleWebSocketReconnect();
|
|
18678
18685
|
});
|
|
18679
18686
|
this._statsMonitor.start();
|
|
18680
|
-
logger$
|
|
18687
|
+
logger$12.debug("[Call] Resilience subsystems initialized for call", this.id);
|
|
18681
18688
|
} catch (error) {
|
|
18682
|
-
logger$
|
|
18689
|
+
logger$12.warn("[Call] Failed to initialize resilience subsystems:", error);
|
|
18683
18690
|
}
|
|
18684
18691
|
}
|
|
18685
18692
|
/**
|
|
@@ -18762,19 +18769,19 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18762
18769
|
}
|
|
18763
18770
|
isCallSessionEvent(event) {
|
|
18764
18771
|
try {
|
|
18765
|
-
logger$
|
|
18772
|
+
logger$12.debug("[Call] Checking if event is for this call session:", event);
|
|
18766
18773
|
const callId = getValueFrom(event, "params.params.callID") ?? getValueFrom(event, "params.call_id");
|
|
18767
18774
|
const roomSessionId = getValueFrom(event, "params.room_session_id");
|
|
18768
|
-
logger$
|
|
18775
|
+
logger$12.debug(`[Call] Extracted session identifiers callID: ${callId} and roomSessionID: ${roomSessionId} from event:`);
|
|
18769
18776
|
return callId === this.id || !!callId && this.callEventsManager.isCallIdValid(callId) || !!roomSessionId && this.callEventsManager.isRoomSessionIdValid(roomSessionId);
|
|
18770
18777
|
} catch (error) {
|
|
18771
|
-
logger$
|
|
18778
|
+
logger$12.error("[Call] Error checking if event is for this call session:", error);
|
|
18772
18779
|
return false;
|
|
18773
18780
|
}
|
|
18774
18781
|
}
|
|
18775
18782
|
get callSessionEvents$() {
|
|
18776
18783
|
return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$11.filter)((event) => this.isCallSessionEvent(event)), (0, import_cjs$11.tap)((event) => {
|
|
18777
|
-
logger$
|
|
18784
|
+
logger$12.debug("[Call] Received call session event:", event);
|
|
18778
18785
|
}), (0, import_cjs$11.takeUntil)(this.destroyed$), (0, import_cjs$11.share)()));
|
|
18779
18786
|
}
|
|
18780
18787
|
/** Observable of call-updated events. */
|
|
@@ -18844,16 +18851,16 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18844
18851
|
this._customSubscriptions.set(eventType, filtered$);
|
|
18845
18852
|
}, (error) => {
|
|
18846
18853
|
this._customSubscriptions.delete(eventType);
|
|
18847
|
-
logger$
|
|
18854
|
+
logger$12.warn(`[Call] verto.subscribe for '${eventType}' failed, not caching:`, error);
|
|
18848
18855
|
});
|
|
18849
18856
|
this._customSubscriptions.set(eventType, filtered$);
|
|
18850
18857
|
return filtered$;
|
|
18851
18858
|
}
|
|
18852
18859
|
get webrtcMessages$() {
|
|
18853
|
-
return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(filterAs(isWebrtcMessageMetadata, "params"), (0, import_cjs$11.tap)((event) => logger$
|
|
18860
|
+
return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(filterAs(isWebrtcMessageMetadata, "params"), (0, import_cjs$11.tap)((event) => logger$12.debug("[Call] Event is a WebRTC message event:", event)), (0, import_cjs$11.takeUntil)(this.destroyed$), (0, import_cjs$11.share)()));
|
|
18854
18861
|
}
|
|
18855
18862
|
get callEvent$() {
|
|
18856
|
-
return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(filterAs(isSignalwireCallMetadata, "params"), (0, import_cjs$11.tap)((event) => logger$
|
|
18863
|
+
return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(filterAs(isSignalwireCallMetadata, "params"), (0, import_cjs$11.tap)((event) => logger$12.debug("[Call] Event is a call event:", event)), (0, import_cjs$11.takeUntil)(this.destroyed$), (0, import_cjs$11.share)()));
|
|
18857
18864
|
}
|
|
18858
18865
|
get layoutEvent$() {
|
|
18859
18866
|
return this.cachedObservable("layoutEvent$", () => this.callEvent$.pipe(filterAs(isLayoutChangedMetadata, "params")));
|
|
@@ -18982,7 +18989,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18982
18989
|
setLocalMicrophoneGain(value) {
|
|
18983
18990
|
const pipeline = this.vertoManager.ensureLocalAudioPipeline();
|
|
18984
18991
|
if (!pipeline) {
|
|
18985
|
-
logger$
|
|
18992
|
+
logger$12.warn("[Call] setLocalMicrophoneGain: audio pipeline unavailable");
|
|
18986
18993
|
return;
|
|
18987
18994
|
}
|
|
18988
18995
|
const percent = Math.max(0, Math.min(200, value));
|
|
@@ -19027,7 +19034,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
19027
19034
|
enablePushToTalk() {
|
|
19028
19035
|
const pipeline = this.vertoManager.ensureLocalAudioPipeline();
|
|
19029
19036
|
if (!pipeline) {
|
|
19030
|
-
logger$
|
|
19037
|
+
logger$12.warn("[Call] enablePushToTalk: audio pipeline unavailable");
|
|
19031
19038
|
return;
|
|
19032
19039
|
}
|
|
19033
19040
|
pipeline.setPTTActive(false);
|
|
@@ -19190,7 +19197,7 @@ var CallFactory = class {
|
|
|
19190
19197
|
//#endregion
|
|
19191
19198
|
//#region src/behaviors/Collection.ts
|
|
19192
19199
|
var import_cjs$10 = require_cjs();
|
|
19193
|
-
const logger$
|
|
19200
|
+
const logger$11 = getLogger();
|
|
19194
19201
|
var Fetcher = class {
|
|
19195
19202
|
constructor(endpoint, params, http) {
|
|
19196
19203
|
this.endpoint = endpoint;
|
|
@@ -19214,7 +19221,7 @@ var Fetcher = class {
|
|
|
19214
19221
|
this.hasMore = !!this.nextUrl;
|
|
19215
19222
|
return result.data.filter(this.filter).map(this.mapper);
|
|
19216
19223
|
}
|
|
19217
|
-
logger$
|
|
19224
|
+
logger$11.error("Failed to fetch entity");
|
|
19218
19225
|
return [];
|
|
19219
19226
|
}
|
|
19220
19227
|
async id(v) {
|
|
@@ -19290,7 +19297,7 @@ var EntityCollection = class extends Destroyable {
|
|
|
19290
19297
|
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
19291
19298
|
this._loading$.next(false);
|
|
19292
19299
|
} catch (error) {
|
|
19293
|
-
logger$
|
|
19300
|
+
logger$11.error(`Failed to fetch initial collection data`, error);
|
|
19294
19301
|
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
19295
19302
|
this._loading$.next(false);
|
|
19296
19303
|
this.onError?.(new CollectionFetchError("fetchMore", error));
|
|
@@ -19304,7 +19311,7 @@ var EntityCollection = class extends Destroyable {
|
|
|
19304
19311
|
if (data) this.upsertData(data);
|
|
19305
19312
|
return data;
|
|
19306
19313
|
} catch (error) {
|
|
19307
|
-
logger$
|
|
19314
|
+
logger$11.error(`Failed to fetch data for (${String(key)}:${String(value)}) :`, error);
|
|
19308
19315
|
this._loading$.next(false);
|
|
19309
19316
|
this.onError?.(new CollectionFetchError(`tryFetch(${String(key)})`, error));
|
|
19310
19317
|
}
|
|
@@ -19553,13 +19560,13 @@ var Address = class extends Destroyable {
|
|
|
19553
19560
|
//#endregion
|
|
19554
19561
|
//#region src/core/utils.ts
|
|
19555
19562
|
var import_cjs$8 = require_cjs();
|
|
19556
|
-
const logger$
|
|
19563
|
+
const logger$10 = getLogger();
|
|
19557
19564
|
const isRPCConnectResult = (e) => {
|
|
19558
|
-
logger$
|
|
19565
|
+
logger$10.debug("isRPCConnectResult check:", e);
|
|
19559
19566
|
if (!e || typeof e !== "object") return false;
|
|
19560
19567
|
const result = e;
|
|
19561
19568
|
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";
|
|
19562
|
-
logger$
|
|
19569
|
+
logger$10.debug("isRPCConnectResult check result:", is);
|
|
19563
19570
|
return is;
|
|
19564
19571
|
};
|
|
19565
19572
|
var PendingRPC = class PendingRPC {
|
|
@@ -19568,7 +19575,7 @@ var PendingRPC = class PendingRPC {
|
|
|
19568
19575
|
}
|
|
19569
19576
|
constructor(request, responses$, options) {
|
|
19570
19577
|
this.id = v4_default();
|
|
19571
|
-
logger$
|
|
19578
|
+
logger$10.debug(`[PendingRPC(${this.id}) request:${request.id}: method:${request.method}] Creating PendingRPC`);
|
|
19572
19579
|
this.request = request;
|
|
19573
19580
|
const timeoutMs = options?.timeoutMs ?? PendingRPC.defaultTimeoutMs;
|
|
19574
19581
|
const signal = options?.signal;
|
|
@@ -19594,22 +19601,22 @@ var PendingRPC = class PendingRPC {
|
|
|
19594
19601
|
isSettled = true;
|
|
19595
19602
|
if (response.error) {
|
|
19596
19603
|
const rpcError = new JSONRPCError(response.error.code, response.error.message, response.error.data, void 0, request.id);
|
|
19597
|
-
logger$
|
|
19604
|
+
logger$10.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
|
|
19598
19605
|
reject(rpcError);
|
|
19599
19606
|
} else {
|
|
19600
|
-
logger$
|
|
19607
|
+
logger$10.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
19601
19608
|
resolve(response);
|
|
19602
19609
|
}
|
|
19603
19610
|
subscription.unsubscribe();
|
|
19604
19611
|
},
|
|
19605
19612
|
error: (error) => {
|
|
19606
|
-
logger$
|
|
19613
|
+
logger$10.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with error:`, error);
|
|
19607
19614
|
isSettled = true;
|
|
19608
19615
|
reject(error);
|
|
19609
19616
|
subscription.unsubscribe();
|
|
19610
19617
|
},
|
|
19611
19618
|
complete: () => {
|
|
19612
|
-
logger$
|
|
19619
|
+
logger$10.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
|
|
19613
19620
|
if (!isSettled) reject(new RPCTimeoutError(request.id, timeoutMs));
|
|
19614
19621
|
subscription.unsubscribe();
|
|
19615
19622
|
}
|
|
@@ -19630,7 +19637,7 @@ var PendingRPC = class PendingRPC {
|
|
|
19630
19637
|
//#endregion
|
|
19631
19638
|
//#region src/managers/ClientSessionManager.ts
|
|
19632
19639
|
var import_cjs$7 = require_cjs();
|
|
19633
|
-
const logger$
|
|
19640
|
+
const logger$9 = getLogger();
|
|
19634
19641
|
const getAddressSearchURI = (options) => {
|
|
19635
19642
|
const to = options.to?.split("?")[0];
|
|
19636
19643
|
const from$9 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
|
|
@@ -19728,7 +19735,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19728
19735
|
try {
|
|
19729
19736
|
return await this.transport.execute(request, options);
|
|
19730
19737
|
} catch (error) {
|
|
19731
|
-
logger$
|
|
19738
|
+
logger$9.debug("[Session] Execute Error", error);
|
|
19732
19739
|
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
19733
19740
|
throw error;
|
|
19734
19741
|
}
|
|
@@ -19742,13 +19749,13 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19742
19749
|
return true;
|
|
19743
19750
|
}
|
|
19744
19751
|
setupMessageHandlers() {
|
|
19745
|
-
logger$
|
|
19752
|
+
logger$9.debug("[Session] Setting up message handlers");
|
|
19746
19753
|
this.subscribeTo(this.authStateEvent$, async (authStateEvent) => {
|
|
19747
|
-
logger$
|
|
19754
|
+
logger$9.debug("[Session] Authorization state event received:", authStateEvent);
|
|
19748
19755
|
try {
|
|
19749
19756
|
await this.updateAuthorizationStateInStorage(authStateEvent.authorization_state);
|
|
19750
19757
|
} catch (error) {
|
|
19751
|
-
logger$
|
|
19758
|
+
logger$9.error("[Session] Failed to handle authorization state update:", error);
|
|
19752
19759
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19753
19760
|
}
|
|
19754
19761
|
});
|
|
@@ -19756,29 +19763,29 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19756
19763
|
if (this._authState$.value.kind === "authenticated") this._authState$.next({ kind: "unauthenticated" });
|
|
19757
19764
|
});
|
|
19758
19765
|
this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$7.filter)((status) => status === "connected"), (0, import_cjs$7.exhaustMap)(() => {
|
|
19759
|
-
logger$
|
|
19766
|
+
logger$9.debug("[Session] Connection established, initiating authentication");
|
|
19760
19767
|
return (0, import_cjs$7.from)(this.authenticate()).pipe((0, import_cjs$7.catchError)((error) => {
|
|
19761
19768
|
this.handleAuthenticationError(error).catch((err) => {
|
|
19762
|
-
logger$
|
|
19769
|
+
logger$9.error("[Session] Error handling authentication failure:", err);
|
|
19763
19770
|
});
|
|
19764
19771
|
return import_cjs$7.EMPTY;
|
|
19765
19772
|
}));
|
|
19766
19773
|
})), void 0);
|
|
19767
19774
|
this.subscribeTo(this.vertoInvite$, async (invite) => {
|
|
19768
|
-
logger$
|
|
19775
|
+
logger$9.debug("[Session] Verto invite received:", invite);
|
|
19769
19776
|
try {
|
|
19770
19777
|
await this.createInboundCall(invite);
|
|
19771
19778
|
} catch (error) {
|
|
19772
|
-
logger$
|
|
19779
|
+
logger$9.error("[Session] Error handling Verto invite:", error);
|
|
19773
19780
|
this._errors$.next(new VertoInviteHandlerError(error));
|
|
19774
19781
|
}
|
|
19775
19782
|
});
|
|
19776
19783
|
this.subscribeTo(this.vertoAttach$, async (attach) => {
|
|
19777
|
-
logger$
|
|
19784
|
+
logger$9.debug("[Session] Verto attach received:", attach);
|
|
19778
19785
|
try {
|
|
19779
19786
|
await this.handleVertoAttach(attach);
|
|
19780
19787
|
} catch (error) {
|
|
19781
|
-
logger$
|
|
19788
|
+
logger$9.error("[Session] Error handling Verto attach:", error);
|
|
19782
19789
|
this._errors$.next(new VertoAttachHandlerError(error));
|
|
19783
19790
|
}
|
|
19784
19791
|
});
|
|
@@ -19788,36 +19795,36 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19788
19795
|
const storedState = await this.storage.getItem(this.authorizationStateKey);
|
|
19789
19796
|
this.authorizationState$.next(storedState ?? void 0);
|
|
19790
19797
|
} catch (error) {
|
|
19791
|
-
logger$
|
|
19798
|
+
logger$9.error("Failed to retrieve authorization state from storage:", error);
|
|
19792
19799
|
this.authorizationState$.next(void 0);
|
|
19793
19800
|
}
|
|
19794
19801
|
}
|
|
19795
19802
|
async updateAuthorizationStateInStorage(authorizationState) {
|
|
19796
19803
|
if (!authorizationState) {
|
|
19797
|
-
logger$
|
|
19804
|
+
logger$9.debug("[Session] Removing authorization state from storage");
|
|
19798
19805
|
try {
|
|
19799
19806
|
await this.storage.removeItem(this.authorizationStateKey);
|
|
19800
19807
|
this.authorizationState$.next(void 0);
|
|
19801
19808
|
} catch (error) {
|
|
19802
|
-
logger$
|
|
19809
|
+
logger$9.error("Failed to remove authorization state from storage:", error);
|
|
19803
19810
|
throw error;
|
|
19804
19811
|
}
|
|
19805
19812
|
return;
|
|
19806
19813
|
}
|
|
19807
19814
|
try {
|
|
19808
|
-
logger$
|
|
19815
|
+
logger$9.debug("[Session] Updating authorization state in storage");
|
|
19809
19816
|
await this.storage.setItem(this.authorizationStateKey, authorizationState);
|
|
19810
19817
|
this.authorizationState$.next(authorizationState);
|
|
19811
19818
|
} catch (error) {
|
|
19812
|
-
logger$
|
|
19819
|
+
logger$9.error("Failed to retrieve authorization state from storage:", error);
|
|
19813
19820
|
throw error;
|
|
19814
19821
|
}
|
|
19815
19822
|
}
|
|
19816
19823
|
get authStateEvent$() {
|
|
19817
19824
|
return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$7.tap)((msg) => {
|
|
19818
|
-
logger$
|
|
19825
|
+
logger$9.debug("[Session] Received incoming message:", msg);
|
|
19819
19826
|
}), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$7.tap)((event) => {
|
|
19820
|
-
logger$
|
|
19827
|
+
logger$9.debug("[Session] Authorization state event received:", event.authorization_state);
|
|
19821
19828
|
})));
|
|
19822
19829
|
}
|
|
19823
19830
|
get signalingEvent$() {
|
|
@@ -19855,15 +19862,15 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19855
19862
|
await (0, import_cjs$7.firstValueFrom)(this.authenticated$.pipe((0, import_cjs$7.takeUntil)(this.destroyed$), (0, import_cjs$7.filter)(Boolean), (0, import_cjs$7.take)(1), (0, import_cjs$7.timeout)({ first: 15e3 })));
|
|
19856
19863
|
}
|
|
19857
19864
|
async handleAuthenticationError(error) {
|
|
19858
|
-
logger$
|
|
19865
|
+
logger$9.error("Authentication error:", error);
|
|
19859
19866
|
const isRecoverableAuthError = error instanceof JSONRPCError && (error.code === RPC_ERROR_REQUESTER_VALIDATION_FAILED || error.code === RPC_ERROR_INVALID_PARAMS || error.code === RPC_ERROR_AUTHENTICATION_FAILED);
|
|
19860
19867
|
const hasStoredState = await (0, import_cjs$7.firstValueFrom)(this.authorizationState$.pipe((0, import_cjs$7.take)(1))) !== void 0;
|
|
19861
19868
|
if (isRecoverableAuthError && hasStoredState) {
|
|
19862
|
-
logger$
|
|
19869
|
+
logger$9.debug("[Session] Recoverable auth error — cleaning up stored state and reconnecting fresh");
|
|
19863
19870
|
try {
|
|
19864
19871
|
await this.cleanupStoredConnectionParams();
|
|
19865
19872
|
} catch (cleanupError) {
|
|
19866
|
-
logger$
|
|
19873
|
+
logger$9.error("Failed to cleanup stored connection params:", cleanupError);
|
|
19867
19874
|
} finally {
|
|
19868
19875
|
this.transport.reconnect();
|
|
19869
19876
|
}
|
|
@@ -19878,19 +19885,19 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19878
19885
|
try {
|
|
19879
19886
|
await this.storage.setItem(this.authorizationStateKey, authorization_state);
|
|
19880
19887
|
} catch (error) {
|
|
19881
|
-
logger$
|
|
19888
|
+
logger$9.error("Failed to update authorization state in storage:", error);
|
|
19882
19889
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19883
19890
|
}
|
|
19884
19891
|
}
|
|
19885
19892
|
async reauthenticate(token, dpopToken, options) {
|
|
19886
|
-
logger$
|
|
19893
|
+
logger$9.debug("[Session] Re-authenticating session");
|
|
19887
19894
|
try {
|
|
19888
19895
|
let resolvedDpopToken = dpopToken;
|
|
19889
19896
|
if (!resolvedDpopToken && this.dpopManager?.initialized) try {
|
|
19890
19897
|
resolvedDpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19891
19898
|
} catch (error) {
|
|
19892
19899
|
if (this.clientBound) throw error;
|
|
19893
|
-
logger$
|
|
19900
|
+
logger$9.warn("[Session] Failed to create DPoP proof for reauthenticate:", error);
|
|
19894
19901
|
}
|
|
19895
19902
|
const request = RPCReauthenticate({
|
|
19896
19903
|
project: this._authorization$.value?.project_id ?? "",
|
|
@@ -19898,24 +19905,24 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19898
19905
|
...resolvedDpopToken ? { dpop_token: resolvedDpopToken } : {}
|
|
19899
19906
|
});
|
|
19900
19907
|
await (0, import_cjs$7.lastValueFrom)((0, import_cjs$7.from)(this.transport.execute(request)).pipe(throwOnRPCError(), (0, import_cjs$7.take)(1), (0, import_cjs$7.catchError)((err) => {
|
|
19901
|
-
logger$
|
|
19908
|
+
logger$9.error("[Session] Re-authentication RPC failed:", err);
|
|
19902
19909
|
throw err;
|
|
19903
19910
|
})));
|
|
19904
19911
|
if (options?.clientBound) this._wasClientBound = true;
|
|
19905
|
-
logger$
|
|
19912
|
+
logger$9.debug("[Session] Re-authentication successful, updating stored auth state");
|
|
19906
19913
|
} catch (error) {
|
|
19907
|
-
logger$
|
|
19914
|
+
logger$9.error("[Session] Re-authentication failed:", error);
|
|
19908
19915
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19909
19916
|
throw error;
|
|
19910
19917
|
}
|
|
19911
19918
|
}
|
|
19912
19919
|
async authenticate() {
|
|
19913
|
-
logger$
|
|
19920
|
+
logger$9.debug("[Session] Starting authentication process");
|
|
19914
19921
|
const persistedParams = await (0, import_cjs$7.firstValueFrom)((0, import_cjs$7.combineLatest)({
|
|
19915
19922
|
protocol: this.transport.protocol$,
|
|
19916
19923
|
authorization_state: this.authorizationState$
|
|
19917
19924
|
}).pipe((0, import_cjs$7.take)(1)));
|
|
19918
|
-
logger$
|
|
19925
|
+
logger$9.debug("[Session] Persisted params:\n", {
|
|
19919
19926
|
protocol: persistedParams.protocol,
|
|
19920
19927
|
authStateLength: persistedParams.authorization_state?.length
|
|
19921
19928
|
});
|
|
@@ -19923,16 +19930,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19923
19930
|
const storedToken = this.getCredential().token;
|
|
19924
19931
|
const isReconnect = hasReconnectState && storedToken;
|
|
19925
19932
|
let dpopToken;
|
|
19926
|
-
if (isReconnect) logger$
|
|
19933
|
+
if (isReconnect) logger$9.debug("[Session] Reconnecting with stored jwt_token + authorization_state");
|
|
19927
19934
|
else if (this.onBeforeReconnect && this.clientBound) {
|
|
19928
|
-
logger$
|
|
19935
|
+
logger$9.debug("[Session] Refreshing credentials before fresh connect");
|
|
19929
19936
|
await this.onBeforeReconnect();
|
|
19930
19937
|
}
|
|
19931
19938
|
if ((!isReconnect || this.clientBound) && this.dpopManager?.initialized) try {
|
|
19932
19939
|
dpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.connect" });
|
|
19933
19940
|
} catch (error) {
|
|
19934
19941
|
if (this.clientBound) throw error;
|
|
19935
|
-
logger$
|
|
19942
|
+
logger$9.warn("[Session] Failed to create DPoP proof for connect, proceeding without:", error);
|
|
19936
19943
|
}
|
|
19937
19944
|
const rpcConnectRequest = RPCConnect({
|
|
19938
19945
|
authentication: isReconnect ? { jwt_token: storedToken } : this.authentication,
|
|
@@ -19949,12 +19956,12 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19949
19956
|
} : {}
|
|
19950
19957
|
});
|
|
19951
19958
|
const response = await (0, import_cjs$7.lastValueFrom)((0, import_cjs$7.from)(this.transport.execute(rpcConnectRequest)).pipe(throwOnRPCError(), (0, import_cjs$7.map)((res) => res.result), (0, import_cjs$7.filter)(isRPCConnectResult), (0, import_cjs$7.tap)(() => {
|
|
19952
|
-
logger$
|
|
19959
|
+
logger$9.debug("[Session] Response passed filter, processing authentication result");
|
|
19953
19960
|
}), (0, import_cjs$7.take)(1), (0, import_cjs$7.catchError)((err) => {
|
|
19954
|
-
logger$
|
|
19961
|
+
logger$9.error("[Session] Authentication RPC failed:", err);
|
|
19955
19962
|
throw err;
|
|
19956
19963
|
})));
|
|
19957
|
-
logger$
|
|
19964
|
+
logger$9.debug("[Session] Processing authentication result:", {
|
|
19958
19965
|
hasProtocol: !!response.protocol,
|
|
19959
19966
|
hasAuthorization: !!response.authorization,
|
|
19960
19967
|
hasIceServers: !!response.ice_servers
|
|
@@ -19963,7 +19970,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19963
19970
|
this._authorization$.next(response.authorization);
|
|
19964
19971
|
this._iceServers$.next(response.ice_servers ?? []);
|
|
19965
19972
|
this._authState$.next({ kind: "authenticated" });
|
|
19966
|
-
logger$
|
|
19973
|
+
logger$9.debug("[Session] Authentication completed successfully");
|
|
19967
19974
|
}
|
|
19968
19975
|
async disconnect() {
|
|
19969
19976
|
this.transport.disconnect();
|
|
@@ -19999,11 +20006,11 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19999
20006
|
async handleVertoAttach(attach) {
|
|
20000
20007
|
const { callID } = attach;
|
|
20001
20008
|
if (callID in this._calls$.value) {
|
|
20002
|
-
logger$
|
|
20009
|
+
logger$9.debug(`[Session] Verto attach for existing call ${callID}, deferring to per-call handler`);
|
|
20003
20010
|
return;
|
|
20004
20011
|
}
|
|
20005
20012
|
const storedOptions = await this.attachManager.consumePendingAttachment(callID);
|
|
20006
|
-
logger$
|
|
20013
|
+
logger$9.debug(`[Session] Creating reattached call for callID: ${callID}`);
|
|
20007
20014
|
const callSession = await this.createCall({
|
|
20008
20015
|
nodeId: attach.node_id,
|
|
20009
20016
|
callId: callID,
|
|
@@ -20034,7 +20041,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
20034
20041
|
});
|
|
20035
20042
|
return callSession;
|
|
20036
20043
|
} catch (error) {
|
|
20037
|
-
logger$
|
|
20044
|
+
logger$9.error("[Session] Error creating outbound call:", error);
|
|
20038
20045
|
callSession?.destroy();
|
|
20039
20046
|
const callError = new CallCreateError(error instanceof import_cjs$7.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
|
|
20040
20047
|
this._errors$.next(callError);
|
|
@@ -20052,7 +20059,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
20052
20059
|
address = this._directory.get(addressId);
|
|
20053
20060
|
if (!address) throw new DependencyError(`Address ID: ${addressId} not found`);
|
|
20054
20061
|
} catch {
|
|
20055
|
-
logger$
|
|
20062
|
+
logger$9.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
|
|
20056
20063
|
}
|
|
20057
20064
|
const callSession = this.callFactory.createCall(address, { ...options });
|
|
20058
20065
|
this.subscribeTo(callSession.status$.pipe((0, import_cjs$7.filter)((status) => status === "destroyed"), (0, import_cjs$7.take)(1)), () => {
|
|
@@ -20061,7 +20068,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
20061
20068
|
});
|
|
20062
20069
|
return callSession;
|
|
20063
20070
|
} catch (error) {
|
|
20064
|
-
logger$
|
|
20071
|
+
logger$9.error("[Session] Error creating call session:", error);
|
|
20065
20072
|
throw new CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
|
|
20066
20073
|
}
|
|
20067
20074
|
}
|
|
@@ -20110,7 +20117,7 @@ const isString = (obj) => typeof obj === "string";
|
|
|
20110
20117
|
//#endregion
|
|
20111
20118
|
//#region src/managers/ConversationsManager.ts
|
|
20112
20119
|
var import_cjs$6 = require_cjs();
|
|
20113
|
-
const logger$
|
|
20120
|
+
const logger$8 = getLogger();
|
|
20114
20121
|
var ConversationMessagesFetcher = class extends Fetcher {
|
|
20115
20122
|
constructor(groupId, http) {
|
|
20116
20123
|
super(`/api/fabric/conversations/${groupId}/messages`, "page_size=100", http);
|
|
@@ -20150,13 +20157,13 @@ var ConversationsManager = class {
|
|
|
20150
20157
|
}
|
|
20151
20158
|
throw new ConversationError("Join Failed - Unexpected response");
|
|
20152
20159
|
} catch (error) {
|
|
20153
|
-
logger$
|
|
20160
|
+
logger$8.error("[ConversationsManager] Failed to join conversation:", error);
|
|
20154
20161
|
throw error;
|
|
20155
20162
|
}
|
|
20156
20163
|
}
|
|
20157
20164
|
async getConversationMessageCollection(addressId) {
|
|
20158
20165
|
const groupId = this.groupIds.get(addressId) ?? await this.join(addressId);
|
|
20159
|
-
return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(filterAs(isConversationMessageMetadata, "params"), (0, import_cjs$6.tap)((event) => logger$
|
|
20166
|
+
return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(filterAs(isConversationMessageMetadata, "params"), (0, import_cjs$6.tap)((event) => logger$8.debug("[ConversationsManager ] Conversation Event:", event)), (0, import_cjs$6.map)((params) => ({ ...params }))), this.http, this.onError));
|
|
20160
20167
|
}
|
|
20161
20168
|
async sendText(text, destinationAddressId) {
|
|
20162
20169
|
const groupId = this.groupIds.get(destinationAddressId) ?? await this.join(destinationAddressId);
|
|
@@ -20173,7 +20180,7 @@ var ConversationsManager = class {
|
|
|
20173
20180
|
})).ok) return;
|
|
20174
20181
|
throw new ConversationError("Send Text Failed - Unexpected response");
|
|
20175
20182
|
} catch (error) {
|
|
20176
|
-
logger$
|
|
20183
|
+
logger$8.error("[ConversationsManager] Failed to send text message:", error);
|
|
20177
20184
|
throw error;
|
|
20178
20185
|
}
|
|
20179
20186
|
}
|
|
@@ -20182,7 +20189,7 @@ var ConversationsManager = class {
|
|
|
20182
20189
|
//#endregion
|
|
20183
20190
|
//#region src/managers/DeviceTokenManager.ts
|
|
20184
20191
|
var import_cjs$5 = require_cjs();
|
|
20185
|
-
const logger$
|
|
20192
|
+
const logger$7 = getLogger();
|
|
20186
20193
|
/**
|
|
20187
20194
|
* Resolves the token expiry timestamp (epoch seconds) using a 3-tier priority chain:
|
|
20188
20195
|
* 1. `data.expires_at` — server-provided absolute timestamp
|
|
@@ -20192,7 +20199,7 @@ const logger$6 = getLogger();
|
|
|
20192
20199
|
function resolveExpiresAt(data) {
|
|
20193
20200
|
if (data.expires_at) return data.expires_at;
|
|
20194
20201
|
if (data.expires_in) return Math.floor(Date.now() / 1e3) + data.expires_in;
|
|
20195
|
-
logger$
|
|
20202
|
+
logger$7.warn("[DeviceToken] Could not determine token expiry, using default");
|
|
20196
20203
|
return Math.floor(Date.now() / 1e3) + DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
20197
20204
|
}
|
|
20198
20205
|
/**
|
|
@@ -20225,11 +20232,12 @@ var DeviceTokenManager = class extends Destroyable {
|
|
|
20225
20232
|
this.getCredential = getCredential;
|
|
20226
20233
|
this._currentToken$ = this.createBehaviorSubject(null);
|
|
20227
20234
|
this._refreshInProgress = false;
|
|
20235
|
+
this._paused = false;
|
|
20228
20236
|
this._effectiveExpireIn = DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
20229
20237
|
this.subscribeTo(this._currentToken$.pipe((0, import_cjs$5.filter)(Boolean), (0, import_cjs$5.switchMap)((tokenData) => {
|
|
20230
20238
|
const expiresAt = resolveExpiresAt(tokenData);
|
|
20231
20239
|
const refreshIn = Math.max(expiresAt * 1e3 - Date.now() - DEVICE_TOKEN_REFRESH_BUFFER_MS, 1e3);
|
|
20232
|
-
logger$
|
|
20240
|
+
logger$7.debug(`[DeviceToken] Scheduling Client Bound SAT refresh in ${refreshIn}ms`);
|
|
20233
20241
|
return (0, import_cjs$5.timer)(refreshIn);
|
|
20234
20242
|
})), () => {
|
|
20235
20243
|
this.executeRefresh();
|
|
@@ -20243,7 +20251,12 @@ var DeviceTokenManager = class extends Destroyable {
|
|
|
20243
20251
|
* Activates the Client Bound SAT flow when the user's token has
|
|
20244
20252
|
* `sat:refresh` scope.
|
|
20245
20253
|
*
|
|
20246
|
-
*
|
|
20254
|
+
* Returns an {@link ActivationResult} indicating whether the manager
|
|
20255
|
+
* took ownership of refresh duties. The caller must use the `activated`
|
|
20256
|
+
* boolean to decide whether to keep its own refresh path armed — when
|
|
20257
|
+
* `activated` is `false`, the caller is responsible for refresh.
|
|
20258
|
+
*
|
|
20259
|
+
* Steps on success:
|
|
20247
20260
|
* 1. Check user's `sat_claims` for `sat:refresh` scope
|
|
20248
20261
|
* 2. Call `/api/fabric/subscriber/devices/token` with a DPoP proof
|
|
20249
20262
|
* 3. Reauthenticate the session with the Client Bound SAT + DPoP proof
|
|
@@ -20252,32 +20265,51 @@ var DeviceTokenManager = class extends Destroyable {
|
|
|
20252
20265
|
async activate(user, session, updateCredential) {
|
|
20253
20266
|
const { satClaims } = user;
|
|
20254
20267
|
if (!satClaims?.scope?.includes(SAT_REFRESH_SCOPE)) {
|
|
20255
|
-
logger$
|
|
20256
|
-
return
|
|
20268
|
+
logger$7.debug("[DeviceToken] No sat:refresh scope, skipping Client Bound SAT activation");
|
|
20269
|
+
return {
|
|
20270
|
+
activated: false,
|
|
20271
|
+
reason: "no-scope"
|
|
20272
|
+
};
|
|
20257
20273
|
}
|
|
20258
20274
|
this._session = session;
|
|
20259
20275
|
this._updateCredential = updateCredential;
|
|
20260
20276
|
try {
|
|
20277
|
+
const cached = this._currentToken$.value;
|
|
20278
|
+
if (cached && this.isTokenFresh(cached)) {
|
|
20279
|
+
logger$7.debug("[DeviceToken] Reusing cached Client Bound SAT — skipping /devices/token");
|
|
20280
|
+
const rpcProof$1 = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
20281
|
+
await session.reauthenticate(cached.token, rpcProof$1, { clientBound: true });
|
|
20282
|
+
updateCredential({ token: cached.token });
|
|
20283
|
+
return { activated: true };
|
|
20284
|
+
}
|
|
20261
20285
|
const tokenData = await this.obtainToken();
|
|
20262
20286
|
if (!tokenData.expires_at && !tokenData.expires_in && satClaims.expires_at) tokenData.expires_at = satClaims.expires_at;
|
|
20263
20287
|
this._effectiveExpireIn = resolveExpireIn(tokenData);
|
|
20264
20288
|
const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
20265
20289
|
await session.reauthenticate(tokenData.token, rpcProof, { clientBound: true });
|
|
20266
20290
|
updateCredential({ token: tokenData.token });
|
|
20267
|
-
logger$
|
|
20291
|
+
logger$7.info("[DeviceToken] Client Bound SAT activated successfully");
|
|
20268
20292
|
this._currentToken$.next(tokenData);
|
|
20293
|
+
return { activated: true };
|
|
20269
20294
|
} catch (error) {
|
|
20270
|
-
logger$
|
|
20295
|
+
logger$7.error("[DeviceToken] Failed to activate Client Bound SAT:", error);
|
|
20271
20296
|
this.errorHandler(new DPoPInitError(error, "Failed to activate Client Bound SAT"));
|
|
20272
|
-
|
|
20273
|
-
|
|
20274
|
-
|
|
20275
|
-
|
|
20276
|
-
expires_at: expiresAt
|
|
20277
|
-
});
|
|
20297
|
+
return {
|
|
20298
|
+
activated: false,
|
|
20299
|
+
reason: "endpoint-failed"
|
|
20300
|
+
};
|
|
20278
20301
|
}
|
|
20279
20302
|
}
|
|
20280
20303
|
/**
|
|
20304
|
+
* Returns true when the cached token has enough headroom before expiry to
|
|
20305
|
+
* be safely reused on reactivation. The headroom matches the refresh
|
|
20306
|
+
* buffer, so a token within the refresh window is treated as stale (the
|
|
20307
|
+
* reactive pipeline is about to refresh it anyway).
|
|
20308
|
+
*/
|
|
20309
|
+
isTokenFresh(token) {
|
|
20310
|
+
return resolveExpiresAt(token) * 1e3 - Date.now() > DEVICE_TOKEN_REFRESH_BUFFER_MS;
|
|
20311
|
+
}
|
|
20312
|
+
/**
|
|
20281
20313
|
* Obtains a Client Bound SAT from `/api/fabric/subscriber/devices/token`.
|
|
20282
20314
|
* Returns the full {@link DeviceTokenResponse} including expiry metadata.
|
|
20283
20315
|
*/
|
|
@@ -20307,7 +20339,7 @@ var DeviceTokenManager = class extends Destroyable {
|
|
|
20307
20339
|
* handled by the reactive pipeline).
|
|
20308
20340
|
*/
|
|
20309
20341
|
async refreshToken(session, currentToken, updateCredential) {
|
|
20310
|
-
logger$
|
|
20342
|
+
logger$7.debug("[DeviceToken] Refreshing Client Bound SAT");
|
|
20311
20343
|
const dpopProof = await this.dpopManager.createHttpProof({
|
|
20312
20344
|
method: "POST",
|
|
20313
20345
|
uri: DEVICE_REFRESH_ENDPOINT,
|
|
@@ -20329,7 +20361,7 @@ var DeviceTokenManager = class extends Destroyable {
|
|
|
20329
20361
|
const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
20330
20362
|
await session.reauthenticate(data.token, rpcProof);
|
|
20331
20363
|
updateCredential({ token: data.token });
|
|
20332
|
-
logger$
|
|
20364
|
+
logger$7.info("[DeviceToken] Client Bound SAT refreshed successfully");
|
|
20333
20365
|
return data;
|
|
20334
20366
|
}
|
|
20335
20367
|
/**
|
|
@@ -20338,18 +20370,22 @@ var DeviceTokenManager = class extends Destroyable {
|
|
|
20338
20370
|
* On all retries exhausted, emits to `errorHandler`.
|
|
20339
20371
|
*/
|
|
20340
20372
|
async executeRefresh() {
|
|
20373
|
+
if (this._paused) {
|
|
20374
|
+
logger$7.debug("[DeviceToken] Manager paused, skipping refresh");
|
|
20375
|
+
return;
|
|
20376
|
+
}
|
|
20341
20377
|
if (this._refreshInProgress) {
|
|
20342
|
-
logger$
|
|
20378
|
+
logger$7.debug("[DeviceToken] Refresh already in progress, skipping");
|
|
20343
20379
|
return;
|
|
20344
20380
|
}
|
|
20345
20381
|
const session = this._session;
|
|
20346
20382
|
const updateCredential = this._updateCredential;
|
|
20347
20383
|
if (!session || !updateCredential) {
|
|
20348
|
-
logger$
|
|
20384
|
+
logger$7.warn("[DeviceToken] Cannot refresh: session or updateCredential not set");
|
|
20349
20385
|
return;
|
|
20350
20386
|
}
|
|
20351
20387
|
if (!session.authenticated) {
|
|
20352
|
-
logger$
|
|
20388
|
+
logger$7.debug("[DeviceToken] Session not authenticated, deferring refresh");
|
|
20353
20389
|
return;
|
|
20354
20390
|
}
|
|
20355
20391
|
this._refreshInProgress = true;
|
|
@@ -20359,7 +20395,7 @@ var DeviceTokenManager = class extends Destroyable {
|
|
|
20359
20395
|
const newTokenData = await this.retryRefresh(session, currentToken, updateCredential);
|
|
20360
20396
|
this._currentToken$.next(newTokenData);
|
|
20361
20397
|
} catch (error) {
|
|
20362
|
-
logger$
|
|
20398
|
+
logger$7.error("[DeviceToken] Automatic Client Bound SAT refresh failed:", error);
|
|
20363
20399
|
this.errorHandler(error instanceof TokenRefreshError ? error : new TokenRefreshError("Automatic token refresh failed", error));
|
|
20364
20400
|
} finally {
|
|
20365
20401
|
this._refreshInProgress = false;
|
|
@@ -20377,18 +20413,215 @@ var DeviceTokenManager = class extends Destroyable {
|
|
|
20377
20413
|
lastError = error;
|
|
20378
20414
|
if (attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES - 1) {
|
|
20379
20415
|
const delay$1 = DEVICE_TOKEN_REFRESH_RETRY_BASE_MS * Math.pow(2, attempt);
|
|
20380
|
-
logger$
|
|
20416
|
+
logger$7.warn(`[DeviceToken] Refresh attempt ${attempt + 1} failed, retrying in ${delay$1}ms`);
|
|
20381
20417
|
await new Promise((resolve) => setTimeout(resolve, delay$1));
|
|
20382
20418
|
}
|
|
20383
20419
|
}
|
|
20384
20420
|
throw lastError instanceof Error ? lastError : new TokenRefreshError("All refresh retries exhausted", lastError);
|
|
20385
20421
|
}
|
|
20422
|
+
/**
|
|
20423
|
+
* Stops the reactive refresh pipeline from firing. Use when the underlying
|
|
20424
|
+
* session is being torn down (e.g., during {@link SignalWire.disconnect})
|
|
20425
|
+
* so a scheduled refresh cannot fire against a destroyed session.
|
|
20426
|
+
*
|
|
20427
|
+
* The manager's state (cached token, effective TTL, subscriptions) is
|
|
20428
|
+
* preserved — call {@link resume} to re-enable firing after reconnect.
|
|
20429
|
+
*/
|
|
20430
|
+
pause() {
|
|
20431
|
+
this._paused = true;
|
|
20432
|
+
}
|
|
20433
|
+
/** Re-enables the reactive refresh pipeline after a previous {@link pause}. */
|
|
20434
|
+
resume() {
|
|
20435
|
+
this._paused = false;
|
|
20436
|
+
}
|
|
20386
20437
|
/** Cleans up the manager, cancelling the reactive pipeline and all subscriptions. */
|
|
20387
20438
|
destroy() {
|
|
20388
20439
|
super.destroy();
|
|
20389
20440
|
}
|
|
20390
20441
|
};
|
|
20391
20442
|
|
|
20443
|
+
//#endregion
|
|
20444
|
+
//#region src/managers/CredentialRefreshCoordinator.ts
|
|
20445
|
+
const logger$6 = getLogger();
|
|
20446
|
+
const defaultDeviceTokenManagerFactory = (dpopManager, http, errorHandler, getCredential) => new DeviceTokenManager(dpopManager, http, errorHandler, getCredential);
|
|
20447
|
+
/**
|
|
20448
|
+
* Centralizes credential-refresh ownership across the two competing
|
|
20449
|
+
* mechanisms — developer-provided `CredentialProvider.refresh()` and the
|
|
20450
|
+
* Client Bound SAT path via {@link DeviceTokenManager}.
|
|
20451
|
+
*
|
|
20452
|
+
* Maintains the invariant: **at most one refresh mechanism is armed at a
|
|
20453
|
+
* time, and at least one is armed whenever the current credential has an
|
|
20454
|
+
* `expiry_at`**.
|
|
20455
|
+
*
|
|
20456
|
+
* Replaces the previous design where refresh state was distributed across
|
|
20457
|
+
* `SignalWire` (timer field, scheduler method, activation helper) and
|
|
20458
|
+
* `DeviceTokenManager` (reactive pipeline). Centralizing the invariant in
|
|
20459
|
+
* one component eliminates the bug class that produced issue #19074.
|
|
20460
|
+
*
|
|
20461
|
+
* Race-safety:
|
|
20462
|
+
* - `_activating` flag prevents overlapping `activate()` calls from racing.
|
|
20463
|
+
* - `_activationGeneration` lets late resolutions detect they've been
|
|
20464
|
+
* preempted by a newer activation (e.g., reconnect during in-flight
|
|
20465
|
+
* `obtainToken`).
|
|
20466
|
+
*/
|
|
20467
|
+
var CredentialRefreshCoordinator = class extends Destroyable {
|
|
20468
|
+
constructor(dpopManager, deps) {
|
|
20469
|
+
super();
|
|
20470
|
+
this.deps = deps;
|
|
20471
|
+
this._activating = false;
|
|
20472
|
+
this._activationGeneration = 0;
|
|
20473
|
+
if (dpopManager?.initialized) this._deviceTokenManager = (deps.deviceTokenManagerFactory ?? defaultDeviceTokenManagerFactory)(dpopManager, deps.http, (error) => deps.notifier.onError(error), () => deps.store.read());
|
|
20474
|
+
}
|
|
20475
|
+
/** True when the Client Bound SAT path is available (DPoP initialized). */
|
|
20476
|
+
get clientBoundSATAvailable() {
|
|
20477
|
+
return this._deviceTokenManager !== void 0;
|
|
20478
|
+
}
|
|
20479
|
+
/** True when the developer-provided refresh timer is currently armed. */
|
|
20480
|
+
get developerRefreshArmed() {
|
|
20481
|
+
return this._developerTimerId !== void 0;
|
|
20482
|
+
}
|
|
20483
|
+
/**
|
|
20484
|
+
* Arms the developer-provided refresh timer to fire shortly before
|
|
20485
|
+
* `expiresAt`. Replaces any previously scheduled developer refresh.
|
|
20486
|
+
*
|
|
20487
|
+
* Idempotent — multiple calls just reschedule. On retry exhaustion,
|
|
20488
|
+
* invokes `deps.onRefreshExhausted` so the orchestrator can disconnect.
|
|
20489
|
+
*/
|
|
20490
|
+
scheduleDeveloperRefresh(provider, expiresAt, attempt = 0) {
|
|
20491
|
+
if (this._developerTimerId !== void 0) clearTimeout(this._developerTimerId);
|
|
20492
|
+
const refreshInterval = attempt === 0 ? Math.max(expiresAt - Date.now() - CREDENTIAL_REFRESH_BUFFER_MS, 1e3) : Math.min(CREDENTIAL_REFRESH_RETRY_BASE_MS * Math.pow(2, attempt) * (.5 + Math.random() * .5), CREDENTIAL_REFRESH_MAX_DELAY_MS);
|
|
20493
|
+
this._developerTimerId = setTimeout(async () => {
|
|
20494
|
+
try {
|
|
20495
|
+
if (!provider.refresh) throw new InvalidCredentialsError("Credential provider does not support refresh");
|
|
20496
|
+
const newCredentials = await provider.refresh();
|
|
20497
|
+
this.deps.store.write(newCredentials);
|
|
20498
|
+
this.deps.store.persist(newCredentials);
|
|
20499
|
+
logger$6.info("[Coordinator] Credentials refreshed successfully.");
|
|
20500
|
+
if (newCredentials.expiry_at) this.scheduleDeveloperRefresh(provider, newCredentials.expiry_at, 0);
|
|
20501
|
+
} catch (error) {
|
|
20502
|
+
const nextAttempt = attempt + 1;
|
|
20503
|
+
logger$6.error(`[Coordinator] Credential refresh failed (attempt ${nextAttempt}/${CREDENTIAL_REFRESH_MAX_RETRIES}):`, error);
|
|
20504
|
+
this.deps.notifier.onError(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
20505
|
+
if (nextAttempt < CREDENTIAL_REFRESH_MAX_RETRIES) this.scheduleDeveloperRefresh(provider, expiresAt, nextAttempt);
|
|
20506
|
+
else {
|
|
20507
|
+
logger$6.error("[Coordinator] Credential refresh exhausted all retries. Disconnecting.");
|
|
20508
|
+
this.deps.notifier.onError(new TokenRefreshError("Credential refresh failed after max retries"));
|
|
20509
|
+
this.deps.notifier.onRefreshExhausted();
|
|
20510
|
+
}
|
|
20511
|
+
}
|
|
20512
|
+
}, refreshInterval);
|
|
20513
|
+
}
|
|
20514
|
+
/**
|
|
20515
|
+
* Cancels any scheduled developer-provided refresh. Idempotent.
|
|
20516
|
+
*
|
|
20517
|
+
* @internal Used by the coordinator's own activation flow. External
|
|
20518
|
+
* callers should use {@link suspend} for disconnect-time quiescence —
|
|
20519
|
+
* `suspend()` also pauses the internal Client Bound SAT pipeline.
|
|
20520
|
+
*/
|
|
20521
|
+
cancelDeveloperRefresh() {
|
|
20522
|
+
if (this._developerTimerId !== void 0) {
|
|
20523
|
+
clearTimeout(this._developerTimerId);
|
|
20524
|
+
this._developerTimerId = void 0;
|
|
20525
|
+
}
|
|
20526
|
+
}
|
|
20527
|
+
/**
|
|
20528
|
+
* Suspends both refresh paths — cancels the developer timer and pauses
|
|
20529
|
+
* the internal reactive pipeline. Use when the underlying session is
|
|
20530
|
+
* being torn down (e.g., {@link SignalWire.disconnect}). The next
|
|
20531
|
+
* {@link activate} call re-enables the internal pipeline.
|
|
20532
|
+
*
|
|
20533
|
+
* The internal manager's cached token survives — see
|
|
20534
|
+
* {@link DeviceTokenManager.pause} — so a subsequent reconnect can
|
|
20535
|
+
* skip the `/devices/token` exchange entirely.
|
|
20536
|
+
*/
|
|
20537
|
+
suspend() {
|
|
20538
|
+
this.cancelDeveloperRefresh();
|
|
20539
|
+
this._deviceTokenManager?.pause();
|
|
20540
|
+
}
|
|
20541
|
+
/**
|
|
20542
|
+
* Asks the Client Bound SAT path to take over refresh. If it accepts,
|
|
20543
|
+
* the developer-provided timer (if any) is cancelled. If it declines, the
|
|
20544
|
+
* developer timer remains armed and a `credential_refresh_fallback`
|
|
20545
|
+
* warning is emitted.
|
|
20546
|
+
*
|
|
20547
|
+
* **Idempotent** — re-entrant calls during an in-flight activation are
|
|
20548
|
+
* dropped. Use `_activationGeneration` to detect stale resolutions
|
|
20549
|
+
* (e.g., a reconnect-triggered activate() that races with an earlier one).
|
|
20550
|
+
*/
|
|
20551
|
+
async activate(user, session) {
|
|
20552
|
+
if (this._activating) {
|
|
20553
|
+
logger$6.debug("[Coordinator] activate() in flight; ignoring re-entrant call");
|
|
20554
|
+
return;
|
|
20555
|
+
}
|
|
20556
|
+
if (!this._deviceTokenManager) return;
|
|
20557
|
+
this._deviceTokenManager.resume();
|
|
20558
|
+
const generation = ++this._activationGeneration;
|
|
20559
|
+
this._activating = true;
|
|
20560
|
+
try {
|
|
20561
|
+
const result = await this.withActivationTimeout(this._deviceTokenManager.activate(user, session, (cred) => this.deps.store.merge(cred)));
|
|
20562
|
+
if (generation !== this._activationGeneration) {
|
|
20563
|
+
logger$6.debug("[Coordinator] activate() result discarded (preempted by newer activation)");
|
|
20564
|
+
return;
|
|
20565
|
+
}
|
|
20566
|
+
if (result.activated) {
|
|
20567
|
+
this.cancelDeveloperRefresh();
|
|
20568
|
+
logger$6.debug("[Coordinator] Developer refresh disabled — Client Bound SAT owns refresh");
|
|
20569
|
+
return;
|
|
20570
|
+
}
|
|
20571
|
+
logger$6.warn(`[SignalWire] [SW-REFRESH-FALLBACK] Client Bound SAT declined (reason=${result.reason}); using developer-provided refresh handler.`);
|
|
20572
|
+
this.deps.notifier.onWarning({
|
|
20573
|
+
code: "credential_refresh_fallback",
|
|
20574
|
+
source: "CredentialProvider",
|
|
20575
|
+
reason: result.reason,
|
|
20576
|
+
message: `Client Bound SAT activation declined (${result.reason}); using developer-provided refresh.`
|
|
20577
|
+
});
|
|
20578
|
+
} finally {
|
|
20579
|
+
this._activating = false;
|
|
20580
|
+
}
|
|
20581
|
+
}
|
|
20582
|
+
destroy() {
|
|
20583
|
+
this.cancelDeveloperRefresh();
|
|
20584
|
+
this._deviceTokenManager?.destroy();
|
|
20585
|
+
this._deviceTokenManager = void 0;
|
|
20586
|
+
super.destroy();
|
|
20587
|
+
}
|
|
20588
|
+
/**
|
|
20589
|
+
* Races the manager's `activate()` against a hard timeout. A wedged HTTP
|
|
20590
|
+
* layer (e.g., proxy issues) could otherwise hang the activation
|
|
20591
|
+
* indefinitely, leaving the session with no refresh mechanism while the
|
|
20592
|
+
* `_activating` guard blocks subsequent retries.
|
|
20593
|
+
*
|
|
20594
|
+
* On timeout, the manager is paused immediately. The inner `activate()`
|
|
20595
|
+
* may still complete in the background and emit to `_currentToken$`,
|
|
20596
|
+
* which would normally arm the reactive refresh pipeline; pausing
|
|
20597
|
+
* prevents that pipeline from firing while the developer refresh path
|
|
20598
|
+
* is the active mechanism — preserving the "at most one mechanism
|
|
20599
|
+
* armed" invariant. The next `activate()` call resumes the manager.
|
|
20600
|
+
*/
|
|
20601
|
+
async withActivationTimeout(inner) {
|
|
20602
|
+
return new Promise((resolve) => {
|
|
20603
|
+
const timer$4 = setTimeout(() => {
|
|
20604
|
+
this._deviceTokenManager?.pause();
|
|
20605
|
+
resolve({
|
|
20606
|
+
activated: false,
|
|
20607
|
+
reason: "activation-timeout"
|
|
20608
|
+
});
|
|
20609
|
+
}, CREDENTIAL_ACTIVATE_TIMEOUT_MS);
|
|
20610
|
+
inner.then((result) => {
|
|
20611
|
+
clearTimeout(timer$4);
|
|
20612
|
+
resolve(result);
|
|
20613
|
+
}, (error) => {
|
|
20614
|
+
clearTimeout(timer$4);
|
|
20615
|
+
this.deps.notifier.onError(error instanceof Error ? error : new Error(String(error)));
|
|
20616
|
+
resolve({
|
|
20617
|
+
activated: false,
|
|
20618
|
+
reason: "endpoint-failed"
|
|
20619
|
+
});
|
|
20620
|
+
});
|
|
20621
|
+
});
|
|
20622
|
+
}
|
|
20623
|
+
};
|
|
20624
|
+
|
|
20392
20625
|
//#endregion
|
|
20393
20626
|
//#region src/managers/DiagnosticsCollector.ts
|
|
20394
20627
|
const logger$5 = getLogger();
|
|
@@ -21102,6 +21335,7 @@ var SignalWire = class extends Destroyable {
|
|
|
21102
21335
|
this._isConnected$ = this.createBehaviorSubject(false);
|
|
21103
21336
|
this._isRegistered$ = this.createBehaviorSubject(false);
|
|
21104
21337
|
this._errors$ = this.createReplaySubject(1);
|
|
21338
|
+
this._warnings$ = this.createReplaySubject(10);
|
|
21105
21339
|
this._options = {};
|
|
21106
21340
|
this._deps = new DependencyContainer();
|
|
21107
21341
|
this._credentialProvider = credentialProvider;
|
|
@@ -21161,6 +21395,27 @@ var SignalWire = class extends Destroyable {
|
|
|
21161
21395
|
*/
|
|
21162
21396
|
async resolveCredentials() {
|
|
21163
21397
|
const fingerprint = await this.initDPoP();
|
|
21398
|
+
this._refreshCoordinator = new CredentialRefreshCoordinator(this._dpopManager, {
|
|
21399
|
+
http: this._deps.http,
|
|
21400
|
+
notifier: {
|
|
21401
|
+
onError: (error) => this._errors$.next(error),
|
|
21402
|
+
onWarning: (warning) => this._warnings$.next(warning),
|
|
21403
|
+
onRefreshExhausted: () => void this.disconnect()
|
|
21404
|
+
},
|
|
21405
|
+
store: {
|
|
21406
|
+
read: () => this._deps.credential,
|
|
21407
|
+
write: (credential) => {
|
|
21408
|
+
this._deps.credential = credential;
|
|
21409
|
+
},
|
|
21410
|
+
merge: (partial) => {
|
|
21411
|
+
this._deps.credential = {
|
|
21412
|
+
...this._deps.credential,
|
|
21413
|
+
...partial
|
|
21414
|
+
};
|
|
21415
|
+
},
|
|
21416
|
+
persist: (credential) => this.persistCredential(credential)
|
|
21417
|
+
}
|
|
21418
|
+
});
|
|
21164
21419
|
if (this._credentialProvider) return this.validateCredentials(this._credentialProvider, void 0, fingerprint);
|
|
21165
21420
|
for (const scope of this._deps.persistSession ? ["local", "session"] : ["session"]) try {
|
|
21166
21421
|
const cached = await this._deps.storage.getItem("sw:cached_credential", scope);
|
|
@@ -21190,7 +21445,16 @@ var SignalWire = class extends Destroyable {
|
|
|
21190
21445
|
logger$1.error("[SignalWire] Provided credentials have expired.");
|
|
21191
21446
|
throw new InvalidCredentialsError("Provided credentials have expired.");
|
|
21192
21447
|
}
|
|
21193
|
-
if (_credentials.expiry_at && credentialProvider?.refresh) this.
|
|
21448
|
+
if (_credentials.expiry_at && credentialProvider?.refresh) this._refreshCoordinator?.scheduleDeveloperRefresh(credentialProvider, _credentials.expiry_at);
|
|
21449
|
+
else if (_credentials.expiry_at && !credentialProvider?.refresh) {
|
|
21450
|
+
logger$1.warn(`[SignalWire] [SW-NO-REFRESH-HANDLER] Credential has expiry_at=${_credentials.expiry_at} but no refresh handler. Session will terminate at expiry unless the SAT has 'sat:refresh' scope.`);
|
|
21451
|
+
this._warnings$.next({
|
|
21452
|
+
code: "credential_no_refresh_handler",
|
|
21453
|
+
source: "CredentialProvider",
|
|
21454
|
+
message: "Credential has expiry_at but no refresh handler. Session will terminate at expiry unless the SAT carries 'sat:refresh' scope.",
|
|
21455
|
+
expiresAt: _credentials.expiry_at
|
|
21456
|
+
});
|
|
21457
|
+
}
|
|
21194
21458
|
this._deps.credential = _credentials;
|
|
21195
21459
|
this.persistCredential(_credentials);
|
|
21196
21460
|
if (this.isConnected && this._clientSession.authenticated && _credentials.token) try {
|
|
@@ -21201,35 +21465,6 @@ var SignalWire = class extends Destroyable {
|
|
|
21201
21465
|
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
21202
21466
|
}
|
|
21203
21467
|
}
|
|
21204
|
-
/**
|
|
21205
|
-
* Schedules credential refresh with exponential backoff retry on failure.
|
|
21206
|
-
* On success, resets attempt counter and schedules the next refresh.
|
|
21207
|
-
* After exhausting retries, emits TokenRefreshError and disconnects.
|
|
21208
|
-
*/
|
|
21209
|
-
scheduleCredentialRefresh(credentialProvider, expiresAt, attempt = 0) {
|
|
21210
|
-
if (this._refreshTimerId !== void 0) clearTimeout(this._refreshTimerId);
|
|
21211
|
-
const refreshInterval = attempt === 0 ? Math.max(expiresAt - Date.now() - CREDENTIAL_REFRESH_BUFFER_MS, 1e3) : Math.min(CREDENTIAL_REFRESH_RETRY_BASE_MS * Math.pow(2, attempt) * (.5 + Math.random() * .5), CREDENTIAL_REFRESH_MAX_DELAY_MS);
|
|
21212
|
-
this._refreshTimerId = setTimeout(async () => {
|
|
21213
|
-
try {
|
|
21214
|
-
if (!credentialProvider.refresh) throw new InvalidCredentialsError("Credential provider does not support refresh");
|
|
21215
|
-
const newCredentials = await credentialProvider.refresh();
|
|
21216
|
-
this._deps.credential = newCredentials;
|
|
21217
|
-
this.persistCredential(newCredentials);
|
|
21218
|
-
logger$1.info("[SignalWire] Credentials refreshed successfully.");
|
|
21219
|
-
if (newCredentials.expiry_at) this.scheduleCredentialRefresh(credentialProvider, newCredentials.expiry_at, 0);
|
|
21220
|
-
} catch (error) {
|
|
21221
|
-
const nextAttempt = attempt + 1;
|
|
21222
|
-
logger$1.error(`[SignalWire] Credential refresh failed (attempt ${nextAttempt}/${CREDENTIAL_REFRESH_MAX_RETRIES}):`, error);
|
|
21223
|
-
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
21224
|
-
if (nextAttempt < CREDENTIAL_REFRESH_MAX_RETRIES) this.scheduleCredentialRefresh(credentialProvider, expiresAt, nextAttempt);
|
|
21225
|
-
else {
|
|
21226
|
-
logger$1.error("[SignalWire] Credential refresh exhausted all retries. Disconnecting.");
|
|
21227
|
-
this._errors$.next(new TokenRefreshError("Credential refresh failed after max retries"));
|
|
21228
|
-
this.disconnect();
|
|
21229
|
-
}
|
|
21230
|
-
}
|
|
21231
|
-
}, refreshInterval);
|
|
21232
|
-
}
|
|
21233
21468
|
/** Persist credential to localStorage when persistSession is enabled. */
|
|
21234
21469
|
persistCredential(credential) {
|
|
21235
21470
|
if (!credential.token) return;
|
|
@@ -21323,6 +21558,7 @@ var SignalWire = class extends Destroyable {
|
|
|
21323
21558
|
logger$1.debug("[SignalWire] Credential expired, refreshing before reconnect");
|
|
21324
21559
|
const newCredentials = await this._credentialProvider.authenticate(fingerprint ? { fingerprint } : void 0);
|
|
21325
21560
|
this._deps.credential = newCredentials;
|
|
21561
|
+
if (newCredentials.expiry_at && this._credentialProvider.refresh) this._refreshCoordinator?.scheduleDeveloperRefresh(this._credentialProvider, newCredentials.expiry_at);
|
|
21326
21562
|
logger$1.debug("[SignalWire] Credential refreshed successfully for reconnect");
|
|
21327
21563
|
} catch (error) {
|
|
21328
21564
|
logger$1.error("[SignalWire] Failed to refresh credentials for reconnect:", error);
|
|
@@ -21334,33 +21570,12 @@ var SignalWire = class extends Destroyable {
|
|
|
21334
21570
|
this._errors$.next(error);
|
|
21335
21571
|
});
|
|
21336
21572
|
await this._clientSession.connect();
|
|
21337
|
-
|
|
21338
|
-
if (this._refreshTimerId) {
|
|
21339
|
-
clearTimeout(this._refreshTimerId);
|
|
21340
|
-
this._refreshTimerId = void 0;
|
|
21341
|
-
logger$1.debug("[SignalWire] Developer refresh disabled — Client Bound SAT activation starting");
|
|
21342
|
-
}
|
|
21343
|
-
this._deviceTokenManager = new DeviceTokenManager(this._dpopManager, this._deps.http, (error) => this._errors$.next(error), () => this._deps.credential);
|
|
21344
|
-
await this._deviceTokenManager.activate(this._deps.user, this._clientSession, (cred) => {
|
|
21345
|
-
this._deps.credential = {
|
|
21346
|
-
...this._deps.credential,
|
|
21347
|
-
...cred
|
|
21348
|
-
};
|
|
21349
|
-
});
|
|
21350
|
-
}
|
|
21573
|
+
await this._refreshCoordinator?.activate(this._deps.user, this._clientSession);
|
|
21351
21574
|
this.subscribeTo(this._clientSession.authenticated$.pipe((0, import_cjs$1.skip)(1), (0, import_cjs$1.filter)(Boolean)), async () => {
|
|
21352
21575
|
try {
|
|
21353
|
-
|
|
21354
|
-
await this._deviceTokenManager.activate(this._deps.user, this._clientSession, (cred) => {
|
|
21355
|
-
this._deps.credential = {
|
|
21356
|
-
...this._deps.credential,
|
|
21357
|
-
...cred
|
|
21358
|
-
};
|
|
21359
|
-
});
|
|
21360
|
-
logger$1.debug("[SignalWire] Client Bound SAT re-activated after reconnect");
|
|
21361
|
-
}
|
|
21576
|
+
await this._refreshCoordinator?.activate(this._deps.user, this._clientSession);
|
|
21362
21577
|
} catch (error) {
|
|
21363
|
-
logger$1.error("[SignalWire]
|
|
21578
|
+
logger$1.error("[SignalWire] Refresh re-arm after reconnect failed (non-fatal):", error);
|
|
21364
21579
|
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
21365
21580
|
}
|
|
21366
21581
|
try {
|
|
@@ -21446,6 +21661,19 @@ var SignalWire = class extends Destroyable {
|
|
|
21446
21661
|
get errors$() {
|
|
21447
21662
|
return this.deferEmission(this._errors$.asObservable());
|
|
21448
21663
|
}
|
|
21664
|
+
/**
|
|
21665
|
+
* Observable stream of non-fatal SDK warnings.
|
|
21666
|
+
*
|
|
21667
|
+
* Subscribe to detect SDK behaviors that affect session liveness or developer-facing
|
|
21668
|
+
* contracts but do not warrant disconnection — e.g., a fallback from Client Bound SAT
|
|
21669
|
+
* refresh to the developer-provided `refresh()` because the SAT lacks `sat:refresh`
|
|
21670
|
+
* scope. Discriminated by `code`.
|
|
21671
|
+
*
|
|
21672
|
+
* Independent from {@link errors$}: existing error consumers are not notified.
|
|
21673
|
+
*/
|
|
21674
|
+
get warnings$() {
|
|
21675
|
+
return this.deferEmission(this._warnings$.asObservable());
|
|
21676
|
+
}
|
|
21449
21677
|
/** Platform WebRTC capabilities detected at construction time. */
|
|
21450
21678
|
get platformCapabilities() {
|
|
21451
21679
|
this._platformCapabilities ??= detectPlatformCapabilities(this._options.webRTCApiProvider);
|
|
@@ -21514,7 +21742,7 @@ var SignalWire = class extends Destroyable {
|
|
|
21514
21742
|
logger$1.warn("[SignalWire] Failed to initialize VisibilityController:", error);
|
|
21515
21743
|
}
|
|
21516
21744
|
try {
|
|
21517
|
-
this._diagnosticsCollector = new DiagnosticsCollector({ sdkVersion: "
|
|
21745
|
+
this._diagnosticsCollector = new DiagnosticsCollector({ sdkVersion: "4.0.0-rc.0" });
|
|
21518
21746
|
} catch (error) {
|
|
21519
21747
|
logger$1.warn("[SignalWire] Failed to initialize DiagnosticsCollector:", error);
|
|
21520
21748
|
}
|
|
@@ -21526,10 +21754,7 @@ var SignalWire = class extends Destroyable {
|
|
|
21526
21754
|
* which creates a fresh transport and session.
|
|
21527
21755
|
*/
|
|
21528
21756
|
async disconnect() {
|
|
21529
|
-
|
|
21530
|
-
clearTimeout(this._refreshTimerId);
|
|
21531
|
-
this._refreshTimerId = void 0;
|
|
21532
|
-
}
|
|
21757
|
+
this._refreshCoordinator?.suspend();
|
|
21533
21758
|
this._diagnosticsCollector?.record("connection", "disconnected");
|
|
21534
21759
|
await this.teardownTransportAndSession();
|
|
21535
21760
|
this._isConnected$.next(false);
|
|
@@ -21918,11 +22143,8 @@ var SignalWire = class extends Destroyable {
|
|
|
21918
22143
|
}
|
|
21919
22144
|
/** Destroys the client, clearing timers and releasing all resources. */
|
|
21920
22145
|
destroy() {
|
|
21921
|
-
|
|
21922
|
-
|
|
21923
|
-
this._refreshTimerId = void 0;
|
|
21924
|
-
}
|
|
21925
|
-
this._deviceTokenManager?.destroy();
|
|
22146
|
+
this._refreshCoordinator?.destroy();
|
|
22147
|
+
this._refreshCoordinator = void 0;
|
|
21926
22148
|
this._dpopManager?.destroy();
|
|
21927
22149
|
if (this._attachManager) this._attachManager.detachAll();
|
|
21928
22150
|
this._transport.destroy();
|
|
@@ -22039,7 +22261,7 @@ var StaticCredentialProvider = class {
|
|
|
22039
22261
|
/**
|
|
22040
22262
|
* Library version from package.json, injected at build time.
|
|
22041
22263
|
*/
|
|
22042
|
-
const version = "
|
|
22264
|
+
const version = "4.0.0-rc.0";
|
|
22043
22265
|
/**
|
|
22044
22266
|
* Flag indicating the library has been loaded and is ready to use.
|
|
22045
22267
|
* For UMD builds: `window.SignalWire.ready`
|
|
@@ -22061,7 +22283,7 @@ const ready = true;
|
|
|
22061
22283
|
*/
|
|
22062
22284
|
const emitReadyEvent = () => {
|
|
22063
22285
|
if (typeof window !== "undefined") {
|
|
22064
|
-
const event = new CustomEvent("signalwire:js:ready", { detail: { version: "
|
|
22286
|
+
const event = new CustomEvent("signalwire:js:ready", { detail: { version: "4.0.0-rc.0" } });
|
|
22065
22287
|
window.dispatchEvent(event);
|
|
22066
22288
|
}
|
|
22067
22289
|
};
|