@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/browser.mjs CHANGED
@@ -10755,7 +10755,7 @@ var NavigatorDeviceController = class extends Destroyable {
10755
10755
  enableAudioInput() {
10756
10756
  if (this._audioInputDisabled$.value) {
10757
10757
  this._audioInputDisabled$.next(false);
10758
- const restored = this._lastAudioInputBeforeDisable ?? this.audioInputDevices[0] ?? null;
10758
+ const restored = this._lastAudioInputBeforeDisable ?? this.audioInputDevices[0];
10759
10759
  this._selectedDevicesState$.next({
10760
10760
  ...this._selectedDevicesState$.value,
10761
10761
  audioinput: restored
@@ -10776,7 +10776,7 @@ var NavigatorDeviceController = class extends Destroyable {
10776
10776
  enableVideoInput() {
10777
10777
  if (this._videoInputDisabled$.value) {
10778
10778
  this._videoInputDisabled$.next(false);
10779
- const restored = this._lastVideoInputBeforeDisable ?? this.videoInputDevices[0] ?? null;
10779
+ const restored = this._lastVideoInputBeforeDisable ?? this.videoInputDevices[0];
10780
10780
  this._selectedDevicesState$.next({
10781
10781
  ...this._selectedDevicesState$.value,
10782
10782
  videoinput: restored
@@ -11713,7 +11713,7 @@ function detectScreenShareAudio() {
11713
11713
  * Safely retrieves navigator.mediaDevices, returning null if unavailable.
11714
11714
  */
11715
11715
  function getNavigatorMediaDevices() {
11716
- if (typeof navigator !== "undefined" && navigator.mediaDevices) return navigator.mediaDevices;
11716
+ if (typeof navigator !== "undefined") return navigator.mediaDevices;
11717
11717
  return null;
11718
11718
  }
11719
11719
 
@@ -11835,11 +11835,12 @@ var PreflightRunner = class extends Destroyable {
11835
11835
  let pc;
11836
11836
  try {
11837
11837
  pc = new RTCPeerConnection({ iceServers: this.iceServers });
11838
+ const peerConnection = pc;
11838
11839
  const candidateTypes = /* @__PURE__ */ new Set();
11839
11840
  const startTime = Date.now();
11840
11841
  const gatheringComplete = new Promise((resolve) => {
11841
11842
  const timer$2 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
11842
- pc.onicecandidate = (event) => {
11843
+ peerConnection.onicecandidate = (event) => {
11843
11844
  if (event.candidate) {
11844
11845
  const candidateStr = event.candidate.candidate;
11845
11846
  if (candidateStr.includes("typ host")) candidateTypes.add("host");
@@ -14409,8 +14410,8 @@ var CallEventsManager = class extends Destroyable {
14409
14410
  }
14410
14411
  updateParticipantPositions(layoutChangedEvent) {
14411
14412
  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.");
14412
- layoutChangedEvent.layers.filter((layer) => Boolean(layer.member_id)).filter((layer) => {
14413
- if (!layer.member_id || !(layer.member_id in this._participants$.value)) {
14413
+ layoutChangedEvent.layers.filter((layer) => !!layer.member_id).filter((layer) => {
14414
+ if (!(layer.member_id in this._participants$.value)) {
14414
14415
  logger$18.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
14415
14416
  return false;
14416
14417
  }
@@ -15774,7 +15775,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15774
15775
  const preferredAudioCodecs = this.options.preferredAudioCodecs ?? PreferencesContainer.instance.preferredAudioCodecs;
15775
15776
  const preferredVideoCodecs = this.options.preferredVideoCodecs ?? PreferencesContainer.instance.preferredVideoCodecs;
15776
15777
  const stereo = this.options.stereo ?? PreferencesContainer.instance.stereoAudio;
15777
- if (preferredAudioCodecs && preferredAudioCodecs.length > 0 || preferredVideoCodecs && preferredVideoCodecs.length > 0) {
15778
+ if (preferredAudioCodecs.length > 0 || preferredVideoCodecs.length > 0) {
15778
15779
  result = setCodecPreferences(result, preferredAudioCodecs, preferredVideoCodecs);
15779
15780
  logger$14.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
15780
15781
  preferredAudioCodecs,
@@ -16016,11 +16017,9 @@ var RTCPeerConnectionController = class extends Destroyable {
16016
16017
  oldTrack.stop();
16017
16018
  this.localStreamController.removeTrack(trackId);
16018
16019
  const newTrack = (await this.getUserMedia({ audio: mergedConstraints })).getAudioTracks()[0];
16019
- if (newTrack) {
16020
- await sender.replaceTrack(newTrack);
16021
- this.localStreamController.addTrack(newTrack);
16022
- logger$14.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
16023
- }
16020
+ await sender.replaceTrack(newTrack);
16021
+ this.localStreamController.addTrack(newTrack);
16022
+ logger$14.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
16024
16023
  }
16025
16024
  }
16026
16025
  /**
@@ -16315,7 +16314,7 @@ var WebRTCVertoManager = class extends VertoManager {
16315
16314
  logger$13.warn("[WebRTCManager] No peer connection for keyframe request");
16316
16315
  return;
16317
16316
  }
16318
- const videoReceiver = pc.getReceivers().find((r) => r.track?.kind === "video");
16317
+ const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
16319
16318
  if (!videoReceiver) {
16320
16319
  logger$13.warn("[WebRTCManager] No video receiver for keyframe request");
16321
16320
  return;
@@ -16391,7 +16390,7 @@ var WebRTCVertoManager = class extends VertoManager {
16391
16390
  try {
16392
16391
  const pc = controller.peerConnection;
16393
16392
  if (!pc) continue;
16394
- const videoReceiver = pc.getReceivers().find((r) => r.track?.kind === "video");
16393
+ const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
16395
16394
  if (!videoReceiver) continue;
16396
16395
  if (typeof videoReceiver.requestKeyFrame === "function") {
16397
16396
  videoReceiver.requestKeyFrame();
@@ -16870,6 +16869,12 @@ function computePacketLossPercent(lost, received) {
16870
16869
  if (total === 0) return 0;
16871
16870
  return lost / total * 100;
16872
16871
  }
16872
+ function isInboundRtpStat(stat) {
16873
+ return typeof stat === "object" && stat !== null && "type" in stat && stat.type === "inbound-rtp";
16874
+ }
16875
+ function isCandidatePairStat(stat) {
16876
+ return typeof stat === "object" && stat !== null && "type" in stat && stat.type === "candidate-pair";
16877
+ }
16873
16878
  var RTCStatsMonitor = class extends Destroyable {
16874
16879
  constructor(peerConnection, config = {}) {
16875
16880
  super();
@@ -17001,17 +17006,15 @@ var RTCStatsMonitor = class extends Destroyable {
17001
17006
  let roundTripTime = 0;
17002
17007
  let availableOutgoingBitrate;
17003
17008
  report.forEach((stat) => {
17004
- if (stat.type === "inbound-rtp") {
17005
- if (stat.kind === "audio") {
17006
- audioPacketsReceived += stat.packetsReceived ?? this.lastAudioPacketsReceived;
17007
- audioPacketsLost += stat.packetsLost ?? 0;
17008
- audioJitter = Math.max(audioJitter, (stat.jitter ?? 0) * 1e3);
17009
- } else if (stat.kind === "video") {
17010
- videoPacketsReceived += stat.packetsReceived ?? this.lastVideoPacketsReceived;
17011
- videoPacketsLost += stat.packetsLost ?? 0;
17012
- }
17009
+ if (isInboundRtpStat(stat)) if (stat.kind === "audio") {
17010
+ audioPacketsReceived += stat.packetsReceived ?? this.lastAudioPacketsReceived;
17011
+ audioPacketsLost += stat.packetsLost ?? 0;
17012
+ audioJitter = Math.max(audioJitter, (stat.jitter ?? 0) * 1e3);
17013
+ } else {
17014
+ videoPacketsReceived += stat.packetsReceived ?? this.lastVideoPacketsReceived;
17015
+ videoPacketsLost += stat.packetsLost ?? 0;
17013
17016
  }
17014
- if (stat.type === "candidate-pair" && stat.state === "succeeded" && stat.nominated) {
17017
+ if (isCandidatePairStat(stat) && stat.state === "succeeded" && stat.nominated) {
17015
17018
  roundTripTime = stat.currentRoundTripTime ? stat.currentRoundTripTime * 1e3 : this.lastRoundTripTime;
17016
17019
  availableOutgoingBitrate = stat.availableOutgoingBitrate ?? this.lastAvailableOutgoingBitrate;
17017
17020
  }
@@ -18052,10 +18055,10 @@ var WebRTCCall = class extends Destroyable {
18052
18055
  logger$10.debug("[Call] Recovery manager failed to enable video");
18053
18056
  });
18054
18057
  },
18055
- isNegotiating: () => this.vertoManager.mainPeerConnection?.isNegotiating ?? false,
18058
+ isNegotiating: () => this.vertoManager.mainPeerConnection.isNegotiating,
18056
18059
  isWebSocketConnected: () => this._lastMergedStatus !== "disconnected",
18057
18060
  isCallConnected: () => this._lastMergedStatus === "connected",
18058
- getPeerConnectionState: () => pc.connectionState ?? null
18061
+ getPeerConnectionState: () => pc.connectionState
18059
18062
  }, {
18060
18063
  debounceTimeMs: prefs.recoveryDebounceTime,
18061
18064
  cooldownMs: prefs.recoveryCooldown,
@@ -19270,7 +19273,7 @@ var ClientSessionManager = class extends Destroyable {
19270
19273
  */
19271
19274
  async handleVertoAttach(attach) {
19272
19275
  const { callID } = attach;
19273
- if (this._calls$.value[callID]) {
19276
+ if (callID in this._calls$.value) {
19274
19277
  logger$7.debug(`[Session] Verto attach for existing call ${callID}, deferring to per-call handler`);
19275
19278
  return;
19276
19279
  }
@@ -19972,12 +19975,12 @@ var TransportManager = class extends Destroyable {
19972
19975
  this.discardStaleEvents = () => {
19973
19976
  return (0, import_cjs$1.filter)((message) => {
19974
19977
  if (!isSignalwireRequest(message)) return true;
19975
- const eventChannel = message.params?.event_channel;
19978
+ const eventChannel = message.params.event_channel;
19976
19979
  if (!eventChannel) return true;
19977
19980
  const currentProtocol = this._currentProtocol;
19978
19981
  if (!currentProtocol) return true;
19979
19982
  if (!eventChannel.includes(currentProtocol)) {
19980
- const eventType = message.params.event_type ?? "unknown";
19983
+ const eventType = message.params.event_type;
19981
19984
  logger$2.warn(`[Transport] Discarding stale event: ${eventType} (event_channel does not match current protocol)`);
19982
19985
  return false;
19983
19986
  }
@@ -20254,7 +20257,7 @@ var SignalWire = class extends Destroyable {
20254
20257
  }
20255
20258
  if (_credentials.expiry_at && credentialProvider?.refresh) {
20256
20259
  const refreshFn = async () => {
20257
- if (!credentialProvider?.refresh) throw new InvalidCredentialsError("Credential provider does not support refresh");
20260
+ if (!credentialProvider.refresh) throw new InvalidCredentialsError("Credential provider does not support refresh");
20258
20261
  return credentialProvider.refresh();
20259
20262
  };
20260
20263
  const refreshInterval = Math.max(_credentials.expiry_at - Date.now() - 5e3, 1e3);
@@ -20662,7 +20665,7 @@ var SignalWire = class extends Destroyable {
20662
20665
  * ```
20663
20666
  */
20664
20667
  async preflight(destination, options) {
20665
- const iceServers = this._clientSession?.iceServers ?? PreferencesContainer.instance.iceServers ?? [];
20668
+ const iceServers = this._clientSession.iceServers ?? PreferencesContainer.instance.iceServers ?? [];
20666
20669
  const isConnected = this._isConnected$.value;
20667
20670
  return new PreflightRunner(this._deviceController, iceServers, isConnected, 0, async (dest, opts) => this.dial(dest, opts), options).run(destination);
20668
20671
  }
@@ -20814,6 +20817,8 @@ var SignalWire = class extends Destroyable {
20814
20817
  * Triggers the browser's media permission dialog and captures the user's device selections.
20815
20818
  *
20816
20819
  * @param options - Which permissions to request.
20820
+ * @param options.audio - Whether to request audio permission.
20821
+ * @param options.video - Whether to request video permission.
20817
20822
  * @returns The permission result with selected devices.
20818
20823
  */
20819
20824
  async requestMediaPermissions(options = {
@@ -20845,8 +20850,14 @@ var SignalWire = class extends Destroyable {
20845
20850
  logger$1.warn("[SignalWire] Media permission request failed:", error);
20846
20851
  }
20847
20852
  await this._deviceController.enumerateDevices();
20848
- if (audioGranted && selectedAudioDevice) selectedAudioDevice = this.audioInputDevices.find((d) => d.deviceId === selectedAudioDevice.deviceId) ?? selectedAudioDevice;
20849
- if (videoGranted && selectedVideoDevice) selectedVideoDevice = this.videoInputDevices.find((d) => d.deviceId === selectedVideoDevice.deviceId) ?? selectedVideoDevice;
20853
+ if (audioGranted && selectedAudioDevice) {
20854
+ const audioDeviceId = selectedAudioDevice.deviceId;
20855
+ selectedAudioDevice = this.audioInputDevices.find((d) => d.deviceId === audioDeviceId) ?? selectedAudioDevice;
20856
+ }
20857
+ if (videoGranted && selectedVideoDevice) {
20858
+ const videoDeviceId = selectedVideoDevice.deviceId;
20859
+ selectedVideoDevice = this.videoInputDevices.find((d) => d.deviceId === videoDeviceId) ?? selectedVideoDevice;
20860
+ }
20850
20861
  if (audioGranted && selectedAudioDevice && !this.selectedAudioInputDevice) this.selectAudioInputDevice(selectedAudioDevice);
20851
20862
  if (videoGranted && selectedVideoDevice && !this.selectedVideoInputDevice) this.selectVideoInputDevice(selectedVideoDevice);
20852
20863
  return {
@@ -20879,8 +20890,8 @@ var SignalWire = class extends Destroyable {
20879
20890
  this._deviceTokenManager?.destroy();
20880
20891
  this._dpopManager?.destroy();
20881
20892
  if (this._attachManager) this._attachManager.detachAll();
20882
- this._transport?.destroy();
20883
- this._clientSession?.destroy();
20893
+ this._transport.destroy();
20894
+ this._clientSession.destroy();
20884
20895
  try {
20885
20896
  this._networkMonitor?.destroy();
20886
20897
  } catch {}