@signalwire/js 4.0.0-dev-20260410161202 → 4.0.0-dev-20260410164129

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
@@ -1319,7 +1319,7 @@ var NavigatorDeviceController = class extends Destroyable {
1319
1319
  enableAudioInput() {
1320
1320
  if (this._audioInputDisabled$.value) {
1321
1321
  this._audioInputDisabled$.next(false);
1322
- const restored = this._lastAudioInputBeforeDisable ?? this.audioInputDevices[0] ?? null;
1322
+ const restored = this._lastAudioInputBeforeDisable ?? this.audioInputDevices[0];
1323
1323
  this._selectedDevicesState$.next({
1324
1324
  ...this._selectedDevicesState$.value,
1325
1325
  audioinput: restored
@@ -1340,7 +1340,7 @@ var NavigatorDeviceController = class extends Destroyable {
1340
1340
  enableVideoInput() {
1341
1341
  if (this._videoInputDisabled$.value) {
1342
1342
  this._videoInputDisabled$.next(false);
1343
- const restored = this._lastVideoInputBeforeDisable ?? this.videoInputDevices[0] ?? null;
1343
+ const restored = this._lastVideoInputBeforeDisable ?? this.videoInputDevices[0];
1344
1344
  this._selectedDevicesState$.next({
1345
1345
  ...this._selectedDevicesState$.value,
1346
1346
  videoinput: restored
@@ -2276,7 +2276,7 @@ function detectScreenShareAudio() {
2276
2276
  * Safely retrieves navigator.mediaDevices, returning null if unavailable.
2277
2277
  */
2278
2278
  function getNavigatorMediaDevices() {
2279
- if (typeof navigator !== "undefined" && navigator.mediaDevices) return navigator.mediaDevices;
2279
+ if (typeof navigator !== "undefined") return navigator.mediaDevices;
2280
2280
  return null;
2281
2281
  }
2282
2282
 
@@ -2397,11 +2397,12 @@ var PreflightRunner = class extends Destroyable {
2397
2397
  let pc;
2398
2398
  try {
2399
2399
  pc = new RTCPeerConnection({ iceServers: this.iceServers });
2400
+ const peerConnection = pc;
2400
2401
  const candidateTypes = /* @__PURE__ */ new Set();
2401
2402
  const startTime = Date.now();
2402
2403
  const gatheringComplete = new Promise((resolve) => {
2403
2404
  const timer$1 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
2404
- pc.onicecandidate = (event) => {
2405
+ peerConnection.onicecandidate = (event) => {
2405
2406
  if (event.candidate) {
2406
2407
  const candidateStr = event.candidate.candidate;
2407
2408
  if (candidateStr.includes("typ host")) candidateTypes.add("host");
@@ -3936,8 +3937,8 @@ var CallEventsManager = class extends Destroyable {
3936
3937
  }
3937
3938
  updateParticipantPositions(layoutChangedEvent) {
3938
3939
  if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$18.warn("[CallEventsManager] No layers with member_id found in layout.changed event. Nothing to update.");
3939
- layoutChangedEvent.layers.filter((layer) => Boolean(layer.member_id)).filter((layer) => {
3940
- if (!layer.member_id || !(layer.member_id in this._participants$.value)) {
3940
+ layoutChangedEvent.layers.filter((layer) => !!layer.member_id).filter((layer) => {
3941
+ if (!(layer.member_id in this._participants$.value)) {
3941
3942
  logger$18.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
3942
3943
  return false;
3943
3944
  }
@@ -5298,7 +5299,7 @@ var RTCPeerConnectionController = class extends Destroyable {
5298
5299
  const preferredAudioCodecs = this.options.preferredAudioCodecs ?? PreferencesContainer.instance.preferredAudioCodecs;
5299
5300
  const preferredVideoCodecs = this.options.preferredVideoCodecs ?? PreferencesContainer.instance.preferredVideoCodecs;
5300
5301
  const stereo = this.options.stereo ?? PreferencesContainer.instance.stereoAudio;
5301
- if (preferredAudioCodecs && preferredAudioCodecs.length > 0 || preferredVideoCodecs && preferredVideoCodecs.length > 0) {
5302
+ if (preferredAudioCodecs.length > 0 || preferredVideoCodecs.length > 0) {
5302
5303
  result = setCodecPreferences(result, preferredAudioCodecs, preferredVideoCodecs);
5303
5304
  logger$14.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
5304
5305
  preferredAudioCodecs,
@@ -5540,11 +5541,9 @@ var RTCPeerConnectionController = class extends Destroyable {
5540
5541
  oldTrack.stop();
5541
5542
  this.localStreamController.removeTrack(trackId);
5542
5543
  const newTrack = (await this.getUserMedia({ audio: mergedConstraints })).getAudioTracks()[0];
5543
- if (newTrack) {
5544
- await sender.replaceTrack(newTrack);
5545
- this.localStreamController.addTrack(newTrack);
5546
- logger$14.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
5547
- }
5544
+ await sender.replaceTrack(newTrack);
5545
+ this.localStreamController.addTrack(newTrack);
5546
+ logger$14.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
5548
5547
  }
5549
5548
  }
5550
5549
  /**
@@ -5838,7 +5837,7 @@ var WebRTCVertoManager = class extends VertoManager {
5838
5837
  logger$13.warn("[WebRTCManager] No peer connection for keyframe request");
5839
5838
  return;
5840
5839
  }
5841
- const videoReceiver = pc.getReceivers().find((r) => r.track?.kind === "video");
5840
+ const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
5842
5841
  if (!videoReceiver) {
5843
5842
  logger$13.warn("[WebRTCManager] No video receiver for keyframe request");
5844
5843
  return;
@@ -5914,7 +5913,7 @@ var WebRTCVertoManager = class extends VertoManager {
5914
5913
  try {
5915
5914
  const pc = controller.peerConnection;
5916
5915
  if (!pc) continue;
5917
- const videoReceiver = pc.getReceivers().find((r) => r.track?.kind === "video");
5916
+ const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
5918
5917
  if (!videoReceiver) continue;
5919
5918
  if (typeof videoReceiver.requestKeyFrame === "function") {
5920
5919
  videoReceiver.requestKeyFrame();
@@ -6398,6 +6397,12 @@ function computePacketLossPercent(lost, received) {
6398
6397
  if (total === 0) return 0;
6399
6398
  return lost / total * 100;
6400
6399
  }
6400
+ function isInboundRtpStat(stat) {
6401
+ return typeof stat === "object" && stat !== null && "type" in stat && stat.type === "inbound-rtp";
6402
+ }
6403
+ function isCandidatePairStat(stat) {
6404
+ return typeof stat === "object" && stat !== null && "type" in stat && stat.type === "candidate-pair";
6405
+ }
6401
6406
  var RTCStatsMonitor = class extends Destroyable {
6402
6407
  constructor(peerConnection, config = {}) {
6403
6408
  super();
@@ -6529,17 +6534,15 @@ var RTCStatsMonitor = class extends Destroyable {
6529
6534
  let roundTripTime = 0;
6530
6535
  let availableOutgoingBitrate;
6531
6536
  report.forEach((stat) => {
6532
- if (stat.type === "inbound-rtp") {
6533
- if (stat.kind === "audio") {
6534
- audioPacketsReceived += stat.packetsReceived ?? this.lastAudioPacketsReceived;
6535
- audioPacketsLost += stat.packetsLost ?? 0;
6536
- audioJitter = Math.max(audioJitter, (stat.jitter ?? 0) * 1e3);
6537
- } else if (stat.kind === "video") {
6538
- videoPacketsReceived += stat.packetsReceived ?? this.lastVideoPacketsReceived;
6539
- videoPacketsLost += stat.packetsLost ?? 0;
6540
- }
6537
+ if (isInboundRtpStat(stat)) if (stat.kind === "audio") {
6538
+ audioPacketsReceived += stat.packetsReceived ?? this.lastAudioPacketsReceived;
6539
+ audioPacketsLost += stat.packetsLost ?? 0;
6540
+ audioJitter = Math.max(audioJitter, (stat.jitter ?? 0) * 1e3);
6541
+ } else {
6542
+ videoPacketsReceived += stat.packetsReceived ?? this.lastVideoPacketsReceived;
6543
+ videoPacketsLost += stat.packetsLost ?? 0;
6541
6544
  }
6542
- if (stat.type === "candidate-pair" && stat.state === "succeeded" && stat.nominated) {
6545
+ if (isCandidatePairStat(stat) && stat.state === "succeeded" && stat.nominated) {
6543
6546
  roundTripTime = stat.currentRoundTripTime ? stat.currentRoundTripTime * 1e3 : this.lastRoundTripTime;
6544
6547
  availableOutgoingBitrate = stat.availableOutgoingBitrate ?? this.lastAvailableOutgoingBitrate;
6545
6548
  }
@@ -7578,10 +7581,10 @@ var WebRTCCall = class extends Destroyable {
7578
7581
  logger$10.debug("[Call] Recovery manager failed to enable video");
7579
7582
  });
7580
7583
  },
7581
- isNegotiating: () => this.vertoManager.mainPeerConnection?.isNegotiating ?? false,
7584
+ isNegotiating: () => this.vertoManager.mainPeerConnection.isNegotiating,
7582
7585
  isWebSocketConnected: () => this._lastMergedStatus !== "disconnected",
7583
7586
  isCallConnected: () => this._lastMergedStatus === "connected",
7584
- getPeerConnectionState: () => pc.connectionState ?? null
7587
+ getPeerConnectionState: () => pc.connectionState
7585
7588
  }, {
7586
7589
  debounceTimeMs: prefs.recoveryDebounceTime,
7587
7590
  cooldownMs: prefs.recoveryCooldown,
@@ -8792,7 +8795,7 @@ var ClientSessionManager = class extends Destroyable {
8792
8795
  */
8793
8796
  async handleVertoAttach(attach) {
8794
8797
  const { callID } = attach;
8795
- if (this._calls$.value[callID]) {
8798
+ if (callID in this._calls$.value) {
8796
8799
  logger$7.debug(`[Session] Verto attach for existing call ${callID}, deferring to per-call handler`);
8797
8800
  return;
8798
8801
  }
@@ -9490,12 +9493,12 @@ var TransportManager = class extends Destroyable {
9490
9493
  this.discardStaleEvents = () => {
9491
9494
  return (0, rxjs.filter)((message) => {
9492
9495
  if (!isSignalwireRequest(message)) return true;
9493
- const eventChannel = message.params?.event_channel;
9496
+ const eventChannel = message.params.event_channel;
9494
9497
  if (!eventChannel) return true;
9495
9498
  const currentProtocol = this._currentProtocol;
9496
9499
  if (!currentProtocol) return true;
9497
9500
  if (!eventChannel.includes(currentProtocol)) {
9498
- const eventType = message.params.event_type ?? "unknown";
9501
+ const eventType = message.params.event_type;
9499
9502
  logger$2.warn(`[Transport] Discarding stale event: ${eventType} (event_channel does not match current protocol)`);
9500
9503
  return false;
9501
9504
  }
@@ -9771,7 +9774,7 @@ var SignalWire = class extends Destroyable {
9771
9774
  }
9772
9775
  if (_credentials.expiry_at && credentialProvider?.refresh) {
9773
9776
  const refreshFn = async () => {
9774
- if (!credentialProvider?.refresh) throw new require_operators.InvalidCredentialsError("Credential provider does not support refresh");
9777
+ if (!credentialProvider.refresh) throw new require_operators.InvalidCredentialsError("Credential provider does not support refresh");
9775
9778
  return credentialProvider.refresh();
9776
9779
  };
9777
9780
  const refreshInterval = Math.max(_credentials.expiry_at - Date.now() - 5e3, 1e3);
@@ -10179,7 +10182,7 @@ var SignalWire = class extends Destroyable {
10179
10182
  * ```
10180
10183
  */
10181
10184
  async preflight(destination, options) {
10182
- const iceServers = this._clientSession?.iceServers ?? PreferencesContainer.instance.iceServers ?? [];
10185
+ const iceServers = this._clientSession.iceServers ?? PreferencesContainer.instance.iceServers ?? [];
10183
10186
  const isConnected = this._isConnected$.value;
10184
10187
  return new PreflightRunner(this._deviceController, iceServers, isConnected, 0, async (dest, opts) => this.dial(dest, opts), options).run(destination);
10185
10188
  }
@@ -10331,6 +10334,8 @@ var SignalWire = class extends Destroyable {
10331
10334
  * Triggers the browser's media permission dialog and captures the user's device selections.
10332
10335
  *
10333
10336
  * @param options - Which permissions to request.
10337
+ * @param options.audio - Whether to request audio permission.
10338
+ * @param options.video - Whether to request video permission.
10334
10339
  * @returns The permission result with selected devices.
10335
10340
  */
10336
10341
  async requestMediaPermissions(options = {
@@ -10362,8 +10367,14 @@ var SignalWire = class extends Destroyable {
10362
10367
  logger$1.warn("[SignalWire] Media permission request failed:", error);
10363
10368
  }
10364
10369
  await this._deviceController.enumerateDevices();
10365
- if (audioGranted && selectedAudioDevice) selectedAudioDevice = this.audioInputDevices.find((d) => d.deviceId === selectedAudioDevice.deviceId) ?? selectedAudioDevice;
10366
- if (videoGranted && selectedVideoDevice) selectedVideoDevice = this.videoInputDevices.find((d) => d.deviceId === selectedVideoDevice.deviceId) ?? selectedVideoDevice;
10370
+ if (audioGranted && selectedAudioDevice) {
10371
+ const audioDeviceId = selectedAudioDevice.deviceId;
10372
+ selectedAudioDevice = this.audioInputDevices.find((d) => d.deviceId === audioDeviceId) ?? selectedAudioDevice;
10373
+ }
10374
+ if (videoGranted && selectedVideoDevice) {
10375
+ const videoDeviceId = selectedVideoDevice.deviceId;
10376
+ selectedVideoDevice = this.videoInputDevices.find((d) => d.deviceId === videoDeviceId) ?? selectedVideoDevice;
10377
+ }
10367
10378
  if (audioGranted && selectedAudioDevice && !this.selectedAudioInputDevice) this.selectAudioInputDevice(selectedAudioDevice);
10368
10379
  if (videoGranted && selectedVideoDevice && !this.selectedVideoInputDevice) this.selectVideoInputDevice(selectedVideoDevice);
10369
10380
  return {
@@ -10396,8 +10407,8 @@ var SignalWire = class extends Destroyable {
10396
10407
  this._deviceTokenManager?.destroy();
10397
10408
  this._dpopManager?.destroy();
10398
10409
  if (this._attachManager) this._attachManager.detachAll();
10399
- this._transport?.destroy();
10400
- this._clientSession?.destroy();
10410
+ this._transport.destroy();
10411
+ this._clientSession.destroy();
10401
10412
  try {
10402
10413
  this._networkMonitor?.destroy();
10403
10414
  } catch {}