@wazo/sdk 0.37.2 → 0.37.6

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.
Files changed (99) hide show
  1. package/dist/wazo-sdk.js +5 -5
  2. package/esm/__tests__/api-client.test.js +84 -22
  3. package/esm/__tests__/web-rtc-client.test.js +156 -55
  4. package/esm/api/call-logd.js +10 -22
  5. package/esm/api/calld.js +3 -0
  6. package/esm/api/confd.js +71 -0
  7. package/esm/api-client.js +84 -22
  8. package/esm/checker/Checker.js +160 -55
  9. package/esm/checker/checks/aor.js +84 -22
  10. package/esm/checker/checks/api.js +84 -22
  11. package/esm/checker/checks/index.js +160 -55
  12. package/esm/checker/checks/wazo-websocket.js +4 -0
  13. package/esm/checker/checks/webrtc-transport.js +156 -55
  14. package/esm/checker/checks/webrtc.js +156 -55
  15. package/esm/domain/AdHocAPIConference.js +84 -22
  16. package/esm/domain/CallLog.js +10 -22
  17. package/esm/domain/Features.js +84 -22
  18. package/esm/domain/Meeting.js +71 -0
  19. package/esm/domain/Phone/CTIPhone.js +84 -22
  20. package/esm/domain/Phone/WebRTCPhone.js +22 -8
  21. package/esm/domain/__tests__/CallLog.test.js +10 -22
  22. package/esm/index.js +726 -371
  23. package/esm/lib/WazoSessionDescriptionHandler.js +17 -9
  24. package/esm/service/CallApi.js +84 -22
  25. package/esm/service/getApiClient.js +84 -22
  26. package/esm/simple/Auth.js +717 -363
  27. package/esm/simple/Configuration.js +717 -363
  28. package/esm/simple/Directory.js +84 -22
  29. package/esm/simple/Phone.js +709 -355
  30. package/esm/simple/Websocket.js +6 -0
  31. package/esm/simple/index.js +719 -365
  32. package/esm/simple/room/LocalParticipant.js +689 -335
  33. package/esm/simple/room/Participant.js +689 -335
  34. package/esm/simple/room/RemoteParticipant.js +689 -335
  35. package/esm/simple/room/Room.js +689 -335
  36. package/esm/simple/room/SipRoom.js +13001 -0
  37. package/esm/simple/room/Stream.js +719 -365
  38. package/esm/simple/room/__tests__/RemoteParticipant.test.js +4130 -3774
  39. package/esm/simple/utils.js +719 -365
  40. package/esm/web-rtc-client.js +156 -55
  41. package/esm/websocket-client.js +5 -1
  42. package/lib/__tests__/api-client.test.js +84 -22
  43. package/lib/__tests__/web-rtc-client.test.js +156 -55
  44. package/lib/api/call-logd.js +10 -22
  45. package/lib/api/calld.js +3 -0
  46. package/lib/api/confd.js +71 -0
  47. package/lib/api-client.js +84 -22
  48. package/lib/checker/Checker.js +160 -55
  49. package/lib/checker/checks/aor.js +84 -22
  50. package/lib/checker/checks/api.js +84 -22
  51. package/lib/checker/checks/index.js +160 -55
  52. package/lib/checker/checks/wazo-websocket.js +4 -0
  53. package/lib/checker/checks/webrtc-transport.js +156 -55
  54. package/lib/checker/checks/webrtc.js +156 -55
  55. package/lib/domain/AdHocAPIConference.js +84 -22
  56. package/lib/domain/CallLog.js +10 -22
  57. package/lib/domain/Features.js +84 -22
  58. package/lib/domain/Meeting.js +73 -0
  59. package/lib/domain/Phone/CTIPhone.js +84 -22
  60. package/lib/domain/Phone/WebRTCPhone.js +22 -8
  61. package/lib/domain/__tests__/CallLog.test.js +10 -22
  62. package/lib/index.js +726 -371
  63. package/lib/lib/WazoSessionDescriptionHandler.js +17 -9
  64. package/lib/service/CallApi.js +84 -22
  65. package/lib/service/getApiClient.js +84 -22
  66. package/lib/simple/Auth.js +717 -363
  67. package/lib/simple/Configuration.js +717 -363
  68. package/lib/simple/Directory.js +84 -22
  69. package/lib/simple/Phone.js +709 -355
  70. package/lib/simple/Websocket.js +6 -0
  71. package/lib/simple/index.js +719 -365
  72. package/lib/simple/room/LocalParticipant.js +689 -335
  73. package/lib/simple/room/Participant.js +689 -335
  74. package/lib/simple/room/RemoteParticipant.js +689 -335
  75. package/lib/simple/room/Room.js +689 -335
  76. package/lib/simple/room/SipRoom.js +13011 -0
  77. package/lib/simple/room/Stream.js +719 -365
  78. package/lib/simple/room/__tests__/RemoteParticipant.test.js +4131 -3775
  79. package/lib/simple/utils.js +719 -365
  80. package/lib/web-rtc-client.js +156 -55
  81. package/lib/websocket-client.js +6 -0
  82. package/package.json +1 -1
  83. package/src/api/calld.js +3 -0
  84. package/src/api/confd.js +13 -0
  85. package/src/domain/CallLog.js +10 -22
  86. package/src/domain/Meeting.js +59 -0
  87. package/src/domain/Phone/WebRTCPhone.js +22 -8
  88. package/src/index.js +2 -0
  89. package/src/lib/WazoSessionDescriptionHandler.js +17 -9
  90. package/src/simple/Phone.js +13 -4
  91. package/src/simple/index.js +4 -0
  92. package/src/simple/room/Participant.js +7 -0
  93. package/src/simple/room/Room.js +158 -79
  94. package/src/simple/room/SipRoom.js +147 -0
  95. package/src/simple/room/Stream.js +1 -3
  96. package/src/simple/room/__tests__/RemoteParticipant.test.js +3 -2
  97. package/src/types/WebSocketMessage.js +21 -0
  98. package/src/web-rtc-client.js +55 -24
  99. package/src/websocket-client.js +4 -0
@@ -778,7 +778,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
778
778
  .then(() => {
779
779
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
780
780
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
781
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
781
+ if (this.peerConnection.addTransceiver) {
782
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
783
+ }
782
784
  }
783
785
  })
784
786
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -805,12 +807,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
805
807
  };
806
808
  })
807
809
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
808
- .then((sessionDescription) => {
809
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
810
- this.localMediaStreamConstraints = options.constraints;
811
-
812
- return sessionDescription;
813
- })
814
810
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
815
811
  .catch((error) => {
816
812
  wazoLogger.error('error when creating media', error);
@@ -1005,6 +1001,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
1005
1001
 
1006
1002
  // set the transceiver direction to the answer direction
1007
1003
  this._peerConnection.getTransceivers().forEach((transceiver) => {
1004
+ if (transceiver.stopped) {
1005
+ return;
1006
+ }
1008
1007
  if (transceiver.direction /* guarding, but should always be true */) {
1009
1008
  const { receiver } = transceiver;
1010
1009
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -1049,10 +1048,15 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
1049
1048
  if (kind !== 'audio' && kind !== 'video') {
1050
1049
  throw new Error(`Unknown new track kind ${kind}.`);
1051
1050
  }
1052
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
1051
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
1052
+ otherSender.track && otherSender.track.kind === kind);
1053
1053
 
1054
1054
  // Do not reuse sender video tracks in SFU
1055
1055
  if (sender && (!sfu || newTrack.kind === 'audio')) {
1056
+ if (sender.track) {
1057
+ // eslint-disable-next-line no-param-reassign
1058
+ newTrack.enabled = sender.track.enabled;
1059
+ }
1056
1060
  trackUpdates.push(
1057
1061
  new Promise((resolve) => {
1058
1062
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -1086,7 +1090,11 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
1086
1090
  // Review: could make streamless tracks a configurable option?
1087
1091
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
1088
1092
  try {
1089
- pc.addTrack(newTrack, localStream);
1093
+ if (pc.addTrack) {
1094
+ pc.addTrack(newTrack, localStream);
1095
+ } else {
1096
+ pc.addStream(localStream);
1097
+ }
1090
1098
  } catch (error) {
1091
1099
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
1092
1100
  throw error;
@@ -3043,6 +3051,65 @@ class ExternalApp {
3043
3051
  }
3044
3052
  }
3045
3053
 
3054
+ //
3055
+
3056
+
3057
+
3058
+
3059
+
3060
+
3061
+
3062
+
3063
+
3064
+
3065
+
3066
+ class Meeting {
3067
+
3068
+
3069
+
3070
+
3071
+
3072
+
3073
+
3074
+
3075
+
3076
+
3077
+ static parse(plain ) {
3078
+ return new Meeting({
3079
+ guestSipAuthorization: plain.guest_sip_authorization,
3080
+ hostname: plain.hostname,
3081
+ name: plain.name,
3082
+ ownerUuids: plain.owner_uuids,
3083
+ port: plain.port,
3084
+ uuid: plain.uuid,
3085
+ number: plain.number,
3086
+ });
3087
+ }
3088
+
3089
+ static newFrom(meeting ) {
3090
+ return newFrom(meeting, Meeting);
3091
+ }
3092
+
3093
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
3094
+ this.guestSipAuthorization = guestSipAuthorization;
3095
+ this.hostname = hostname;
3096
+ this.name = name;
3097
+ this.ownerUuids = ownerUuids;
3098
+ this.port = port;
3099
+ this.uuid = uuid;
3100
+ this.number = number;
3101
+
3102
+ // Useful to compare instead of instanceof with minified code
3103
+ this.type = 'Meeting';
3104
+ }
3105
+
3106
+ getGuestSipCredentials() {
3107
+ // eslint-disable-next-line no-undef
3108
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
3109
+ return { username, secret };
3110
+ }
3111
+ }
3112
+
3046
3113
  /* */
3047
3114
 
3048
3115
  var confdMethods = (client , baseUrl ) => ({
@@ -3107,6 +3174,18 @@ var confdMethods = (client , baseUrl ) => ({
3107
3174
  return null;
3108
3175
  }
3109
3176
  },
3177
+
3178
+ createMyMeeting: (name ) =>
3179
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
3180
+
3181
+ deleteMyMeeting: (meetingUuid ) =>
3182
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
3183
+
3184
+ getMeeting: (meetingUuid ) =>
3185
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
3186
+
3187
+ guestGetMeeting: (meetingUuid ) =>
3188
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
3110
3189
  });
3111
3190
 
3112
3191
  //
@@ -3691,7 +3770,11 @@ class CallLog {
3691
3770
  answered: plain.answered,
3692
3771
  callDirection: plain.call_direction,
3693
3772
  destination: {
3694
- extension: plain.requested_extension || plain.destination_extension,
3773
+ // @TEMP: Temporarily assuming empty numbers are meetings
3774
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3775
+ extension: plain.requested_extension
3776
+ || plain.destination_extension
3777
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3695
3778
  name: plain.requested_name || plain.destination_name || '',
3696
3779
  },
3697
3780
  source: {
@@ -3707,27 +3790,11 @@ class CallLog {
3707
3790
  }
3708
3791
 
3709
3792
  static parseNew(plain , session ) {
3710
- return new CallLog({
3711
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3712
- answered: plain.answered,
3713
- callDirection: plain.call_direction,
3714
- destination: {
3715
- extension: plain.requested_extension || plain.destination_extension,
3716
- name: plain.requested_name || plain.destination_name || '',
3717
- },
3718
- source: {
3719
- extension: plain.source_extension,
3720
- name: plain.source_name,
3721
- },
3722
- id: plain.id,
3723
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3724
- start: moment__default['default'](plain.start).toDate(),
3725
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3726
- recordings: Recording.parseMany(plain.recordings),
3727
- // @TODO: FIXME add verification declined vs missed call
3728
- newMissedCall: session
3729
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3730
- });
3793
+ const callLog = CallLog.parse(plain);
3794
+ // @TODO: FIXME add verification declined vs missed call
3795
+ callLog.newMissedCall = session
3796
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3797
+ return callLog;
3731
3798
  }
3732
3799
 
3733
3800
  static newFrom(profile ) {
@@ -4484,6 +4551,9 @@ var calldMethods = (client , baseUrl ) => ({
4484
4551
  getConferenceParticipantsAsUser: async (conferenceId ) =>
4485
4552
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
4486
4553
 
4554
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4555
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4556
+
4487
4557
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4488
4558
 
4489
4559
  mute: (callId ) =>
@@ -5116,6 +5186,7 @@ const MAX_REGISTER_TRIES = 10;
5116
5186
 
5117
5187
 
5118
5188
 
5189
+
5119
5190
 
5120
5191
 
5121
5192
 
@@ -5142,6 +5213,7 @@ class WebRTCClient extends Emitter {
5142
5213
 
5143
5214
 
5144
5215
 
5216
+
5145
5217
 
5146
5218
  // sugar
5147
5219
 
@@ -5180,6 +5252,8 @@ class WebRTCClient extends Emitter {
5180
5252
  super();
5181
5253
  this.uaConfigOverrides = uaConfigOverrides;
5182
5254
  this.config = config;
5255
+ this.skipRegister = config.skipRegister;
5256
+
5183
5257
  this._buildConfig(config, session).then((newConfig ) => {
5184
5258
  this.config = newConfig;
5185
5259
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -5307,14 +5381,22 @@ class WebRTCClient extends Emitter {
5307
5381
  }
5308
5382
 
5309
5383
  register(tries = 0) {
5310
- logger.info('sdk webrtc registering...', {
5384
+ const logInfo = {
5311
5385
  userAgent: !!this.userAgent,
5312
5386
  registered: this.isRegistered(),
5313
5387
  connectionPromise: !!this.connectionPromise,
5314
5388
  registerer: !!this.registerer,
5315
5389
  waiting: this.registerer && this.registerer.waiting,
5316
5390
  tries,
5317
- });
5391
+ skipRegister: this.skipRegister,
5392
+ };
5393
+
5394
+ if (this.skipRegister) {
5395
+ logger.info('sdk webrtc skip register...', logInfo);
5396
+ return Promise.resolve();
5397
+ }
5398
+
5399
+ logger.info('sdk webrtc registering...', logInfo);
5318
5400
 
5319
5401
  if (!this.userAgent) {
5320
5402
  logger.info('sdk webrtc recreating User Agent');
@@ -5645,12 +5727,18 @@ class WebRTCClient extends Emitter {
5645
5727
  }
5646
5728
 
5647
5729
  if (pc.getSenders) {
5730
+ if (!pc.getSenders().length) {
5731
+ return false;
5732
+ }
5648
5733
  pc.getSenders().forEach(sender => {
5649
5734
  if (sender && sender.track && sender.track.kind === 'audio') {
5650
5735
  muted = muted && !sender.track.enabled;
5651
5736
  }
5652
5737
  });
5653
5738
  } else {
5739
+ if (!pc.getLocalStreams().length) {
5740
+ return false;
5741
+ }
5654
5742
  pc.getLocalStreams().forEach(stream => {
5655
5743
  stream.getAudioTracks().forEach(track => {
5656
5744
  muted = muted && !track.enabled;
@@ -5709,6 +5797,8 @@ class WebRTCClient extends Emitter {
5709
5797
  }
5710
5798
  options.sessionDescriptionHandlerOptions = {
5711
5799
  constraints: options.constraints,
5800
+ hold: true,
5801
+ conference: isConference,
5712
5802
  };
5713
5803
 
5714
5804
  // Send re-INVITE
@@ -5751,6 +5841,8 @@ class WebRTCClient extends Emitter {
5751
5841
  }
5752
5842
  options.sessionDescriptionHandlerOptions = {
5753
5843
  constraints: options.constraints,
5844
+ hold: false,
5845
+ conference: isConference,
5754
5846
  };
5755
5847
 
5756
5848
  // Send re-INVITE
@@ -5934,7 +6026,8 @@ class WebRTCClient extends Emitter {
5934
6026
  }
5935
6027
  const sdh = session.sessionDescriptionHandler;
5936
6028
  const pc = sdh.peerConnection;
5937
- const localStream = this.getLocalStream(this.getSipSessionId(session));
6029
+ const sessionId = this.getSipSessionId(session);
6030
+ const localStream = this.getLocalStream(sessionId);
5938
6031
 
5939
6032
  // Release old video stream
5940
6033
  if (localStream) {
@@ -5960,11 +6053,8 @@ class WebRTCClient extends Emitter {
5960
6053
 
5961
6054
  // let's update the local stream
5962
6055
  this.eventEmitter.emit('onVideoInputChange', stream);
5963
- try {
5964
- await sdh.setLocalMediaStream(stream);
5965
- } catch (_) {
5966
- // Nothing to do
5967
- }
6056
+ this.setLocalMediaStream(sessionId, stream);
6057
+
5968
6058
  return stream;
5969
6059
  });
5970
6060
  }
@@ -6266,9 +6356,11 @@ class WebRTCClient extends Emitter {
6266
6356
  remoteStream.removeTrack(track);
6267
6357
  });
6268
6358
 
6269
- pc.getReceivers().forEach(receiver => {
6270
- remoteStream.addTrack(receiver.track);
6271
- });
6359
+ if (pc.getReceivers) {
6360
+ pc.getReceivers().forEach(receiver => {
6361
+ remoteStream.addTrack(receiver.track);
6362
+ });
6363
+ }
6272
6364
  }
6273
6365
 
6274
6366
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -6303,6 +6395,25 @@ class WebRTCClient extends Emitter {
6303
6395
  return sessionId in this.conferences;
6304
6396
  }
6305
6397
 
6398
+ createAudioElementFor(sessionId ) {
6399
+ const audio = document.createElement('audio');
6400
+ audio.setAttribute('id', `audio-${sessionId}`);
6401
+
6402
+ if (audio.setSinkId && this.audioOutputDeviceId) {
6403
+ audio.setSinkId(this.audioOutputDeviceId);
6404
+ }
6405
+
6406
+ if (document.body) {
6407
+ document.body.appendChild(audio);
6408
+ }
6409
+ this.audioElements[sessionId] = audio;
6410
+
6411
+ audio.volume = this.audioOutputVolume;
6412
+ audio.autoplay = true;
6413
+
6414
+ return audio;
6415
+ }
6416
+
6306
6417
  _onTransportError() {
6307
6418
  this.eventEmitter.emit(TRANSPORT_ERROR);
6308
6419
  this.attemptReconnection();
@@ -6532,7 +6643,7 @@ class WebRTCClient extends Emitter {
6532
6643
  let hadRemoteVideo = false;
6533
6644
 
6534
6645
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
6535
- // Becase when `onInvite` is called we already got the video track
6646
+ // Because when `onInvite` is called we already got the video track
6536
6647
  session.onInviteRequest = (request) => {
6537
6648
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
6538
6649
 
@@ -6607,20 +6718,10 @@ class WebRTCClient extends Emitter {
6607
6718
  const isConference = this.isConference(sessionId);
6608
6719
 
6609
6720
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
6610
- const audio = document.createElement('audio');
6611
- audio.setAttribute('id', `audio-${sessionId}`);
6612
-
6613
- if (audio.setSinkId && this.audioOutputDeviceId) {
6614
- audio.setSinkId(this.audioOutputDeviceId);
6615
- }
6616
-
6617
- if (document.body) {
6618
- document.body.appendChild(audio);
6619
- }
6620
- this.audioElements[sessionId] = audio;
6721
+ this.createAudioElementFor(sessionId);
6621
6722
  }
6622
6723
 
6623
- const audioElement = this.audioElements[this.getSipSessionId(session)];
6724
+ const audioElement = this.audioElements[sessionId];
6624
6725
  const stream = newStream || this.getRemoteStream(sessionId);
6625
6726
 
6626
6727
  if (!this._isWeb() || !stream) {