@signalwire/js 4.0.0-beta.3 → 4.0.0-beta.4

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
@@ -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$2(project, resultSelector) {
6937
+ function switchMap$3(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$2;
6961
+ exports.switchMap = switchMap$3;
6962
6962
  }));
6963
6963
 
6964
6964
  //#endregion
@@ -12515,7 +12515,7 @@ var CallEventsManager = class extends Destroyable {
12515
12515
  });
12516
12516
  this.updateParticipants(sessionState.members);
12517
12517
  this._self$.value?.capabilities.updateFromRaw(capabilities);
12518
- this.updateLayouts();
12518
+ if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
12519
12519
  });
12520
12520
  this.subscribeTo(this.memberUpdates$, (member) => {
12521
12521
  logger$15.debug("[CallEventsManager] Handling member update event for member ID:", member);
@@ -13847,7 +13847,10 @@ function isVertoAttachMessage(value) {
13847
13847
  return value.method === "verto.attach";
13848
13848
  }
13849
13849
  function isVertoAnswerInnerParams(value) {
13850
- return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.answer" && isObject(value.params) && hasProperty(value.params, "callID") && hasProperty(value.params, "sdp");
13850
+ return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.answer" && isObject(value.params) && hasProperty(value.params, "callID");
13851
+ }
13852
+ function isVertoMediaInnerParams(value) {
13853
+ return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.media" && isObject(value.params) && hasProperty(value.params, "callID") && hasProperty(value.params, "sdp");
13851
13854
  }
13852
13855
  function isVertoMediaParamsInnerParams(value) {
13853
13856
  return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.mediaParams" && isObject(value.params) && hasProperty(value.params, "mediaParams");
@@ -13957,10 +13960,19 @@ var WebRTCVertoManager = class extends VertoManager {
13957
13960
  ].includes(connectionState)))));
13958
13961
  }
13959
13962
  initSubscriptions() {
13963
+ this.subscribeTo(this.vertoMedia$, (event) => {
13964
+ logger$10.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
13965
+ this._signalingStatus$.next("ringing");
13966
+ const { sdp, callID } = event;
13967
+ this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
13968
+ status: "received",
13969
+ sdp
13970
+ });
13971
+ });
13960
13972
  this.subscribeTo(this.vertoAnswer$, (event) => {
13961
13973
  logger$10.debug("[WebRTCManager] Received Verto answer event:", event);
13962
- const { sdp } = event;
13963
- this._rtcPeerConnectionsMap.get(event.callID)?.updateAnswerStatus({
13974
+ const { sdp, callID } = event;
13975
+ this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
13964
13976
  status: "received",
13965
13977
  sdp
13966
13978
  });
@@ -14001,6 +14013,9 @@ var WebRTCVertoManager = class extends VertoManager {
14001
14013
  get selfId() {
14002
14014
  return this._selfId$.value;
14003
14015
  }
14016
+ get vertoMedia$() {
14017
+ return this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaInnerParams, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$));
14018
+ }
14004
14019
  get vertoAnswer$() {
14005
14020
  return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAnswerInnerParams, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
14006
14021
  }
@@ -14084,7 +14099,6 @@ var WebRTCVertoManager = class extends VertoManager {
14084
14099
  this._selfId$.next(memberId);
14085
14100
  rtcPeerConnController.setMemberId(memberId);
14086
14101
  if (callId) this.webRtcCallSession.addCallId(callId);
14087
- this._signalingStatus$.next("ringing");
14088
14102
  this.attachManager.attach(this.webRtcCallSession);
14089
14103
  logger$10.info("[WebRTCManager] Verto invite successful");
14090
14104
  logger$10.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
@@ -14179,6 +14193,7 @@ var WebRTCVertoManager = class extends VertoManager {
14179
14193
  }
14180
14194
  setupVertoByeHandler() {
14181
14195
  this.subscribeTo(this.vertoBye$, () => {
14196
+ this._signalingStatus$.next("disconnected");
14182
14197
  this.attachManager.detach(this.webRtcCallSession);
14183
14198
  this.callSession?.destroy();
14184
14199
  });
@@ -14206,7 +14221,12 @@ var WebRTCVertoManager = class extends VertoManager {
14206
14221
  this.callSession?.destroy();
14207
14222
  } else if (!vertoByeOrAccepted) {
14208
14223
  logger$10.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
14209
- await this.bye("USER_BUSY");
14224
+ try {
14225
+ await this.bye("USER_BUSY");
14226
+ } finally {
14227
+ this._signalingStatus$.next("disconnected");
14228
+ this.callSession?.destroy();
14229
+ }
14210
14230
  } else {
14211
14231
  logger$10.debug("[WebRTCManager] Call accepted, sending answer");
14212
14232
  try {
@@ -14236,8 +14256,7 @@ var WebRTCVertoManager = class extends VertoManager {
14236
14256
  userVariables: {
14237
14257
  memberCallId: this.webRtcCallSession.id,
14238
14258
  memberId,
14239
- ...this.webRtcCallSession.options.userVariables,
14240
- ...PreferencesContainer.instance.userVariables
14259
+ ...this.webRtcCallSession.userVariables
14241
14260
  },
14242
14261
  screenShare: rtcPeerConnectionController.isScreenShare,
14243
14262
  additionalDevice: rtcPeerConnectionController.isAdditionalDevice,
@@ -14436,6 +14455,20 @@ var ParticipantFactory = class {
14436
14455
  //#region src/core/entities/Call.ts
14437
14456
  var import_cjs$9 = require_cjs();
14438
14457
  const logger$9 = getLogger();
14458
+ const fromDestinationParams = (destination) => {
14459
+ if (!destination) return {};
14460
+ try {
14461
+ const url = new URL(`destination:${destination}`);
14462
+ const params = {};
14463
+ url.searchParams.forEach((value, key) => {
14464
+ params[key] = value;
14465
+ });
14466
+ return params;
14467
+ } catch (error) {
14468
+ logger$9.warn(`Failed to parse destination URI: ${destination}`, error);
14469
+ return {};
14470
+ }
14471
+ };
14439
14472
  /**
14440
14473
  * Concrete WebRTC call implementation.
14441
14474
  *
@@ -14453,8 +14486,21 @@ var WebRTCCall = class extends Destroyable {
14453
14486
  this._errors$ = this.createSubject();
14454
14487
  this._answered$ = this.createReplaySubject();
14455
14488
  this._holdState = false;
14489
+ this._userVariables$ = this.createBehaviorSubject({ ...PreferencesContainer.instance.userVariables });
14456
14490
  this.id = options.callId ?? v4_default();
14457
14491
  this.to = options.to;
14492
+ this._userVariables$.next({
14493
+ ...this._userVariables$.value,
14494
+ ...fromDestinationParams(options.to),
14495
+ ...options.userVariables
14496
+ });
14497
+ this.subscribeTo(this.webrtcMessages$, (message) => {
14498
+ const userVars = getValueFrom(message, "params.userVariables");
14499
+ if (userVars) this._userVariables$.next({
14500
+ ...this._userVariables$.value,
14501
+ ...userVars
14502
+ });
14503
+ });
14458
14504
  const managers = initialization.initializeManagers(this);
14459
14505
  this.vertoManager = managers.vertoManager;
14460
14506
  this.callEventsManager = managers.callEventsManager;
@@ -14668,6 +14714,21 @@ var WebRTCCall = class extends Destroyable {
14668
14714
  get remoteStream() {
14669
14715
  return this.vertoManager.remoteStream;
14670
14716
  }
14717
+ /** Observable of custom user variables associated with the call. */
14718
+ get userVariables$() {
14719
+ return this._userVariables$.asObservable();
14720
+ }
14721
+ /** a copy of the current custom user variables of the call. */
14722
+ get userVariables() {
14723
+ return { ...this._userVariables$.value };
14724
+ }
14725
+ /** Merge current custom user variables of the call. */
14726
+ set userVariables(variables) {
14727
+ this._userVariables$.next({
14728
+ ...this._userVariables$.value,
14729
+ ...variables
14730
+ });
14731
+ }
14671
14732
  /** @internal */
14672
14733
  createParticipant(memberId, selfId) {
14673
14734
  if (memberId === (selfId ?? this.vertoManager.selfId)) return this.participantFactory.createSelfParticipant(memberId);
@@ -14773,7 +14834,6 @@ var WebRTCCall = class extends Destroyable {
14773
14834
  try {
14774
14835
  await this.vertoManager.bye();
14775
14836
  } finally {
14776
- this._status$.next("destroyed");
14777
14837
  this.destroy();
14778
14838
  }
14779
14839
  }
@@ -14812,6 +14872,7 @@ var WebRTCCall = class extends Destroyable {
14812
14872
  }
14813
14873
  /** Destroys the call, releasing all resources and subscriptions. */
14814
14874
  destroy() {
14875
+ this._status$.next("destroyed");
14815
14876
  this.vertoManager.destroy();
14816
14877
  this.callEventsManager.destroy();
14817
14878
  this.participantsMap.clear();
@@ -14866,7 +14927,10 @@ var Fetcher = class {
14866
14927
  this.nextUrl = `${this.endpoint}?${params}`;
14867
14928
  }
14868
14929
  async next() {
14869
- if (!this.nextUrl) return [];
14930
+ if (!this.nextUrl) {
14931
+ this.hasMore = false;
14932
+ return [];
14933
+ }
14870
14934
  const response = await this.http.request({
14871
14935
  ...GET_PARAMS,
14872
14936
  url: this.nextUrl
@@ -14874,6 +14938,7 @@ var Fetcher = class {
14874
14938
  if (response.ok && !!response.body) {
14875
14939
  const result = JSON.parse(response.body);
14876
14940
  this.nextUrl = result.links.next;
14941
+ this.hasMore = !!this.nextUrl;
14877
14942
  return result.data.filter(this.filter).map(this.mapper);
14878
14943
  }
14879
14944
  logger$8.error("Failed to fetch entity");
@@ -14907,10 +14972,11 @@ var EntityCollection = class extends Destroyable {
14907
14972
  this.observablesRegistry.get(data.id)?.next(updated);
14908
14973
  this.values$.next(Array.from(this.collectionData.values()));
14909
14974
  };
14975
+ this._hasMore$ = this.createBehaviorSubject(true);
14910
14976
  this._destroy$ = new import_cjs$8.Subject();
14911
14977
  this.updateSubscription = this.update$.subscribe(this.upsertData);
14912
14978
  this.loading$.next(false);
14913
- this.hasMore$ = (0, import_cjs$8.defer)(() => (0, import_cjs$8.from)(this.init())).pipe((0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.takeUntil)(this._destroy$));
14979
+ this.hasMore$ = (0, import_cjs$8.defer)(() => (0, import_cjs$8.from)(this.init())).pipe((0, import_cjs$8.switchMap)(() => this._hasMore$), (0, import_cjs$8.distinctUntilChanged)(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.takeUntil)(this._destroy$));
14914
14980
  }
14915
14981
  get loading() {
14916
14982
  return this.loading$.value;
@@ -14925,17 +14991,21 @@ var EntityCollection = class extends Destroyable {
14925
14991
  return Array.from(this.collectionData.values());
14926
14992
  }
14927
14993
  async init() {
14928
- if (this.fetchController.hasMore === false) return Promise.resolve(false);
14994
+ if (this.fetchController.hasMore === false) {
14995
+ this._hasMore$.next(false);
14996
+ return;
14997
+ }
14929
14998
  await this.fetchMore();
14930
- return this.fetchController.hasMore ?? true;
14931
14999
  }
14932
15000
  async fetchMore() {
14933
15001
  try {
14934
15002
  this.loading$.next(true);
14935
15003
  (await this.fetchController.next()).forEach(this.upsertData);
15004
+ this._hasMore$.next(this.fetchController.hasMore ?? false);
14936
15005
  this.loading$.next(false);
14937
15006
  } catch (error) {
14938
15007
  logger$8.error(`Failed to fetch initial collection data`, error);
15008
+ this._hasMore$.next(this.fetchController.hasMore ?? false);
14939
15009
  this.loading$.next(false);
14940
15010
  this.onError?.(new CollectionFetchError("fetchMore", error));
14941
15011
  }
@@ -15507,7 +15577,8 @@ var ClientSessionManager = class extends Destroyable {
15507
15577
  to: invite.callee_id_number,
15508
15578
  fromName: invite.caller_id_name,
15509
15579
  from: invite.caller_id_number,
15510
- displayDirection: invite.display_direction
15580
+ displayDirection: invite.display_direction,
15581
+ userVariables: invite.userVariables
15511
15582
  });
15512
15583
  await (0, import_cjs$5.firstValueFrom)(callSession.status$);
15513
15584
  this._calls$.next({
@@ -15539,12 +15610,14 @@ var ClientSessionManager = class extends Destroyable {
15539
15610
  try {
15540
15611
  const addressURI = getAddressSearchURI(options);
15541
15612
  let address;
15542
- if (!addressURI.startsWith("+")) {
15613
+ try {
15543
15614
  if (!this._directory) throw new DependencyError("Directory not initialized");
15544
15615
  const addressId = await this._directory.findAddressIdByURI(addressURI);
15545
15616
  if (!addressId) throw new DependencyError(`Address name: ${addressURI} not found`);
15546
15617
  address = this._directory.get(addressId);
15547
15618
  if (!address) throw new DependencyError(`Address ID: ${addressId} not found`);
15619
+ } catch (error) {
15620
+ logger$6.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
15548
15621
  }
15549
15622
  const callSession = this.callFactory.createCall(address, { ...options });
15550
15623
  callSession.status$.pipe((0, import_cjs$5.filter)((status) => status === "destroyed"), (0, import_cjs$5.take)(1)).subscribe(() => {