@signalwire/js 4.0.0-dev-20260311213302 → 4.0.0-dev-20260318132643

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,30 @@
1
+ //#region src/core/RPCMessages/types/base.d.ts
2
+ type EventChannel = string | string[];
3
+ type JSONRPCVersion = '2.0';
4
+ type JSONRPCMethod = string;
5
+ interface JSONRPCRequest<TParams = unknown> {
6
+ jsonrpc: JSONRPCVersion;
7
+ id: string;
8
+ method: JSONRPCMethod;
9
+ params?: TParams;
10
+ }
11
+ interface JSONRPCSuccessResponse<TResult = unknown> {
12
+ jsonrpc: '2.0';
13
+ id: string;
14
+ result: TResult;
15
+ error?: never;
16
+ }
17
+ interface JSONRPCErrorResponse {
18
+ jsonrpc: '2.0';
19
+ id: string;
20
+ result?: never;
21
+ error: {
22
+ code: number;
23
+ message: string;
24
+ data?: unknown;
25
+ };
26
+ }
27
+ type JSONRPCResponse<TResult = unknown> = JSONRPCSuccessResponse<TResult> | JSONRPCErrorResponse;
28
+ //#endregion
29
+ export { JSONRPCSuccessResponse as a, JSONRPCResponse as i, JSONRPCErrorResponse as n, JSONRPCRequest as r, EventChannel as t };
30
+ //# sourceMappingURL=base-BxFSgMTI.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base-A5AZTrAd.d.cts","names":[],"sources":["../src/core/RPCMessages/types/base.ts"],"sourcesContent":[],"mappings":";KAUY,YAAA;AAOA,KAAA,cAAA,GAAc,KAAA;AACd,KAAA,aAAA,GAAa,MAAA;AAER,UAAA,cAAc,CAAA,UAAA,OAAA,CAAA,CAAA;EACpB,OAAA,EAAA,cAAA;EAED,EAAA,EAAA,MAAA;EACC,MAAA,EADD,aACC;EAAO,MAAA,CAAA,EAAP,OAAO;AAGlB;UAAiB;;;WAGN"}
1
+ {"version":3,"file":"base-BxFSgMTI.d.cts","names":[],"sources":["../src/core/RPCMessages/types/base.ts"],"sourcesContent":[],"mappings":";KAUY,YAAA;AAOA,KAAA,cAAA,GAAc,KAAA;AACd,KAAA,aAAA,GAAa,MAAA;AAER,UAAA,cAAc,CAAA,UAAA,OAAA,CAAA,CAAA;EACpB,OAAA,EAAA,cAAA;EAED,EAAA,EAAA,MAAA;EACC,MAAA,EADD,aACC;EAAO,MAAA,CAAA,EAAP,OAAO;AAGlB;AAOiB,UAPA,sBAOoB,CAAA,UAAA,OAAA,CAAA,CAAA;EAOzB,OAAA,EAAA,KAAA;EACe,EAAA,EAAA,MAAA;EAAvB,MAAA,EAZM,OAYN;EACA,KAAA,CAAA,EAAA,KAAA;;UATa,oBAAA;;;;;;;;;;KAOL,qCACR,uBAAuB,WACvB"}
@@ -0,0 +1,30 @@
1
+ //#region src/core/RPCMessages/types/base.d.ts
2
+ type EventChannel = string | string[];
3
+ type JSONRPCVersion = '2.0';
4
+ type JSONRPCMethod = string;
5
+ interface JSONRPCRequest<TParams = unknown> {
6
+ jsonrpc: JSONRPCVersion;
7
+ id: string;
8
+ method: JSONRPCMethod;
9
+ params?: TParams;
10
+ }
11
+ interface JSONRPCSuccessResponse<TResult = unknown> {
12
+ jsonrpc: '2.0';
13
+ id: string;
14
+ result: TResult;
15
+ error?: never;
16
+ }
17
+ interface JSONRPCErrorResponse {
18
+ jsonrpc: '2.0';
19
+ id: string;
20
+ result?: never;
21
+ error: {
22
+ code: number;
23
+ message: string;
24
+ data?: unknown;
25
+ };
26
+ }
27
+ type JSONRPCResponse<TResult = unknown> = JSONRPCSuccessResponse<TResult> | JSONRPCErrorResponse;
28
+ //#endregion
29
+ export { JSONRPCSuccessResponse as a, JSONRPCResponse as i, JSONRPCErrorResponse as n, JSONRPCRequest as r, EventChannel as t };
30
+ //# sourceMappingURL=base-DKDZK4Rr.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base-aVtoG8Wk.d.mts","names":[],"sources":["../src/core/RPCMessages/types/base.ts"],"sourcesContent":[],"mappings":";KAUY,YAAA;AAOA,KAAA,cAAA,GAAc,KAAA;AACd,KAAA,aAAA,GAAa,MAAA;AAER,UAAA,cAAc,CAAA,UAAA,OAAA,CAAA,CAAA;EACpB,OAAA,EAAA,cAAA;EAED,EAAA,EAAA,MAAA;EACC,MAAA,EADD,aACC;EAAO,MAAA,CAAA,EAAP,OAAO;AAGlB;UAAiB;;;WAGN"}
1
+ {"version":3,"file":"base-DKDZK4Rr.d.mts","names":[],"sources":["../src/core/RPCMessages/types/base.ts"],"sourcesContent":[],"mappings":";KAUY,YAAA;AAOA,KAAA,cAAA,GAAc,KAAA;AACd,KAAA,aAAA,GAAa,MAAA;AAER,UAAA,cAAc,CAAA,UAAA,OAAA,CAAA,CAAA;EACpB,OAAA,EAAA,cAAA;EAED,EAAA,EAAA,MAAA;EACC,MAAA,EADD,aACC;EAAO,MAAA,CAAA,EAAP,OAAO;AAGlB;AAOiB,UAPA,sBAOoB,CAAA,UAAA,OAAA,CAAA,CAAA;EAOzB,OAAA,EAAA,KAAA;EACe,EAAA,EAAA,MAAA;EAAvB,MAAA,EAZM,OAYN;EACA,KAAA,CAAA,EAAA,KAAA;;UATa,oBAAA;;;;;;;;;;KAOL,qCACR,uBAAuB,WACvB"}
package/dist/browser.mjs CHANGED
@@ -3107,7 +3107,7 @@ var require_throwError = /* @__PURE__ */ __commonJSMin(((exports) => {
3107
3107
  exports.throwError = void 0;
3108
3108
  var Observable_1$18 = require_Observable();
3109
3109
  var isFunction_1$14 = require_isFunction();
3110
- function throwError(errorOrErrorFactory, scheduler) {
3110
+ function throwError$1(errorOrErrorFactory, scheduler) {
3111
3111
  var errorFactory = isFunction_1$14.isFunction(errorOrErrorFactory) ? errorOrErrorFactory : function() {
3112
3112
  return errorOrErrorFactory;
3113
3113
  };
@@ -3118,7 +3118,7 @@ var require_throwError = /* @__PURE__ */ __commonJSMin(((exports) => {
3118
3118
  return scheduler.schedule(init, 0, subscriber);
3119
3119
  } : init);
3120
3120
  }
3121
- exports.throwError = throwError;
3121
+ exports.throwError = throwError$1;
3122
3122
  }));
3123
3123
 
3124
3124
  //#endregion
@@ -4327,13 +4327,13 @@ var require_race$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
4327
4327
  var innerFrom_1$28 = require_innerFrom();
4328
4328
  var argsOrArgArray_1$4 = require_argsOrArgArray();
4329
4329
  var OperatorSubscriber_1$48 = require_OperatorSubscriber();
4330
- function race$3() {
4330
+ function race$4() {
4331
4331
  var sources = [];
4332
4332
  for (var _i = 0; _i < arguments.length; _i++) sources[_i] = arguments[_i];
4333
4333
  sources = argsOrArgArray_1$4.argsOrArgArray(sources);
4334
4334
  return sources.length === 1 ? innerFrom_1$28.innerFrom(sources[0]) : new Observable_1$6.Observable(raceInit(sources));
4335
4335
  }
4336
- exports.race = race$3;
4336
+ exports.race = race$4;
4337
4337
  function raceInit(sources) {
4338
4338
  return function(subscriber) {
4339
4339
  var subscriptions = [];
@@ -5470,7 +5470,7 @@ var require_distinctUntilChanged = /* @__PURE__ */ __commonJSMin(((exports) => {
5470
5470
  var identity_1$10 = require_identity();
5471
5471
  var lift_1$42 = require_lift();
5472
5472
  var OperatorSubscriber_1$31 = require_OperatorSubscriber();
5473
- function distinctUntilChanged$5(comparator, keySelector) {
5473
+ function distinctUntilChanged$6(comparator, keySelector) {
5474
5474
  if (keySelector === void 0) keySelector = identity_1$10.identity;
5475
5475
  comparator = comparator !== null && comparator !== void 0 ? comparator : defaultCompare;
5476
5476
  return lift_1$42.operate(function(source, subscriber) {
@@ -5486,7 +5486,7 @@ var require_distinctUntilChanged = /* @__PURE__ */ __commonJSMin(((exports) => {
5486
5486
  }));
5487
5487
  });
5488
5488
  }
5489
- exports.distinctUntilChanged = distinctUntilChanged$5;
5489
+ exports.distinctUntilChanged = distinctUntilChanged$6;
5490
5490
  function defaultCompare(a, b) {
5491
5491
  return a === b;
5492
5492
  }
@@ -6934,7 +6934,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
6934
6934
  var innerFrom_1$6 = require_innerFrom();
6935
6935
  var lift_1$13 = require_lift();
6936
6936
  var OperatorSubscriber_1$11 = require_OperatorSubscriber();
6937
- function switchMap$3(project, resultSelector) {
6937
+ function switchMap$4(project, resultSelector) {
6938
6938
  return lift_1$13.operate(function(source, subscriber) {
6939
6939
  var innerSubscriber = null;
6940
6940
  var index = 0;
@@ -6958,7 +6958,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
6958
6958
  }));
6959
6959
  });
6960
6960
  }
6961
- exports.switchMap = switchMap$3;
6961
+ exports.switchMap = switchMap$4;
6962
6962
  }));
6963
6963
 
6964
6964
  //#endregion
@@ -9104,13 +9104,14 @@ var DependencyError = class extends Error {
9104
9104
  }
9105
9105
  };
9106
9106
  var CallCreateError = class extends Error {
9107
- constructor(message, error = null, options) {
9107
+ constructor(message, error = null, direction = "outbound", options) {
9108
9108
  super(message, {
9109
9109
  ...options,
9110
9110
  cause: options?.cause ?? (error instanceof Error ? error : void 0)
9111
9111
  });
9112
9112
  this.message = message;
9113
9113
  this.error = error;
9114
+ this.direction = direction;
9114
9115
  this.name = "CallCreateError";
9115
9116
  }
9116
9117
  };
@@ -9982,7 +9983,7 @@ var NavigatorDeviceController = class extends Destroyable {
9982
9983
  };
9983
9984
  this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
9984
9985
  this._selectedDevicesState$ = this.createBehaviorSubject(initialSelectedDevicesState);
9985
- this._errors$ = this.createSubject();
9986
+ this._errors$ = this.createReplaySubject(1);
9986
9987
  this.init();
9987
9988
  }
9988
9989
  get selectedAudioInputDeviceConstraints() {
@@ -10509,7 +10510,7 @@ const RPCExecute = ({ method, params }) => {
10509
10510
 
10510
10511
  //#endregion
10511
10512
  //#region src/core/RPCMessages/VertoMessages.ts
10512
- const tmpMap = {
10513
+ const SDK_TO_VERTO_FIELD_MAP = {
10513
10514
  id: "callID",
10514
10515
  destinationNumber: "destination_number",
10515
10516
  remoteCallerName: "remote_caller_id_name",
@@ -10518,19 +10519,31 @@ const tmpMap = {
10518
10519
  callerNumber: "caller_id_number",
10519
10520
  fromCallAddressId: "from_fabric_address_id"
10520
10521
  };
10522
+ const EXCLUDED_DIALOG_PARAMS = new Set([
10523
+ "remoteSdp",
10524
+ "localStream",
10525
+ "remoteStream"
10526
+ ]);
10521
10527
  /**
10522
- * Translate SDK fields into verto variables
10528
+ * Translate SDK fields into verto variables.
10529
+ * Returns a new object — the input is never mutated.
10523
10530
  */
10531
+ /** @internal Exported for testing only. */
10524
10532
  const filterVertoParams = (params) => {
10525
- if (Object.prototype.hasOwnProperty.call(params, "dialogParams")) {
10526
- const { remoteSdp, localStream, remoteStream, ...dialogParams } = params.dialogParams;
10527
- for (const key in tmpMap) if (key && Object.prototype.hasOwnProperty.call(dialogParams, key)) {
10528
- dialogParams[tmpMap[key]] = dialogParams[key];
10529
- delete dialogParams[key];
10530
- }
10531
- params.dialogParams = dialogParams;
10532
- }
10533
- return params;
10533
+ if (!Object.prototype.hasOwnProperty.call(params, "dialogParams")) return params;
10534
+ const sourceDialogParams = params.dialogParams;
10535
+ const filteredDialogParams = Object.entries(sourceDialogParams).reduce((acc, [key, value]) => {
10536
+ if (EXCLUDED_DIALOG_PARAMS.has(key)) return acc;
10537
+ const mappedKey = SDK_TO_VERTO_FIELD_MAP[key] ?? key;
10538
+ return {
10539
+ ...acc,
10540
+ [mappedKey]: value
10541
+ };
10542
+ }, {});
10543
+ return {
10544
+ ...params,
10545
+ dialogParams: filteredDialogParams
10546
+ };
10534
10547
  };
10535
10548
  const buildVertoRPCMessage = (method) => {
10536
10549
  return (params = {}) => {
@@ -10712,12 +10725,12 @@ var require_race = /* @__PURE__ */ __commonJSMin(((exports) => {
10712
10725
  exports.race = void 0;
10713
10726
  var argsOrArgArray_1 = require_argsOrArgArray();
10714
10727
  var raceWith_1$1 = require_raceWith();
10715
- function race$2() {
10728
+ function race$3() {
10716
10729
  var args = [];
10717
10730
  for (var _i = 0; _i < arguments.length; _i++) args[_i] = arguments[_i];
10718
10731
  return raceWith_1$1.raceWith.apply(void 0, __spreadArray([], __read(argsOrArgArray_1.argsOrArgArray(args))));
10719
10732
  }
10720
- exports.race = race$2;
10733
+ exports.race = race$3;
10721
10734
  }));
10722
10735
 
10723
10736
  //#endregion
@@ -12416,7 +12429,6 @@ var CallEventsManager = class extends Destroyable {
12416
12429
  this.options = options;
12417
12430
  this.callIds = /* @__PURE__ */ new Set();
12418
12431
  this.roomSessionIds = /* @__PURE__ */ new Set();
12419
- this._status$ = this.createBehaviorSubject("trying");
12420
12432
  this._participants$ = this.createBehaviorSubject({});
12421
12433
  this._self$ = this.createBehaviorSubject(null);
12422
12434
  this._sessionState$ = this.createBehaviorSubject(initialSessionState);
@@ -12431,12 +12443,6 @@ var CallEventsManager = class extends Destroyable {
12431
12443
  get self$() {
12432
12444
  return this.cachedObservable("self$", () => this._self$.asObservable().pipe(filterNull()));
12433
12445
  }
12434
- get status$() {
12435
- return this._status$.asObservable();
12436
- }
12437
- get status() {
12438
- return this._status$.value;
12439
- }
12440
12446
  isRoomSessionIdValid(roomSessionId) {
12441
12447
  return this.roomSessionIds.has(roomSessionId);
12442
12448
  }
@@ -12521,7 +12527,6 @@ var CallEventsManager = class extends Destroyable {
12521
12527
  callId: callJoinedEvent.call_id,
12522
12528
  roomSessionId: callJoinedEvent.room_session_id
12523
12529
  });
12524
- this._status$.next("connected");
12525
12530
  const sessionState = callJoinedEvent.room_session;
12526
12531
  const { capabilities } = callJoinedEvent;
12527
12532
  this.selfId = this.selfId ?? callJoinedEvent.member_id;
@@ -13344,7 +13349,7 @@ var RTCPeerConnectionController = class extends Destroyable {
13344
13349
  this._connectionState$ = this.createReplaySubject(1);
13345
13350
  this._signalingState$ = this.createReplaySubject(1);
13346
13351
  this._iceGatheringState$ = this.createReplaySubject(1);
13347
- this._errors$ = this.createSubject();
13352
+ this._errors$ = this.createReplaySubject(1);
13348
13353
  this._iceCandidates$ = this.createReplaySubject(1);
13349
13354
  this._initialized$ = this.createReplaySubject(1);
13350
13355
  this._remoteDescription$ = this.createReplaySubject(1);
@@ -13785,37 +13790,29 @@ var RTCPeerConnectionController = class extends Destroyable {
13785
13790
  }
13786
13791
  async setupLocalTracks() {
13787
13792
  logger$11.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
13788
- let { localStream } = this;
13789
- if (!localStream) try {
13790
- localStream = await this.localStreamController.buildLocalStream();
13791
- } catch (error) {
13792
- logger$11.error("[RTCPeerConnectionController] Error building local stream:", error);
13793
- this._errors$.next(error);
13794
- }
13795
- if (localStream) {
13796
- if (this.transceiverController?.useAddStream ?? false) {
13797
- logger$11.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
13798
- this.peerConnection?.addStream(localStream);
13799
- if (!this.isNegotiating) {
13800
- logger$11.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
13801
- this.negotiationNeeded$.next();
13802
- }
13803
- return;
13793
+ const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
13794
+ if (this.transceiverController?.useAddStream ?? false) {
13795
+ logger$11.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
13796
+ this.peerConnection?.addStream(localStream);
13797
+ if (!this.isNegotiating) {
13798
+ logger$11.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
13799
+ this.negotiationNeeded$.next();
13804
13800
  }
13805
- for (const kind of ["audio", "video"]) {
13806
- const tracks = (kind === "audio" ? localStream.getAudioTracks() : localStream.getVideoTracks()).map((track, index) => ({
13807
- index,
13808
- track
13809
- }));
13810
- for (const { index, track } of tracks) {
13811
- this.localStreamController.addTrackEndedListener(track);
13812
- if (this.transceiverController?.useAddTransceivers ?? false) {
13813
- const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
13814
- await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
13815
- } else {
13816
- logger$11.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
13817
- this.peerConnection?.addTrack(track, localStream);
13818
- }
13801
+ return;
13802
+ }
13803
+ for (const kind of ["audio", "video"]) {
13804
+ const tracks = (kind === "audio" ? localStream.getAudioTracks() : localStream.getVideoTracks()).map((track, index) => ({
13805
+ index,
13806
+ track
13807
+ }));
13808
+ for (const { index, track } of tracks) {
13809
+ this.localStreamController.addTrackEndedListener(track);
13810
+ if (this.transceiverController?.useAddTransceivers ?? false) {
13811
+ const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
13812
+ await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
13813
+ } else {
13814
+ logger$11.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
13815
+ this.peerConnection?.addTrack(track, localStream);
13819
13816
  }
13820
13817
  }
13821
13818
  }
@@ -14091,6 +14088,7 @@ var WebRTCVertoManager = class extends VertoManager {
14091
14088
  });
14092
14089
  this.subscribeTo(this.vertoAnswer$, (event) => {
14093
14090
  logger$10.debug("[WebRTCManager] Received Verto answer event:", event);
14091
+ this._signalingStatus$.next("connecting");
14094
14092
  const { sdp, callID } = event;
14095
14093
  this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
14096
14094
  status: "received",
@@ -14162,13 +14160,13 @@ var WebRTCVertoManager = class extends VertoManager {
14162
14160
  if (response.error) {
14163
14161
  const error = new JSONRPCError(response.error.code, response.error.message, response.error.data);
14164
14162
  this.onError?.(error);
14165
- throw error;
14163
+ return response;
14166
14164
  }
14167
14165
  const innerResult = getValueFrom(response, "result.result");
14168
14166
  if (innerResult?.error) {
14169
14167
  const error = new JSONRPCError(innerResult.error.code, innerResult.error.message, innerResult.error.data);
14170
14168
  this.onError?.(error);
14171
- throw error;
14169
+ return response;
14172
14170
  }
14173
14171
  return response;
14174
14172
  }
@@ -14188,7 +14186,7 @@ var WebRTCVertoManager = class extends VertoManager {
14188
14186
  }
14189
14187
  } catch (error) {
14190
14188
  logger$10.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
14191
- throw error;
14189
+ this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
14192
14190
  }
14193
14191
  }
14194
14192
  async processModifyResponse(response, rtcPeerConnController) {
@@ -14202,12 +14200,14 @@ var WebRTCVertoManager = class extends VertoManager {
14202
14200
  });
14203
14201
  } catch (error) {
14204
14202
  logger$10.warn("[WebRTCManager] Error processing modify response:", error);
14205
- this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
14203
+ const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
14204
+ this.onError?.(modifyError);
14206
14205
  }
14207
14206
  }
14208
14207
  }
14209
14208
  processInviteResponse(response, rtcPeerConnController) {
14210
14209
  if (!response.error && getValueFrom(response, "result.result.result.message") === "CALL CREATED") {
14210
+ this._signalingStatus$.next("trying");
14211
14211
  this._nodeId$.next(getValueFrom(response, "result.node_id") ?? null);
14212
14212
  const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
14213
14213
  const callId = getValueFrom(response, "result.result.result.callID") ?? null;
@@ -14325,7 +14325,6 @@ var WebRTCVertoManager = class extends VertoManager {
14325
14325
  });
14326
14326
  this.sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnController);
14327
14327
  } else if (initial) {
14328
- this._signalingStatus$.next("trying");
14329
14328
  const vertoMessageRequest = VertoInvite({
14330
14329
  dialogParams,
14331
14330
  sdp
@@ -14632,7 +14631,8 @@ var WebRTCCall = class extends Destroyable {
14632
14631
  this.clientSession = clientSession;
14633
14632
  this.options = options;
14634
14633
  this.address = address;
14635
- this._errors$ = this.createSubject();
14634
+ this._errors$ = this.createReplaySubject(1);
14635
+ this._lastMergedStatus = "new";
14636
14636
  this._answered$ = this.createReplaySubject();
14637
14637
  this._holdState = false;
14638
14638
  this._userVariables$ = this.createBehaviorSubject({ ...PreferencesContainer.instance.userVariables });
@@ -14653,8 +14653,10 @@ var WebRTCCall = class extends Destroyable {
14653
14653
  const managers = initialization.initializeManagers(this);
14654
14654
  this.vertoManager = managers.vertoManager;
14655
14655
  this.callEventsManager = managers.callEventsManager;
14656
- if (options.initOffer) this._status$ = this.createBehaviorSubject("ringing");
14657
- else this._status$ = this.createBehaviorSubject("new");
14656
+ if (options.initOffer) {
14657
+ this._status$ = this.createBehaviorSubject("ringing");
14658
+ this._lastMergedStatus = "ringing";
14659
+ } else this._status$ = this.createBehaviorSubject("new");
14658
14660
  const { deviceController } = initialization;
14659
14661
  this.participantFactory = new ParticipantFactory(this.executeMethod.bind(this), this.vertoManager, deviceController);
14660
14662
  }
@@ -14662,9 +14664,17 @@ var WebRTCCall = class extends Destroyable {
14662
14664
  get errors$() {
14663
14665
  return this._errors$.asObservable();
14664
14666
  }
14665
- /** @internal Push an error to the call's error stream. */
14666
- emitError(error) {
14667
- this._errors$.next(error);
14667
+ /**
14668
+ * @internal Push an error to the call's error stream.
14669
+ * Fatal errors automatically transition the call to `'failed'` and destroy it.
14670
+ */
14671
+ emitError(callError) {
14672
+ if (this._status$.value === "destroyed" || this._status$.value === "failed") return;
14673
+ this._errors$.next(callError);
14674
+ if (callError.fatal) {
14675
+ this._status$.next("failed");
14676
+ this.destroy();
14677
+ }
14668
14678
  }
14669
14679
  /** Whether this call is `'inbound'` or `'outbound'`. */
14670
14680
  get direction() {
@@ -14776,7 +14786,9 @@ var WebRTCCall = class extends Destroyable {
14776
14786
  }
14777
14787
  /** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
14778
14788
  get status$() {
14779
- return this.cachedObservable("status$", () => (0, import_cjs$9.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$));
14789
+ return this.cachedObservable("status$", () => (0, import_cjs$9.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.tap)((status) => {
14790
+ this._lastMergedStatus = status;
14791
+ })));
14780
14792
  }
14781
14793
  /** Observable of the participants list, emits on join/leave/update. */
14782
14794
  get participants$() {
@@ -14816,7 +14828,7 @@ var WebRTCCall = class extends Destroyable {
14816
14828
  }
14817
14829
  /** Current call status. */
14818
14830
  get status() {
14819
- return this._status$.value;
14831
+ return this._lastMergedStatus;
14820
14832
  }
14821
14833
  /** Whether the call is currently being recorded. */
14822
14834
  get recording() {
@@ -15029,6 +15041,7 @@ var WebRTCCall = class extends Destroyable {
15029
15041
  }
15030
15042
  /** Destroys the call, releasing all resources and subscriptions. */
15031
15043
  destroy() {
15044
+ if (this._status$.value === "destroyed") return;
15032
15045
  this._status$.next("destroyed");
15033
15046
  this.vertoManager.destroy();
15034
15047
  this.callEventsManager.destroy();
@@ -15039,6 +15052,23 @@ var WebRTCCall = class extends Destroyable {
15039
15052
  //#endregion
15040
15053
  //#region src/managers/CallFactory.ts
15041
15054
  /**
15055
+ * Infers the semantic error category from a raw Error thrown by VertoManager
15056
+ * or an RTCPeerConnection layer.
15057
+ */
15058
+ function inferCallErrorKind(error) {
15059
+ if (error instanceof RPCTimeoutError) return "timeout";
15060
+ if (error instanceof JSONRPCError) return "signaling";
15061
+ if (error instanceof MediaTrackError) return "media";
15062
+ if (error instanceof WebSocketConnectionError || error instanceof TransportConnectionError) return "network";
15063
+ return "internal";
15064
+ }
15065
+ /** Determines whether an error should be fatal (destroy the call). */
15066
+ function isFatalError(error) {
15067
+ if (error instanceof VertoPongError) return false;
15068
+ if (error instanceof MediaTrackError) return false;
15069
+ return true;
15070
+ }
15071
+ /**
15042
15072
  * Factory for creating WebRTCCall instances with proper manager wiring.
15043
15073
  * Eliminates circular dependencies by centralizing Call and Manager creation.
15044
15074
  */
@@ -15059,7 +15089,13 @@ var CallFactory = class {
15059
15089
  vertoManager: new WebRTCVertoManager(callInstance, this.attachManager, this.deviceController, this.webRTCApiProvider, {
15060
15090
  nodeId: options.nodeId,
15061
15091
  onError: (error) => {
15062
- callInstance.emitError(error);
15092
+ const callError = {
15093
+ kind: inferCallErrorKind(error),
15094
+ fatal: isFatalError(error),
15095
+ error,
15096
+ callId: callInstance.id
15097
+ };
15098
+ callInstance.emitError(callError);
15063
15099
  }
15064
15100
  }),
15065
15101
  callEventsManager: new CallEventsManager(callInstance)
@@ -15504,7 +15540,7 @@ var ClientSessionManager = class extends Destroyable {
15504
15540
  revision: 0
15505
15541
  };
15506
15542
  this._authorization$ = this.createBehaviorSubject(void 0);
15507
- this._errors$ = this.createSubject();
15543
+ this._errors$ = this.createReplaySubject(1);
15508
15544
  this._authenticated$ = this.createBehaviorSubject(false);
15509
15545
  this._subscriberInfo$ = this.createBehaviorSubject(null);
15510
15546
  this._calls$ = this.createBehaviorSubject({});
@@ -15774,12 +15810,13 @@ var ClientSessionManager = class extends Destroyable {
15774
15810
  }
15775
15811
  async createOutboundCall(destination, options = {}) {
15776
15812
  const destinationURI = destination instanceof Address ? destination.defaultChannel : destination;
15813
+ let callSession;
15777
15814
  try {
15778
- const callSession = await this.createCall({
15815
+ callSession = await this.createCall({
15779
15816
  to: destinationURI,
15780
15817
  ...options
15781
15818
  });
15782
- await (0, import_cjs$5.firstValueFrom)(callSession.selfId$.pipe((0, import_cjs$5.filter)((id) => Boolean(id)), (0, import_cjs$5.take)(1), (0, import_cjs$5.timeout)(this.callCreateTimeout)));
15819
+ await (0, import_cjs$5.firstValueFrom)((0, import_cjs$5.race)(callSession.selfId$.pipe((0, import_cjs$5.filter)((id) => Boolean(id)), (0, import_cjs$5.take)(1), (0, import_cjs$5.timeout)(this.callCreateTimeout)), callSession.errors$.pipe((0, import_cjs$5.take)(1), (0, import_cjs$5.switchMap)((callError) => (0, import_cjs$5.throwError)(() => callError.error)))));
15783
15820
  this._calls$.next({
15784
15821
  [`${callSession.id}`]: callSession,
15785
15822
  ...this._calls$.value
@@ -15787,7 +15824,8 @@ var ClientSessionManager = class extends Destroyable {
15787
15824
  return callSession;
15788
15825
  } catch (error) {
15789
15826
  logger$6.error("[Session] Error creating outbound call:", error);
15790
- const callError = new CallCreateError("Call create timeout", error);
15827
+ callSession?.destroy();
15828
+ const callError = new CallCreateError(error instanceof import_cjs$5.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
15791
15829
  this._errors$.next(callError);
15792
15830
  throw callError;
15793
15831
  }
@@ -15813,7 +15851,7 @@ var ClientSessionManager = class extends Destroyable {
15813
15851
  return callSession;
15814
15852
  } catch (error) {
15815
15853
  logger$6.error("[Session] Error creating call session:", error);
15816
- throw new CallCreateError("Call create error", error);
15854
+ throw new CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
15817
15855
  }
15818
15856
  }
15819
15857
  destroy() {
@@ -16062,7 +16100,7 @@ var WebSocketController = class WebSocketController extends Destroyable {
16062
16100
  this.shouldReconnect = false;
16063
16101
  this._status$ = this.createBehaviorSubject("disconnected");
16064
16102
  this._incomingMessages$ = this.createSubject();
16065
- this._errors$ = this.createSubject();
16103
+ this._errors$ = this.createReplaySubject(1);
16066
16104
  this.reconnectDelayMin = options.reconnectDelayMin ?? WebSocketController.DEFAULT_RECONNECT_DELAY_MIN_MS;
16067
16105
  this.reconnectDelayMax = options.reconnectDelayMax ?? WebSocketController.DEFAULT_RECONNECT_DELAY_MAX_MS;
16068
16106
  this.connectionTimeout = options.connectionTimeout ?? WebSocketController.DEFAULT_CONNECTION_TIMEOUT_MS;
@@ -16420,7 +16458,7 @@ var SignalWire = class extends Destroyable {
16420
16458
  this._directory$ = this.createBehaviorSubject(void 0);
16421
16459
  this._isConnected$ = this.createBehaviorSubject(false);
16422
16460
  this._isRegistered$ = this.createBehaviorSubject(false);
16423
- this._errors$ = this.createSubject();
16461
+ this._errors$ = this.createReplaySubject(1);
16424
16462
  this._options = {};
16425
16463
  this._deps = new DependencyContainer();
16426
16464
  this._options = {