@signalwire/js 4.0.0-dev-20260420151734 → 4.0.0-dev-20260421201955

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/index.cjs CHANGED
@@ -143,7 +143,7 @@ const POST_PARAMS = {
143
143
  "Content-Type": "application/json"
144
144
  }
145
145
  };
146
- var HTTPRequestController = class HTTPRequestController {
146
+ var HTTPRequestController = class HTTPRequestController extends Destroyable {
147
147
  static {
148
148
  this.defaultMaxRetries = 3;
149
149
  }
@@ -164,11 +164,12 @@ var HTTPRequestController = class HTTPRequestController {
164
164
  ]);
165
165
  }
166
166
  constructor(baseURL, getCredential, options = {}) {
167
+ super();
167
168
  this.baseURL = baseURL;
168
169
  this.getCredential = getCredential;
169
- this._responses$ = new rxjs.Subject();
170
- this._errors$ = new rxjs.Subject();
171
- this._status$ = new rxjs.BehaviorSubject("idle");
170
+ this._responses$ = this.createSubject();
171
+ this._errors$ = this.createSubject();
172
+ this._status$ = this.createBehaviorSubject("idle");
172
173
  this.maxRetries = options.maxRetries ?? HTTPRequestController.defaultMaxRetries;
173
174
  this.retryDelayMin = options.retryDelayMin ?? HTTPRequestController.defaultRetryDelayMinMs;
174
175
  this.retryDelayMax = options.retryDelayMax ?? HTTPRequestController.defaultRetryDelayMaxMs;
@@ -478,6 +479,12 @@ const DEFAULT_ICE_DISCONNECTED_GRACE_PERIOD_MS = 3e3;
478
479
  const DEFAULT_ICE_RESTART_TIMEOUT_MS$1 = 5e3;
479
480
  /** Maximum recovery attempts before emitting 'max_attempts_reached'. */
480
481
  const DEFAULT_MAX_RECOVERY_ATTEMPTS = 3;
482
+ /** Upper bound in ms for waiting on iceGatheringState === 'complete' after an ICE restart. */
483
+ const ICE_GATHERING_COMPLETE_TIMEOUT_MS = 1e4;
484
+ /** Upper bound in ms for waiting on RTCPeerConnection.connectionState === 'connected' after a recovery ICE restart. */
485
+ const PEER_CONNECTION_RECOVERY_WAIT_MS = 5e3;
486
+ /** Polling interval in ms while waiting for RTCPeerConnection.connectionState to transition. */
487
+ const PEER_CONNECTION_RECOVERY_POLL_MS = 100;
481
488
  /** Whether to persist device selections to storage by default. */
482
489
  const DEFAULT_PERSIST_DEVICE_SELECTION = true;
483
490
  /** Whether to auto-apply device changes to active calls by default. */
@@ -2428,7 +2435,7 @@ var PreflightRunner = class extends Destroyable {
2428
2435
  const candidateTypes = /* @__PURE__ */ new Set();
2429
2436
  const startTime = Date.now();
2430
2437
  const gatheringComplete = new Promise((resolve) => {
2431
- const timer$2 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
2438
+ const timer$3 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
2432
2439
  peerConnection.onicecandidate = (event) => {
2433
2440
  if (event.candidate) {
2434
2441
  const candidateStr = event.candidate.candidate;
@@ -2436,7 +2443,7 @@ var PreflightRunner = class extends Destroyable {
2436
2443
  if (candidateStr.includes("typ srflx")) candidateTypes.add("srflx");
2437
2444
  if (candidateStr.includes("typ relay")) candidateTypes.add("relay");
2438
2445
  } else {
2439
- clearTimeout(timer$2);
2446
+ clearTimeout(timer$3);
2440
2447
  resolve();
2441
2448
  }
2442
2449
  };
@@ -2797,13 +2804,11 @@ var AttachManager = class {
2797
2804
  this.deviceController = deviceController;
2798
2805
  this.reconnectCallsTimeout = reconnectCallsTimeout;
2799
2806
  this.attachKey = attachKey;
2807
+ this.writeQueue = Promise.resolve();
2800
2808
  }
2801
2809
  async detachAll() {
2802
- const attached = await this.readAttached();
2803
- for (const callId of Object.keys(attached)) await this.detach({
2804
- id: callId,
2805
- nodeId: attached[callId].nodeId,
2806
- mediaDirections: attached[callId].mediaDirections
2810
+ await this.mutate((attached) => {
2811
+ return {};
2807
2812
  });
2808
2813
  }
2809
2814
  setSession(session) {
@@ -2824,31 +2829,47 @@ var AttachManager = class {
2824
2829
  logger$21.warn("[AttachManager] Failed to write attached calls to storage", error);
2825
2830
  }
2826
2831
  }
2832
+ /**
2833
+ * Serialize a read-modify-write operation against the attached-calls
2834
+ * storage. The mutator receives the current state and returns the new
2835
+ * state. Concurrent calls queue behind the in-flight one so writes never
2836
+ * interleave.
2837
+ */
2838
+ async mutate(mutator) {
2839
+ const next = this.writeQueue.then(async () => {
2840
+ const updated = await mutator(await this.readAttached());
2841
+ await this.writeAttached(updated);
2842
+ });
2843
+ this.writeQueue = next.catch(() => void 0);
2844
+ return next;
2845
+ }
2827
2846
  async attach(call) {
2828
2847
  if (!call.to) {
2829
2848
  logger$21.warn("[AttachManager] Skip attach for calls with no destination");
2830
2849
  return;
2831
2850
  }
2851
+ const destination = call.to;
2832
2852
  const attachment = {
2833
2853
  nodeId: call.nodeId,
2834
- destination: call.to,
2854
+ destination,
2835
2855
  mediaDirections: call.mediaDirections,
2836
2856
  audioInputDevice: call.mediaDirections.audio !== "inactive" ? this.deviceController.selectedAudioInputDevice : null,
2837
2857
  videoInputDevice: call.mediaDirections.video !== "inactive" ? this.deviceController.selectedVideoInputDevice : null,
2838
2858
  attachedAt: Date.now()
2839
2859
  };
2840
- const updated = {
2841
- ...await this.readAttached(),
2860
+ await this.mutate((attached) => ({
2861
+ ...attached,
2842
2862
  [call.id]: attachment
2843
- };
2844
- await this.writeAttached(updated);
2863
+ }));
2845
2864
  }
2846
2865
  async detach(call) {
2847
- const { [call.id]: _, ...remaining } = await this.readAttached();
2848
- await this.writeAttached(remaining);
2866
+ await this.mutate((attached) => {
2867
+ const { [call.id]: _, ...remaining } = attached;
2868
+ return remaining;
2869
+ });
2849
2870
  }
2850
2871
  async flush() {
2851
- await this.writeAttached({});
2872
+ await this.mutate(() => ({}));
2852
2873
  }
2853
2874
  /**
2854
2875
  * Reattach to previously active calls by sending verto.invite with
@@ -2920,20 +2941,31 @@ var AttachManager = class {
2920
2941
  };
2921
2942
  }
2922
2943
  /**
2923
- * Consume stored attachment data for a pending call (used by session-level
2924
- * verto.attach handler as a future path when server supports it).
2944
+ * Look up stored attachment data for a call id and return CallOptions
2945
+ * suitable for rehydrating a reattached call. Returns undefined when no
2946
+ * matching entry exists in storage.
2947
+ *
2948
+ * Used by the session-level verto.attach handler when the server pushes
2949
+ * an attach event for a call the client doesn't have an object for yet
2950
+ * (e.g. after a reload).
2925
2951
  */
2926
- consumePendingAttachment(_callId) {}
2952
+ async consumePendingAttachment(callId) {
2953
+ const attachment = (await this.readAttached())[callId];
2954
+ if (!attachment) return;
2955
+ return this.buildCallOptions(attachment);
2956
+ }
2927
2957
  async detachExpired() {
2928
- const attached = await this.readAttached();
2929
2958
  const now = Date.now();
2930
2959
  const timeout$4 = this.reconnectCallsTimeout;
2931
- const expired = Object.entries(attached).filter(([, attachment]) => now - attachment.attachedAt > timeout$4);
2932
- if (expired.length > 0) {
2960
+ await this.mutate((attached) => {
2933
2961
  const remaining = { ...attached };
2934
- for (const [callId] of expired) delete remaining[callId];
2935
- await this.writeAttached(remaining);
2936
- }
2962
+ let changed = false;
2963
+ for (const [callId, attachment] of Object.entries(attached)) if (now - attachment.attachedAt > timeout$4) {
2964
+ delete remaining[callId];
2965
+ changed = true;
2966
+ }
2967
+ return changed ? remaining : attached;
2968
+ });
2937
2969
  }
2938
2970
  };
2939
2971
 
@@ -4401,12 +4433,12 @@ var ICEGatheringController = class extends Destroyable {
4401
4433
  ...this.peerConnection.getConfiguration(),
4402
4434
  iceTransportPolicy: "relay"
4403
4435
  });
4404
- if (!(this.peerConnection.connectionState === "connected")) this.peerConnection.restartIce();
4436
+ this.peerConnection.restartIce();
4405
4437
  }
4406
- removeTimer(timer$2) {
4407
- if (this[timer$2]) {
4408
- clearTimeout(this[timer$2]);
4409
- this[timer$2] = void 0;
4438
+ removeTimer(timer$3) {
4439
+ if (this[timer$3]) {
4440
+ clearTimeout(this[timer$3]);
4441
+ this[timer$3] = void 0;
4410
4442
  }
4411
4443
  }
4412
4444
  clearAllTimers() {
@@ -5370,9 +5402,6 @@ var RTCPeerConnectionController = class extends Destroyable {
5370
5402
  negotiationEnded() {
5371
5403
  this._isNegotiating$.next(false);
5372
5404
  }
5373
- restarIce() {
5374
- this.peerConnection?.restartIce();
5375
- }
5376
5405
  /**
5377
5406
  * Trigger an ICE restart through the existing negotiation pipeline.
5378
5407
  *
@@ -5412,7 +5441,10 @@ var RTCPeerConnectionController = class extends Destroyable {
5412
5441
  if (policyChanged) this.restoreIceTransportPolicy();
5413
5442
  throw error;
5414
5443
  }
5415
- if (policyChanged) this.restoreIceTransportPolicy();
5444
+ if (policyChanged) (0, rxjs.firstValueFrom)((0, rxjs.race)(this._iceGatheringState$.pipe((0, rxjs.filter)((state) => state === "complete"), (0, rxjs.take)(1)), (0, rxjs.timer)(ICE_GATHERING_COMPLETE_TIMEOUT_MS).pipe((0, rxjs.map)(() => "timeout")))).then(() => this.restoreIceTransportPolicy()).catch((error) => {
5445
+ logger$15.warn("[RTCPeerConnectionController] Error waiting for ICE gathering to complete:", error);
5446
+ this.restoreIceTransportPolicy();
5447
+ });
5416
5448
  }
5417
5449
  restoreIceTransportPolicy() {
5418
5450
  try {
@@ -6584,11 +6616,11 @@ var RTCStatsMonitor = class extends Destroyable {
6584
6616
  let availableOutgoingBitrate;
6585
6617
  report.forEach((stat) => {
6586
6618
  if (isInboundRtpStat(stat)) if (stat.kind === "audio") {
6587
- audioPacketsReceived += stat.packetsReceived ?? this.lastAudioPacketsReceived;
6619
+ audioPacketsReceived += stat.packetsReceived ?? 0;
6588
6620
  audioPacketsLost += stat.packetsLost ?? 0;
6589
6621
  audioJitter = Math.max(audioJitter, (stat.jitter ?? 0) * 1e3);
6590
6622
  } else {
6591
- videoPacketsReceived += stat.packetsReceived ?? this.lastVideoPacketsReceived;
6623
+ videoPacketsReceived += stat.packetsReceived ?? 0;
6592
6624
  videoPacketsLost += stat.packetsLost ?? 0;
6593
6625
  }
6594
6626
  if (isCandidatePairStat(stat) && stat.state === "succeeded" && stat.nominated) {
@@ -7636,10 +7668,10 @@ var WebRTCCall = class extends Destroyable {
7636
7668
  try {
7637
7669
  if (this.vertoManager.requestIceRestartAll) await this.vertoManager.requestIceRestartAll(relayOnly);
7638
7670
  else await this.vertoManager.requestIceRestart?.(relayOnly);
7639
- return true;
7640
7671
  } catch {
7641
7672
  return false;
7642
7673
  }
7674
+ return this.waitForPeerConnectionConnected();
7643
7675
  },
7644
7676
  disableVideo: () => {
7645
7677
  try {
@@ -7731,6 +7763,27 @@ var WebRTCCall = class extends Destroyable {
7731
7763
  }
7732
7764
  }
7733
7765
  /**
7766
+ * Wait for the underlying RTCPeerConnection to reach 'connected' after
7767
+ * triggering an ICE restart. Resolves true on success, false on failure
7768
+ * or if the state doesn't transition within the configured timeout.
7769
+ *
7770
+ * Polls connectionState directly because the recovery manager already
7771
+ * wraps this call in its own withTimeout(); a separate listener-based
7772
+ * implementation would race the outer timeout in subtle ways.
7773
+ */
7774
+ async waitForPeerConnectionConnected() {
7775
+ const pc = this.rtcPeerConnection;
7776
+ if (!pc) return false;
7777
+ const deadline = Date.now() + PEER_CONNECTION_RECOVERY_WAIT_MS;
7778
+ while (true) {
7779
+ const state = pc.connectionState;
7780
+ if (state === "connected") return true;
7781
+ if (state === "failed" || state === "closed") return false;
7782
+ if (Date.now() >= deadline) return false;
7783
+ await new Promise((resolve) => setTimeout(resolve, PEER_CONNECTION_RECOVERY_POLL_MS));
7784
+ }
7785
+ }
7786
+ /**
7734
7787
  * @internal Stop and destroy resilience subsystems (on disconnect/destroy).
7735
7788
  * Clears references so they can be re-created on reconnect.
7736
7789
  */
@@ -7867,8 +7920,13 @@ var WebRTCCall = class extends Destroyable {
7867
7920
  const cached = this._customSubscriptions.get(eventType);
7868
7921
  if (cached) return cached;
7869
7922
  const filtered$ = this.callSessionEvents$.pipe((0, rxjs.filter)((event) => event.event_type === eventType), (0, rxjs.map)((event) => JSON.parse(JSON.stringify(event))), (0, rxjs.takeUntil)(this._destroyed$));
7923
+ this._sendVertoSubscribe(eventType).then(() => {
7924
+ this._customSubscriptions.set(eventType, filtered$);
7925
+ }, (error) => {
7926
+ this._customSubscriptions.delete(eventType);
7927
+ logger$11.warn(`[Call] verto.subscribe for '${eventType}' failed, not caching:`, error);
7928
+ });
7870
7929
  this._customSubscriptions.set(eventType, filtered$);
7871
- this._sendVertoSubscribe(eventType);
7872
7930
  return filtered$;
7873
7931
  }
7874
7932
  get webrtcMessages$() {
@@ -7994,26 +8052,21 @@ var WebRTCCall = class extends Destroyable {
7994
8052
  }
7995
8053
  /**
7996
8054
  * @internal Send a verto.subscribe message to add an event type to the
7997
- * server's subscription list for this call. Best-effort — failures are
7998
- * logged but don't prevent the filtered observable from being returned.
7999
- */
8000
- _sendVertoSubscribe(eventType) {
8001
- try {
8002
- const message = VertoSubscribe({
8003
- sessid: this.id,
8004
- eventChannel: [eventType]
8005
- });
8006
- const params = {
8007
- callID: this.id,
8008
- node_id: this.vertoManager.nodeId ?? "",
8009
- message
8010
- };
8011
- this.clientSession.execute(WebrtcVerto(params)).catch((error) => {
8012
- logger$11.warn(`[Call] verto.subscribe for '${eventType}' failed (non-fatal):`, error);
8013
- });
8014
- } catch (error) {
8015
- logger$11.warn(`[Call] Failed to send verto.subscribe for '${eventType}':`, error);
8016
- }
8055
+ * server's subscription list for this call. Returns the underlying RPC
8056
+ * promise so callers can decide whether to cache the observable on success
8057
+ * or retry on failure.
8058
+ */
8059
+ async _sendVertoSubscribe(eventType) {
8060
+ const message = VertoSubscribe({
8061
+ sessid: this.id,
8062
+ eventChannel: [eventType]
8063
+ });
8064
+ const params = {
8065
+ callID: this.id,
8066
+ node_id: this.vertoManager.nodeId ?? "",
8067
+ message
8068
+ };
8069
+ await this.clientSession.execute(WebrtcVerto(params));
8017
8070
  }
8018
8071
  };
8019
8072
 
@@ -8030,11 +8083,21 @@ function inferCallErrorKind(error) {
8030
8083
  if (error instanceof require_operators.WebSocketConnectionError || error instanceof require_operators.TransportConnectionError) return "network";
8031
8084
  return "internal";
8032
8085
  }
8086
+ /** JSON-RPC error codes that ClientSessionManager treats as recoverable at the
8087
+ * session level. Surfacing one of these against an in-flight call should not
8088
+ * destroy the call, because the session will reauthenticate and any pending
8089
+ * RPC can then be retried. */
8090
+ const RECOVERABLE_RPC_CODES = new Set([
8091
+ RPC_ERROR_REQUESTER_VALIDATION_FAILED,
8092
+ RPC_ERROR_AUTHENTICATION_FAILED,
8093
+ RPC_ERROR_INVALID_PARAMS
8094
+ ]);
8033
8095
  /** Determines whether an error should be fatal (destroy the call). */
8034
8096
  function isFatalError(error) {
8035
8097
  if (error instanceof require_operators.VertoPongError) return false;
8036
8098
  if (error instanceof require_operators.MediaTrackError) return false;
8037
8099
  if (error instanceof require_operators.RPCTimeoutError) return false;
8100
+ if (error instanceof require_operators.JSONRPCError && RECOVERABLE_RPC_CODES.has(error.code)) return false;
8038
8101
  return true;
8039
8102
  }
8040
8103
  /**
@@ -8469,10 +8532,10 @@ var PendingRPC = class PendingRPC {
8469
8532
  }
8470
8533
  let isSettled = false;
8471
8534
  const subscription = (0, rxjs.race)(responses$.pipe((0, rxjs.filter)((result) => result.id === request.id), (0, rxjs.take)(1)), new rxjs.Observable((subscriber) => {
8472
- const timer$2 = setTimeout(() => {
8535
+ const timer$3 = setTimeout(() => {
8473
8536
  subscriber.error(new require_operators.RPCTimeoutError(request.id, timeoutMs));
8474
8537
  }, timeoutMs);
8475
- return () => clearTimeout(timer$2);
8538
+ return () => clearTimeout(timer$3);
8476
8539
  }), signal ? new rxjs.Observable((subscriber) => {
8477
8540
  const abortHandler = () => {
8478
8541
  subscriber.error(new DOMException("The operation was aborted", "AbortError"));
@@ -8537,7 +8600,7 @@ var ClientSessionManager = class extends Destroyable {
8537
8600
  this.attachManager = attachManager;
8538
8601
  this.dpopManager = dpopManager;
8539
8602
  this.callCreateTimeout = 6e3;
8540
- this.agent = `signalwire-typescript-sdk/1.0.0`;
8603
+ this.agent = `signalwire-js/4.0.0`;
8541
8604
  this.eventAcks = true;
8542
8605
  this.authorizationState$ = this.createReplaySubject(1);
8543
8606
  this.connectVersion = {
@@ -8871,7 +8934,6 @@ var ClientSessionManager = class extends Destroyable {
8871
8934
  displayDirection: invite.display_direction,
8872
8935
  userVariables: invite.userVariables
8873
8936
  });
8874
- await (0, rxjs.firstValueFrom)(callSession.status$);
8875
8937
  this._calls$.next({
8876
8938
  [`${callSession.id}`]: callSession,
8877
8939
  ...this._calls$.value
@@ -8892,7 +8954,7 @@ var ClientSessionManager = class extends Destroyable {
8892
8954
  logger$8.debug(`[Session] Verto attach for existing call ${callID}, deferring to per-call handler`);
8893
8955
  return;
8894
8956
  }
8895
- const storedOptions = this.attachManager.consumePendingAttachment(callID);
8957
+ const storedOptions = await this.attachManager.consumePendingAttachment(callID);
8896
8958
  logger$8.debug(`[Session] Creating reattached call for callID: ${callID}`);
8897
8959
  const callSession = await this.createCall({
8898
8960
  nodeId: attach.node_id,
@@ -8904,7 +8966,6 @@ var ClientSessionManager = class extends Destroyable {
8904
8966
  reattach: true,
8905
8967
  ...storedOptions
8906
8968
  });
8907
- await (0, rxjs.firstValueFrom)(callSession.status$);
8908
8969
  this._calls$.next({
8909
8970
  [`${callSession.id}`]: callSession,
8910
8971
  ...this._calls$.value
@@ -9623,10 +9684,9 @@ var WebSocketController = class WebSocketController extends Destroyable {
9623
9684
  else this._status$.next("disconnected");
9624
9685
  }
9625
9686
  reconnect() {
9626
- if (this.shouldReconnect) {
9627
- this._status$.next("reconnecting");
9628
- this.scheduleReconnection();
9629
- } else this._status$.next("disconnected");
9687
+ this.shouldReconnect = true;
9688
+ this._status$.next("reconnecting");
9689
+ this.scheduleReconnection();
9630
9690
  }
9631
9691
  send(data) {
9632
9692
  if (this._status$.value === "connected" && this.socket?.readyState === 1) {
@@ -10185,6 +10245,7 @@ var SignalWire = class extends Destroyable {
10185
10245
  * `'reconnecting'`, `'disconnecting'`, or `'disconnected'`.
10186
10246
  */
10187
10247
  async connect() {
10248
+ await this.teardownTransportAndSession();
10188
10249
  try {
10189
10250
  const subscriber = this._subscriber$.value;
10190
10251
  if (!subscriber) throw new require_operators.UnexpectedError("Subscriber not initialized before connect");
@@ -10416,10 +10477,30 @@ var SignalWire = class extends Destroyable {
10416
10477
  this._refreshTimerId = void 0;
10417
10478
  }
10418
10479
  this._diagnosticsCollector?.record("connection", "disconnected");
10419
- await this._clientSession.disconnect();
10420
- this._clientSession.destroy();
10480
+ await this.teardownTransportAndSession();
10421
10481
  this._isConnected$.next(false);
10422
10482
  }
10483
+ /**
10484
+ * Tear down the current transport / session / attach manager. Safe to call
10485
+ * when nothing has been initialized yet (e.g. first connect()).
10486
+ */
10487
+ async teardownTransportAndSession() {
10488
+ const session = this._clientSession;
10489
+ const transport = this._transport;
10490
+ if (session) {
10491
+ try {
10492
+ await session.disconnect();
10493
+ } catch (error) {
10494
+ logger$1.warn("[SignalWire] Error disconnecting previous session:", error);
10495
+ }
10496
+ session.destroy();
10497
+ }
10498
+ if (transport) transport.destroy();
10499
+ this._clientSession = void 0;
10500
+ this._publicSession = void 0;
10501
+ this._transport = void 0;
10502
+ this._attachManager = void 0;
10503
+ }
10423
10504
  async waitAuthentication() {
10424
10505
  await (0, rxjs.firstValueFrom)(this.ready$.pipe((0, rxjs.filter)((ready$1) => ready$1 === true)));
10425
10506
  }
@@ -10439,22 +10520,27 @@ var SignalWire = class extends Destroyable {
10439
10520
  params: {}
10440
10521
  }));
10441
10522
  this._isRegistered$.next(true);
10523
+ return;
10442
10524
  } catch (error) {
10525
+ if (!this._deps.credential.token) {
10526
+ this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
10527
+ throw error;
10528
+ }
10443
10529
  logger$1.debug("[SignalWire] Failed to register subscriber, trying reauthentication...");
10444
- if (this._deps.credential.token) this._clientSession.reauthenticate(this._deps.credential.token).then(async () => {
10530
+ try {
10531
+ await this._clientSession.reauthenticate(this._deps.credential.token);
10445
10532
  logger$1.debug("[SignalWire] Reauthentication successful, retrying register()");
10446
10533
  await this._transport.execute(RPCExecute({
10447
10534
  method: "subscriber.online",
10448
10535
  params: {}
10449
10536
  }));
10450
10537
  this._isRegistered$.next(true);
10451
- }).catch((reauthError) => {
10538
+ } catch (reauthError) {
10452
10539
  logger$1.error("[SignalWire] Reauthentication failed during register():", reauthError);
10453
10540
  const registerError = new require_operators.InvalidCredentialsError("Failed to register subscriber, and reauthentication attempt also failed. Please check your credentials.", { cause: reauthError instanceof Error ? reauthError : new Error(String(reauthError), { cause: reauthError }) });
10454
10541
  this._errors$.next(registerError);
10455
- });
10456
- this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
10457
- throw error;
10542
+ throw registerError;
10543
+ }
10458
10544
  }
10459
10545
  }
10460
10546
  /**