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

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
@@ -598,8 +598,9 @@ const selectDevice = (devices = [], selected, preferred) => {
598
598
  return selected;
599
599
  };
600
600
  var NavigatorDeviceController = class extends Destroyable {
601
- constructor() {
601
+ constructor(webRTCApiProvider) {
602
602
  super();
603
+ this.webRTCApiProvider = webRTCApiProvider;
603
604
  this.deviceChangeHandler = () => {
604
605
  logger$18.debug("[DeviceController] Device change detected");
605
606
  this.enumerateDevices();
@@ -681,24 +682,22 @@ var NavigatorDeviceController = class extends Destroyable {
681
682
  });
682
683
  }
683
684
  init() {
684
- if (navigator.mediaDevices) {
685
- this.subscribeTo(this._devicesState$.pipe((0, rxjs.debounceTime)(PreferencesContainer.instance.deviceDebounceTime)), (devicesState) => {
686
- const currentSelected = this._selectedDevicesState$.value;
687
- const newAudioInput = selectDevice(devicesState.audioinput, currentSelected.audioinput, PreferencesContainer.instance.preferredAudioInput);
688
- const newAudioOutput = selectDevice(devicesState.audiooutput, currentSelected.audiooutput, PreferencesContainer.instance.preferredAudioOutput);
689
- const newVideoInput = selectDevice(devicesState.videoinput, currentSelected.videoinput, PreferencesContainer.instance.preferredVideoInput);
690
- if (newAudioInput !== currentSelected.audioinput || newAudioOutput !== currentSelected.audiooutput || newVideoInput !== currentSelected.videoinput) this._selectedDevicesState$.next({
691
- audioinput: newAudioInput,
692
- audiooutput: newAudioOutput,
693
- videoinput: newVideoInput
694
- });
685
+ this.subscribeTo(this._devicesState$.pipe((0, rxjs.debounceTime)(PreferencesContainer.instance.deviceDebounceTime)), (devicesState) => {
686
+ const currentSelected = this._selectedDevicesState$.value;
687
+ const newAudioInput = selectDevice(devicesState.audioinput, currentSelected.audioinput, PreferencesContainer.instance.preferredAudioInput);
688
+ const newAudioOutput = selectDevice(devicesState.audiooutput, currentSelected.audiooutput, PreferencesContainer.instance.preferredAudioOutput);
689
+ const newVideoInput = selectDevice(devicesState.videoinput, currentSelected.videoinput, PreferencesContainer.instance.preferredVideoInput);
690
+ if (newAudioInput !== currentSelected.audioinput || newAudioOutput !== currentSelected.audiooutput || newVideoInput !== currentSelected.videoinput) this._selectedDevicesState$.next({
691
+ audioinput: newAudioInput,
692
+ audiooutput: newAudioOutput,
693
+ videoinput: newVideoInput
695
694
  });
696
- this.enumerateDevices();
697
- }
695
+ });
696
+ this.enumerateDevices();
698
697
  }
699
698
  enableDeviceMonitoring() {
700
699
  this.disableDeviceMonitoring();
701
- navigator.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
700
+ this.webRTCApiProvider.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
702
701
  if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, rxjs.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
703
702
  logger$18.debug("[DeviceController] Polling devices due to interval");
704
703
  this.enumerateDevices();
@@ -706,7 +705,7 @@ var NavigatorDeviceController = class extends Destroyable {
706
705
  this.enumerateDevices();
707
706
  }
708
707
  disableDeviceMonitoring() {
709
- navigator.mediaDevices.removeEventListener("devicechange", this.deviceChangeHandler);
708
+ this.webRTCApiProvider.mediaDevices.removeEventListener("devicechange", this.deviceChangeHandler);
710
709
  if (this._devicesPoolingSubscription) {
711
710
  this._devicesPoolingSubscription.unsubscribe();
712
711
  this._devicesPoolingSubscription = void 0;
@@ -714,7 +713,7 @@ var NavigatorDeviceController = class extends Destroyable {
714
713
  }
715
714
  async enumerateDevices() {
716
715
  try {
717
- const devicesByKind = (await navigator.mediaDevices.enumerateDevices()).reduce((acc, device) => {
716
+ const devicesByKind = (await this.webRTCApiProvider.mediaDevices.enumerateDevices()).reduce((acc, device) => {
718
717
  acc[device.kind].push(device);
719
718
  return acc;
720
719
  }, {
@@ -737,7 +736,7 @@ var NavigatorDeviceController = class extends Destroyable {
737
736
  if (deviceInfo.kind === "audiooutput") return null;
738
737
  try {
739
738
  const constraints = this.deviceInfoToConstraints(deviceInfo);
740
- const stream = await navigator.mediaDevices.getUserMedia({
739
+ const stream = await this.webRTCApiProvider.mediaDevices.getUserMedia({
741
740
  audio: deviceInfo.kind === "audioinput" ? constraints : false,
742
741
  video: deviceInfo.kind === "videoinput" ? constraints : false
743
742
  });
@@ -909,9 +908,23 @@ var DependencyContainer = class {
909
908
  this._webSocketConstructor = WebSocketConstructor;
910
909
  }
911
910
  get deviceController() {
912
- this._deviceController ??= new NavigatorDeviceController();
911
+ this._deviceController ??= new NavigatorDeviceController(this.webRTCApiProvider);
913
912
  return this._deviceController;
914
913
  }
914
+ get webRTCApiProvider() {
915
+ if (!this._webRTCApiProvider) {
916
+ if (typeof RTCPeerConnection === "undefined" || typeof navigator === "undefined") throw new require_operators.DependencyError("WebRTCApiProvider: RTCPeerConnection or navigator.mediaDevices is not available. Please provide a custom webRTCApiProvider in SignalWireOptions.");
917
+ this._webRTCApiProvider = {
918
+ RTCPeerConnection,
919
+ mediaDevices: navigator.mediaDevices
920
+ };
921
+ }
922
+ return this._webRTCApiProvider;
923
+ }
924
+ set webRTCApiProvider(webRTCApiProvider) {
925
+ this._webRTCApiProvider = webRTCApiProvider;
926
+ this._deviceController = void 0;
927
+ }
915
928
  get authorizationStateKey() {
916
929
  return `sw:${this.subscriberId}:as`;
917
930
  }
@@ -1905,7 +1918,7 @@ function isJSONRPCRequest(value) {
1905
1918
  return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "id") && typeof value.id === "string" && hasProperty(value, "method") && typeof value.method === "string";
1906
1919
  }
1907
1920
  function isJSONRPCResponse(value) {
1908
- return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "id") && typeof value.id === "string" && hasProperty(value, "result");
1921
+ return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "id") && typeof value.id === "string" && (hasProperty(value, "result") || hasProperty(value, "error"));
1909
1922
  }
1910
1923
 
1911
1924
  //#endregion
@@ -2827,7 +2840,7 @@ var RTCPeerConnectionController = class extends Destroyable {
2827
2840
  logger$11.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
2828
2841
  return;
2829
2842
  }
2830
- const streamTrack = (await navigator.mediaDevices.getUserMedia({ [kind]: {
2843
+ const streamTrack = (await this.getUserMedia({ [kind]: {
2831
2844
  ...track.getConstraints(),
2832
2845
  ...this.deviceController.deviceInfoToConstraints(deviceInfo)
2833
2846
  } })).getTracks().find((t) => t.kind === kind);
@@ -3018,7 +3031,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3018
3031
  };
3019
3032
  }
3020
3033
  get WebRTCPeerConnectionConstructor() {
3021
- return this.options.WebRTCPeerConnectionConstructor ?? RTCPeerConnection;
3034
+ return this.options.webRTCApiProvider?.RTCPeerConnection ?? RTCPeerConnection;
3022
3035
  }
3023
3036
  get offerOptions() {
3024
3037
  const options = { iceRestart: this.firstSDPExchangeCompleted ? true : void 0 };
@@ -3285,10 +3298,12 @@ var RTCPeerConnectionController = class extends Destroyable {
3285
3298
  }
3286
3299
  }
3287
3300
  async getUserMedia(constraints) {
3288
- return this.options.getUserMedia?.(constraints) ?? navigator.mediaDevices.getUserMedia(constraints);
3301
+ return (this.options.webRTCApiProvider?.mediaDevices ?? navigator.mediaDevices).getUserMedia(constraints);
3289
3302
  }
3290
3303
  async getDisplayMedia(options) {
3291
- return this.options.getDisplayMedia?.(options) ?? navigator.mediaDevices.getDisplayMedia(options);
3304
+ const mediaDevices = this.options.webRTCApiProvider?.mediaDevices ?? navigator.mediaDevices;
3305
+ if (!mediaDevices.getDisplayMedia) throw new require_operators.DependencyError("getDisplayMedia is not supported by the current WebRTC provider");
3306
+ return mediaDevices.getDisplayMedia(options);
3292
3307
  }
3293
3308
  async setupRemoteTracks() {
3294
3309
  if (!this.peerConnection) throw new require_operators.DependencyError("RTCPeerConnection is not initialized");
@@ -3452,11 +3467,12 @@ var VertoManager = class extends Destroyable {
3452
3467
  }
3453
3468
  };
3454
3469
  var WebRTCVertoManager = class extends VertoManager {
3455
- constructor(webRtcCallSession, attachManager, deviceController, options = {}) {
3470
+ constructor(webRtcCallSession, attachManager, deviceController, webRTCApiProvider, options = {}) {
3456
3471
  super(webRtcCallSession);
3457
3472
  this.webRtcCallSession = webRtcCallSession;
3458
3473
  this.attachManager = attachManager;
3459
3474
  this.deviceController = deviceController;
3475
+ this.webRTCApiProvider = webRTCApiProvider;
3460
3476
  this._rtcPeerConnections$ = this.createBehaviorSubject([]);
3461
3477
  this._selfId$ = this.createBehaviorSubject(null);
3462
3478
  this._signalingStatus$ = this.createBehaviorSubject(null);
@@ -3619,7 +3635,7 @@ var WebRTCVertoManager = class extends VertoManager {
3619
3635
  }
3620
3636
  async sendLocalDescription(message, rtcPeerConnController) {
3621
3637
  const vertoMethod = message.method;
3622
- const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController);
3638
+ const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMethod);
3623
3639
  try {
3624
3640
  const response = await this.executeVerto(message, optionalsParams);
3625
3641
  switch (vertoMethod) {
@@ -3696,6 +3712,7 @@ var WebRTCVertoManager = class extends VertoManager {
3696
3712
  inputVideoStream: options.inputVideoStream,
3697
3713
  receiveAudio: options.receiveAudio,
3698
3714
  receiveVideo: options.receiveVideo,
3715
+ webRTCApiProvider: this.webRTCApiProvider,
3699
3716
  ...this.RTCPeerConnectionConfig
3700
3717
  }, options.initOffer, this.deviceController);
3701
3718
  this.setupLocalDescriptionHandler(rtcPeerConnController);
@@ -3762,18 +3779,18 @@ var WebRTCVertoManager = class extends VertoManager {
3762
3779
  this.callSession?.destroy();
3763
3780
  });
3764
3781
  }
3765
- getSendLocalSDPOptionalParams(rtcPeerConnController) {
3782
+ getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMethod) {
3766
3783
  let subscribe = void 0;
3767
- const initial = !rtcPeerConnController.firstSDPExchangeCompleted;
3768
- if (initial) {
3784
+ if (!rtcPeerConnController.firstSDPExchangeCompleted) {
3769
3785
  subscribe = [];
3770
3786
  if (rtcPeerConnController.isMainDevice) subscribe.push(...PreferencesContainer.instance.inviteSubscribeMainDevice);
3771
3787
  else if (rtcPeerConnController.isAdditionalDevice) subscribe.push(...PreferencesContainer.instance.inviteSubscribeAdditionalDevice);
3772
3788
  else if (rtcPeerConnController.isScreenShare) subscribe.push(...PreferencesContainer.instance.inviteSubscribeScreenshare);
3773
3789
  }
3790
+ const isInvite = vertoMethod === "verto.invite";
3774
3791
  return {
3775
3792
  callID: rtcPeerConnController.id,
3776
- node_id: initial ? "" : this._nodeId$.value ?? "",
3793
+ node_id: isInvite ? "" : this._nodeId$.value ?? "",
3777
3794
  subscribe
3778
3795
  };
3779
3796
  }
@@ -3874,7 +3891,8 @@ var WebRTCVertoManager = class extends VertoManager {
3874
3891
  rtcPeerConnController = new RTCPeerConnectionController({
3875
3892
  ...options,
3876
3893
  ...this.RTCPeerConnectionConfig,
3877
- propose
3894
+ propose,
3895
+ webRTCApiProvider: this.webRTCApiProvider
3878
3896
  }, void 0, this.deviceController);
3879
3897
  this.setupLocalDescriptionHandler(rtcPeerConnController);
3880
3898
  if (propose === "screenshare") this._screenShareId = rtcPeerConnController.id;
@@ -4403,10 +4421,11 @@ var WebRTCCall = class extends Destroyable {
4403
4421
  * Eliminates circular dependencies by centralizing Call and Manager creation.
4404
4422
  */
4405
4423
  var CallFactory = class {
4406
- constructor(sessionManager, deviceController, attachManager) {
4424
+ constructor(sessionManager, deviceController, attachManager, webRTCApiProvider) {
4407
4425
  this.sessionManager = sessionManager;
4408
4426
  this.deviceController = deviceController;
4409
4427
  this.attachManager = attachManager;
4428
+ this.webRTCApiProvider = webRTCApiProvider;
4410
4429
  }
4411
4430
  /**
4412
4431
  * Create a new WebRTCCall with properly initialized managers
@@ -4415,7 +4434,7 @@ var CallFactory = class {
4415
4434
  return new WebRTCCall(this.sessionManager, options, {
4416
4435
  initializeManagers: (callInstance) => {
4417
4436
  return {
4418
- vertoManager: new WebRTCVertoManager(callInstance, this.attachManager, this.deviceController, {
4437
+ vertoManager: new WebRTCVertoManager(callInstance, this.attachManager, this.deviceController, this.webRTCApiProvider, {
4419
4438
  nodeId: options.nodeId,
4420
4439
  onError: (error) => {
4421
4440
  callInstance.emitError(error);
@@ -4827,7 +4846,7 @@ const getAddressSearchURI = (options) => {
4827
4846
  return name;
4828
4847
  };
4829
4848
  var ClientSessionManager = class extends Destroyable {
4830
- constructor(credential, transport, storage, authorizationStateKey, deviceController, attachManager) {
4849
+ constructor(credential, transport, storage, authorizationStateKey, deviceController, attachManager, webRTCApiProvider) {
4831
4850
  super();
4832
4851
  this.credential = credential;
4833
4852
  this.transport = transport;
@@ -4850,7 +4869,7 @@ var ClientSessionManager = class extends Destroyable {
4850
4869
  this._calls$ = this.createBehaviorSubject({});
4851
4870
  this._iceServers$ = this.createBehaviorSubject([]);
4852
4871
  attachManager.setSession(this);
4853
- this.callFactory = new CallFactory(this, deviceController, attachManager);
4872
+ this.callFactory = new CallFactory(this, deviceController, attachManager, webRTCApiProvider);
4854
4873
  this.initialized$ = (0, rxjs.defer)(() => (0, rxjs.from)(this.init())).pipe((0, rxjs.shareReplay)(1), (0, rxjs.takeUntil)(this.destroyed$));
4855
4874
  }
4856
4875
  get incomingCalls$() {
@@ -5737,6 +5756,7 @@ var SignalWire = class extends Destroyable {
5737
5756
  if (this._options.storageImplementation) this._deps.storageImpl = this._options.storageImplementation;
5738
5757
  if (this._options.webSocketConstructor) this._deps.WebSocket = this._options.webSocketConstructor;
5739
5758
  if (this._options.savePreferences) this.preferences.enableSavePreferences(this._deps.storage);
5759
+ if (this._options.webRTCApiProvider) this._deps.webRTCApiProvider = this._options.webRTCApiProvider;
5740
5760
  this._deviceController = this._deps.deviceController;
5741
5761
  if (!this._options.skipDeviceMonitoring) this._deviceController.enableDeviceMonitoring();
5742
5762
  this.subscribeTo(this._deviceController.errors$, (error) => {
@@ -5861,7 +5881,7 @@ var SignalWire = class extends Destroyable {
5861
5881
  };
5862
5882
  this._transport = new TransportManager(this._deps.storage, this._deps.protocolKey, this._deps.WebSocket, PreferencesContainer.instance.relayHost ?? this._deps.relayHost, errorHandler);
5863
5883
  this._attachManager = new AttachManager(this._deps.storage, this._deps.deviceController, PreferencesContainer.instance.reconnectCallsTimeout, this._deps.attachedCallsKey);
5864
- this._clientSession = new ClientSessionManager(this._deps.credential, this._transport, this._deps.storage, this._deps.authorizationStateKey, this._deps.deviceController, this._attachManager);
5884
+ this._clientSession = new ClientSessionManager(this._deps.credential, this._transport, this._deps.storage, this._deps.authorizationStateKey, this._deps.deviceController, this._attachManager, this._deps.webRTCApiProvider);
5865
5885
  this._publicSession = new ClientSessionWrapper(this._clientSession);
5866
5886
  this.subscribeTo(this._clientSession.errors$, (error) => {
5867
5887
  this._errors$.next(error);