@signalwire/js 4.0.0-dev-20260915014810 → 4.0.0-dev-20260915175740

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
@@ -12536,8 +12536,36 @@ var AttachManager = class {
12536
12536
  logger$26.warn("[AttachManager] Skip attach for calls with no destination");
12537
12537
  return;
12538
12538
  }
12539
+ const attachment = this.buildAttachment(call, call.to);
12540
+ await this.mutate((attached) => ({
12541
+ ...attached,
12542
+ [call.id]: attachment
12543
+ }));
12544
+ }
12545
+ /**
12546
+ * Keep an already-stored call's reference alive and current — the periodic
12547
+ * refresh the `verto.ping` keepalive drives.
12548
+ *
12549
+ * Only ever updates: a call with no record is one nothing wants reattached,
12550
+ * and re-creating it here would undo a `detach`. That matters because a ping
12551
+ * can land in the window between `bye()` detaching and the call being torn
12552
+ * down, and a record revived there survives the hangup — so the next page
12553
+ * load dials a call nobody is on. The existence check and the write share
12554
+ * one {@link mutate} turn, so a concurrent detach cannot slip between them.
12555
+ */
12556
+ async refresh(call) {
12557
+ if (!call.to) return;
12539
12558
  const destination = call.to;
12540
- const attachment = {
12559
+ await this.mutate((attached) => {
12560
+ if (!Object.hasOwn(attached, call.id)) return attached;
12561
+ return {
12562
+ ...attached,
12563
+ [call.id]: this.buildAttachment(call, destination)
12564
+ };
12565
+ });
12566
+ }
12567
+ buildAttachment(call, destination) {
12568
+ return {
12541
12569
  nodeId: call.nodeId,
12542
12570
  destination,
12543
12571
  mediaDirections: call.mediaDirections,
@@ -12545,10 +12573,6 @@ var AttachManager = class {
12545
12573
  videoInputDevice: call.mediaDirections.video !== "inactive" ? this.deviceController.selectedVideoInputDevice : null,
12546
12574
  attachedAt: Date.now()
12547
12575
  };
12548
- await this.mutate((attached) => ({
12549
- ...attached,
12550
- [call.id]: attachment
12551
- }));
12552
12576
  }
12553
12577
  async detach(call) {
12554
12578
  await this.mutate((attached) => {
@@ -14336,22 +14360,31 @@ var SelfParticipant = class extends Participant {
14336
14360
  this.deviceController.selectAudioInputDevice(device);
14337
14361
  if (options.savePreference) PreferencesContainer.instance.preferredAudioInput = device;
14338
14362
  }
14339
- /** Updates the audio input track constraints for the active call. */
14363
+ /**
14364
+ * Updates the audio input track constraints for the active call.
14365
+ * @returns whether the constraints reached the media the call is sending.
14366
+ */
14340
14367
  async setAudioInputDeviceConstraints(constraints) {
14341
- await this.vertoManager.updateMediaConstraints({ audio: constraints });
14368
+ return this.vertoManager.updateMediaConstraints({ audio: constraints });
14342
14369
  }
14343
- /** Updates both audio and video input track constraints for the active call. */
14370
+ /**
14371
+ * Updates both audio and video input track constraints for the active call.
14372
+ * @returns whether both kinds took the constraints.
14373
+ */
14344
14374
  async setInputDevicesConstraints(constraints) {
14345
- await this.vertoManager.updateMediaConstraints(constraints);
14375
+ return this.vertoManager.updateMediaConstraints(constraints);
14346
14376
  }
14347
14377
  /** Selects the video input device for future calls. Optionally saves as a preference. */
14348
14378
  selectVideoInputDevice(device, options = {}) {
14349
14379
  this.deviceController.selectVideoInputDevice(device);
14350
14380
  if (options.savePreference) PreferencesContainer.instance.preferredVideoInput = device;
14351
14381
  }
14352
- /** Updates the video input track constraints for the active call. */
14382
+ /**
14383
+ * Updates the video input track constraints for the active call.
14384
+ * @returns whether the constraints reached the media the call is sending.
14385
+ */
14353
14386
  async setVideoInputDeviceConstraints(constraints) {
14354
- await this.vertoManager.updateMediaConstraints({ video: constraints });
14387
+ return this.vertoManager.updateMediaConstraints({ video: constraints });
14355
14388
  }
14356
14389
  /** Selects the audio output device. Optionally saves as a preference. */
14357
14390
  selectAudioOutputDevice(device, options = {}) {
@@ -17289,7 +17322,7 @@ var WebRTCVertoManager = class extends VertoManager {
17289
17322
  this.applyServerMediaParams(rtcPeerConnController, audio, video);
17290
17323
  });
17291
17324
  this.subscribeTo(this.vertoPing$, (vertoPing) => {
17292
- this.attachManager.attach(this.buildAttachableCall());
17325
+ this.attachManager.refresh(this.buildAttachableCall());
17293
17326
  this.sendVertoPong(vertoPing);
17294
17327
  });
17295
17328
  }
@@ -17393,16 +17426,25 @@ var WebRTCVertoManager = class extends VertoManager {
17393
17426
  this.onError?.(new VertoPongError(error));
17394
17427
  }
17395
17428
  }
17429
+ /**
17430
+ * @returns whether the constraints reached the media the call is sending.
17431
+ * `false` is an outcome, not a failure: the leg may have no live sender of
17432
+ * the kind, or carry media the SDK did not capture and may not replace.
17433
+ * A failure behind it still reaches the call's `errors$`, so a caller that
17434
+ * ignores this value learns of it there.
17435
+ */
17396
17436
  async updateMediaConstraints(options = {}) {
17397
17437
  const { audio, video } = options;
17438
+ let applied = true;
17398
17439
  try {
17399
- if (audio) await this.mainPeerConnection.updateSendersConstraints("audio", audio);
17400
- if (video) await this.mainPeerConnection.updateSendersConstraints("video", video);
17440
+ if (audio) applied = await this.mainPeerConnection.updateSendersConstraints("audio", audio) && applied;
17441
+ if (video) applied = await this.mainPeerConnection.updateSendersConstraints("video", video) && applied;
17401
17442
  } catch (error) {
17402
17443
  logger$16.warn("[WebRTCManager] Error updating media constraints:", error);
17403
17444
  this.reportLegError(toError(error), this.mainPeerConnection);
17404
17445
  throw error;
17405
17446
  }
17447
+ return applied;
17406
17448
  }
17407
17449
  get selfId() {
17408
17450
  return this._selfId$.value;
@@ -17642,7 +17684,7 @@ var WebRTCVertoManager = class extends VertoManager {
17642
17684
  this.emitMainSignalingStatus(rtcPeerConnController.id, "trying");
17643
17685
  const nodeId = getValueFrom(response, "result.node_id") ?? null;
17644
17686
  const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
17645
- const callId = getValueFrom(response, "result.result.result.callID") ?? null;
17687
+ const callId = getValueFrom(response, "result.result.result.callID");
17646
17688
  logger$16.debug("[WebRTCManager] Verto invite response:", {
17647
17689
  callId,
17648
17690
  memberId,
@@ -17653,14 +17695,9 @@ var WebRTCVertoManager = class extends VertoManager {
17653
17695
  if (rtcPeerConnController.isMainDevice) {
17654
17696
  this._selfId$.next(memberId);
17655
17697
  this._nodeId$.next(nodeId);
17656
- }
17657
- if (callId) {
17658
- this.webRtcCallSession.addCallId(callId);
17659
17698
  this.attachManager.attach(this.buildAttachableCall(callId, nodeId ?? void 0));
17660
- } else logger$16.warn("[WebRTCManager] Cannot attach call, missing callId:", {
17661
- nodeId: this.nodeId,
17662
- callId
17663
- });
17699
+ }
17700
+ if (callId) this.webRtcCallSession.addCallId(callId);
17664
17701
  logger$16.info("[WebRTCManager] Verto invite successful");
17665
17702
  logger$16.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
17666
17703
  } else {
@@ -19961,17 +19998,28 @@ var WebRTCCall = class extends Destroyable {
19961
19998
  * (notably iOS Safari) fall back to re-acquiring the track with the new
19962
19999
  * constraint set and plumbing the replacement through the local audio
19963
20000
  * pipeline if one is active.
20001
+ *
20002
+ * @returns whether the constraint reached the microphone. `false` is an
20003
+ * outcome rather than an error — a leg sending media the SDK did not capture
20004
+ * is left alone — so a UI that reflects the toggle must read it. Any failure
20005
+ * behind a `false` is also reported on {@link errors$}.
19964
20006
  */
19965
20007
  async setEchoCancellation(enabled) {
19966
- await this.vertoManager.updateMediaConstraints({ audio: { echoCancellation: enabled } });
20008
+ return this.vertoManager.updateMediaConstraints({ audio: { echoCancellation: enabled } });
19967
20009
  }
19968
- /** Toggle browser noise suppression on the local mic at runtime. */
20010
+ /**
20011
+ * Toggle browser noise suppression on the local mic at runtime.
20012
+ * @returns whether the constraint reached the microphone.
20013
+ */
19969
20014
  async setNoiseSuppression(enabled) {
19970
- await this.vertoManager.updateMediaConstraints({ audio: { noiseSuppression: enabled } });
20015
+ return this.vertoManager.updateMediaConstraints({ audio: { noiseSuppression: enabled } });
19971
20016
  }
19972
- /** Toggle browser automatic gain control on the local mic at runtime. */
20017
+ /**
20018
+ * Toggle browser automatic gain control on the local mic at runtime.
20019
+ * @returns whether the constraint reached the microphone.
20020
+ */
19973
20021
  async setAutoGainControl(enabled) {
19974
- await this.vertoManager.updateMediaConstraints({ audio: { autoGainControl: enabled } });
20022
+ return this.vertoManager.updateMediaConstraints({ audio: { autoGainControl: enabled } });
19975
20023
  }
19976
20024
  /**
19977
20025
  * Observable of the aggregate remote audio level, 0..1 RMS. The server
@@ -23093,7 +23141,7 @@ var SignalWire = class extends Destroyable {
23093
23141
  logger$1.warn("[SignalWire] Failed to initialize VisibilityController:", error);
23094
23142
  }
23095
23143
  try {
23096
- this._diagnosticsCollector = new DiagnosticsCollector({ sdkVersion: "4.0.0-dev-20260915014810" });
23144
+ this._diagnosticsCollector = new DiagnosticsCollector({ sdkVersion: "4.0.0-dev-20260915175740" });
23097
23145
  } catch (error) {
23098
23146
  logger$1.warn("[SignalWire] Failed to initialize DiagnosticsCollector:", error);
23099
23147
  }
@@ -23648,7 +23696,7 @@ var StaticCredentialProvider = class {
23648
23696
  /**
23649
23697
  * Library version from package.json, injected at build time.
23650
23698
  */
23651
- const version = "4.0.0-dev-20260915014810";
23699
+ const version = "4.0.0-dev-20260915175740";
23652
23700
  /**
23653
23701
  * Flag indicating the library has been loaded and is ready to use.
23654
23702
  * For UMD builds: `window.SignalWire.ready`
@@ -23670,7 +23718,7 @@ const ready = true;
23670
23718
  */
23671
23719
  const emitReadyEvent = () => {
23672
23720
  if (typeof window !== "undefined") {
23673
- const event = new CustomEvent("signalwire:js:ready", { detail: { version: "4.0.0-dev-20260915014810" } });
23721
+ const event = new CustomEvent("signalwire:js:ready", { detail: { version: "4.0.0-dev-20260915175740" } });
23674
23722
  window.dispatchEvent(event);
23675
23723
  }
23676
23724
  };