@wazo/sdk 0.37.0-rc.5 → 0.37.2

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 (149) hide show
  1. package/dist/wazo-sdk.js +5 -5
  2. package/esm/__tests__/api-client.test.js +93 -16
  3. package/esm/__tests__/web-rtc-client.test.js +153 -54
  4. package/esm/api/agentd.js +24 -3
  5. package/esm/api/amid.js +7 -1
  6. package/esm/api/application.js +24 -3
  7. package/esm/api/auth.js +24 -3
  8. package/esm/api/call-logd.js +78 -20
  9. package/esm/api/calld.js +24 -20
  10. package/esm/api/chatd.js +24 -3
  11. package/esm/api/confd.js +24 -3
  12. package/esm/api/ctid-ng.js +24 -3
  13. package/esm/api/dird.js +27 -6
  14. package/esm/api/webhookd.js +7 -1
  15. package/esm/api-client.js +93 -16
  16. package/esm/checker/Checker.js +156 -54
  17. package/esm/checker/checks/aor.js +95 -16
  18. package/esm/checker/checks/api.js +94 -16
  19. package/esm/checker/checks/index.js +156 -54
  20. package/esm/checker/checks/wazo-websocket.js +7 -1
  21. package/esm/checker/checks/webrtc-transport.js +153 -54
  22. package/esm/checker/checks/webrtc.js +153 -54
  23. package/esm/domain/AdHocAPIConference.js +1717 -1640
  24. package/esm/domain/CallLog.js +71 -19
  25. package/esm/domain/CallSession.js +1 -18
  26. package/esm/domain/Contact.js +3 -3
  27. package/esm/domain/Features.js +93 -16
  28. package/esm/domain/IndirectTransfer.js +0 -17
  29. package/esm/domain/Phone/CTIPhone.js +100 -19
  30. package/esm/domain/Phone/Phone.js +0 -17
  31. package/esm/domain/Phone/WebRTCPhone.js +51 -36
  32. package/esm/domain/Recording.js +51 -0
  33. package/esm/domain/Room.js +0 -17
  34. package/esm/domain/SwitchboardCall.js +0 -17
  35. package/esm/domain/__tests__/CallLog.test.js +89 -19
  36. package/esm/domain/__tests__/CallSession.test.js +1 -18
  37. package/esm/domain/__tests__/Contact.test.js +3 -3
  38. package/esm/domain/__tests__/IndirectTransfer.test.js +1 -18
  39. package/esm/domain/__tests__/Room.test.js +1 -18
  40. package/esm/domain/__tests__/Session.test.js +7 -0
  41. package/esm/index.js +3436 -2911
  42. package/esm/lib/WazoSessionDescriptionHandler.js +28 -10
  43. package/esm/service/CallApi.js +93 -16
  44. package/esm/service/IssueReporter.js +7 -1
  45. package/esm/service/__tests__/IssueReporter.test.js +26 -2
  46. package/esm/service/getApiClient.js +93 -16
  47. package/esm/simple/Auth.js +619 -97
  48. package/esm/simple/Configuration.js +619 -97
  49. package/esm/simple/Directory.js +93 -16
  50. package/esm/simple/Phone.js +3261 -2739
  51. package/esm/simple/Websocket.js +7 -1
  52. package/esm/simple/index.js +619 -97
  53. package/esm/simple/room/LocalParticipant.js +619 -97
  54. package/esm/simple/room/Participant.js +619 -97
  55. package/esm/simple/room/RemoteParticipant.js +619 -97
  56. package/esm/simple/room/Room.js +619 -97
  57. package/esm/simple/room/Stream.js +619 -97
  58. package/esm/simple/room/__tests__/RemoteParticipant.test.js +619 -97
  59. package/esm/simple/utils.js +619 -97
  60. package/esm/utils/__tests__/api-requester.test.js +32 -6
  61. package/esm/utils/api-requester.js +24 -3
  62. package/esm/web-rtc-client.js +153 -54
  63. package/esm/websocket-client.js +7 -1
  64. package/lib/__tests__/api-client.test.js +93 -16
  65. package/lib/__tests__/web-rtc-client.test.js +154 -55
  66. package/lib/api/agentd.js +24 -3
  67. package/lib/api/amid.js +7 -1
  68. package/lib/api/application.js +24 -3
  69. package/lib/api/auth.js +24 -3
  70. package/lib/api/call-logd.js +78 -20
  71. package/lib/api/calld.js +24 -20
  72. package/lib/api/chatd.js +24 -3
  73. package/lib/api/confd.js +24 -3
  74. package/lib/api/ctid-ng.js +24 -3
  75. package/lib/api/dird.js +27 -6
  76. package/lib/api/webhookd.js +7 -1
  77. package/lib/api-client.js +93 -16
  78. package/lib/checker/Checker.js +157 -55
  79. package/lib/checker/checks/aor.js +95 -16
  80. package/lib/checker/checks/api.js +94 -16
  81. package/lib/checker/checks/index.js +157 -55
  82. package/lib/checker/checks/wazo-websocket.js +7 -1
  83. package/lib/checker/checks/webrtc-transport.js +154 -55
  84. package/lib/checker/checks/webrtc.js +154 -55
  85. package/lib/domain/AdHocAPIConference.js +1717 -1640
  86. package/lib/domain/CallLog.js +71 -19
  87. package/lib/domain/CallSession.js +1 -18
  88. package/lib/domain/Contact.js +3 -3
  89. package/lib/domain/Features.js +93 -16
  90. package/lib/domain/IndirectTransfer.js +0 -17
  91. package/lib/domain/Phone/CTIPhone.js +100 -19
  92. package/lib/domain/Phone/Phone.js +0 -16
  93. package/lib/domain/Phone/WebRTCPhone.js +51 -36
  94. package/lib/domain/Recording.js +57 -0
  95. package/lib/domain/Room.js +0 -17
  96. package/lib/domain/SwitchboardCall.js +0 -17
  97. package/lib/domain/__tests__/CallLog.test.js +89 -19
  98. package/lib/domain/__tests__/CallSession.test.js +1 -18
  99. package/lib/domain/__tests__/Contact.test.js +3 -3
  100. package/lib/domain/__tests__/IndirectTransfer.test.js +1 -18
  101. package/lib/domain/__tests__/Room.test.js +1 -18
  102. package/lib/domain/__tests__/Session.test.js +7 -0
  103. package/lib/index.js +3437 -2912
  104. package/lib/lib/WazoSessionDescriptionHandler.js +28 -10
  105. package/lib/service/CallApi.js +93 -16
  106. package/lib/service/IssueReporter.js +7 -1
  107. package/lib/service/__tests__/IssueReporter.test.js +26 -2
  108. package/lib/service/getApiClient.js +93 -16
  109. package/lib/simple/Auth.js +620 -98
  110. package/lib/simple/Configuration.js +620 -98
  111. package/lib/simple/Directory.js +93 -16
  112. package/lib/simple/Phone.js +3262 -2740
  113. package/lib/simple/Websocket.js +7 -1
  114. package/lib/simple/index.js +620 -98
  115. package/lib/simple/room/LocalParticipant.js +620 -98
  116. package/lib/simple/room/Participant.js +620 -98
  117. package/lib/simple/room/RemoteParticipant.js +620 -98
  118. package/lib/simple/room/Room.js +620 -98
  119. package/lib/simple/room/Stream.js +620 -98
  120. package/lib/simple/room/__tests__/RemoteParticipant.test.js +620 -98
  121. package/lib/simple/utils.js +620 -98
  122. package/lib/utils/__tests__/api-requester.test.js +32 -6
  123. package/lib/utils/api-requester.js +24 -3
  124. package/lib/web-rtc-client.js +154 -55
  125. package/lib/websocket-client.js +7 -1
  126. package/package.json +1 -1
  127. package/src/api-client.js +4 -0
  128. package/src/checker/checks/aor.js +2 -0
  129. package/src/checker/checks/api.js +1 -0
  130. package/src/domain/CallLog.js +18 -11
  131. package/src/domain/CallSession.js +1 -2
  132. package/src/domain/Contact.js +3 -3
  133. package/src/domain/Phone/CTIPhone.js +6 -2
  134. package/src/domain/Phone/Phone.js +2 -0
  135. package/src/domain/Phone/WebRTCPhone.js +26 -16
  136. package/src/domain/Recording.js +48 -0
  137. package/src/domain/__tests__/CallLog.test.js +19 -0
  138. package/src/domain/__tests__/Session.test.js +7 -0
  139. package/src/index.js +6 -0
  140. package/src/lib/WazoSessionDescriptionHandler.js +21 -9
  141. package/src/service/IssueReporter.js +7 -1
  142. package/src/service/__tests__/IssueReporter.test.js +20 -1
  143. package/src/simple/Phone.js +5 -1
  144. package/src/simple/index.js +6 -0
  145. package/src/simple/room/Room.js +18 -15
  146. package/src/simple/room/Stream.js +1 -4
  147. package/src/utils/__tests__/api-requester.test.js +9 -4
  148. package/src/utils/api-requester.js +17 -2
  149. package/src/web-rtc-client.js +40 -13
@@ -1,11 +1,10 @@
1
1
  import 'webrtc-adapter';
2
2
  import { UserAgentState } from 'sip.js/lib/api/user-agent-state';
3
- import 'sip.js/lib/api/message';
4
3
  import { Parser } from 'sip.js/lib/core/messages/parser';
5
4
  import { C } from 'sip.js/lib/core/messages/methods/constants';
6
5
  import { URI } from 'sip.js/lib/grammar/uri';
7
6
  import { UserAgent } from 'sip.js/lib/api/user-agent';
8
- import { holdModifier } from 'sip.js/lib/platform/web/modifiers/modifiers';
7
+ import { stripVideo, holdModifier } from 'sip.js/lib/platform/web/modifiers/modifiers';
9
8
  import { Registerer } from 'sip.js/lib/api/registerer';
10
9
  import { Inviter } from 'sip.js/lib/api/inviter';
11
10
  import { Messager } from 'sip.js/lib/api/messager';
@@ -136,6 +135,7 @@ class ApiRequester {
136
135
 
137
136
 
138
137
 
138
+
139
139
 
140
140
 
141
141
 
@@ -175,6 +175,8 @@ class ApiRequester {
175
175
  this.token = token;
176
176
  }
177
177
 
178
+ this.shouldLogErrors = true;
179
+
178
180
  methods.forEach(method => {
179
181
  // $FlowFixMe
180
182
  ApiRequester.prototype[method] = function sugar(...args) {
@@ -198,6 +200,14 @@ class ApiRequester {
198
200
  this.fetchOptions = options;
199
201
  }
200
202
 
203
+ disableErrorLogging() {
204
+ this.shouldLogErrors = false;
205
+ }
206
+
207
+ enableErrorLogging() {
208
+ this.shouldLogErrors = true;
209
+ }
210
+
201
211
  async call(
202
212
  path ,
203
213
  method = 'get',
@@ -258,7 +268,9 @@ class ApiRequester {
258
268
  ? exceptionClass.fromText(err, response.status)
259
269
  : exceptionClass.fromResponse(err, response.status);
260
270
 
261
- logger$2.error('API error', error);
271
+ if (this.shouldLogErrors) {
272
+ logger$2.error('API error', error);
273
+ }
262
274
 
263
275
  throw error;
264
276
  });
@@ -266,7 +278,9 @@ class ApiRequester {
266
278
 
267
279
  return newParse(response, isJson);
268
280
  }).catch(error => {
269
- logger$2.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
281
+ if (this.shouldLogErrors) {
282
+ logger$2.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
283
+ }
270
284
 
271
285
  throw error;
272
286
  });
@@ -577,7 +591,13 @@ class IssueReporter {
577
591
  }
578
592
 
579
593
  _isLevelAbove(level1 , level2 ) {
580
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
594
+ const index1 = LOG_LEVELS.indexOf(level1);
595
+ const index2 = LOG_LEVELS.indexOf(level2);
596
+ if (index1 === -1 || index2 === -1) {
597
+ return false;
598
+ }
599
+
600
+ return index1 > index2;
581
601
  }
582
602
 
583
603
  _makeCategory(category ) {
@@ -606,23 +626,6 @@ const areCandidateValid = (candidates ) =>
606
626
  getSrflxOrRelay(candidates)
607
627
  .length > 0;
608
628
 
609
- const toggleVideoDirection = (sdp , direction ) => {
610
- const parsedSdp = sdpParser.parse(sdp);
611
- parsedSdp.media = parsedSdp.media.map(media => ({
612
- ...media,
613
- ...(media.type === 'video' ? { direction } : {}),
614
- }));
615
-
616
- return sdpParser.write(parsedSdp);
617
- };
618
-
619
- const deactivateVideoModifier = (rawDescription ) => {
620
- const description = rawDescription;
621
- description.sdp = toggleVideoDirection(description.sdp, 'inactive');
622
-
623
- return Promise.resolve(description);
624
- };
625
-
626
629
  const hasAnActiveVideo = (sdp ) => {
627
630
  if (!sdp) {
628
631
  return false;
@@ -734,6 +737,7 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
734
737
  const iceRestart = options.offerOptions ? options.offerOptions.iceRestart : false;
735
738
 
736
739
  const isConference = options ? !!options.conference : false;
740
+ const audioOnly = options ? !!options.audioOnly : false;
737
741
 
738
742
  // We should wait for ice when iceRestart (reinvite) or for the first invite
739
743
  // We shouldn't wait for ice when holding or resuming the call
@@ -760,16 +764,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
760
764
  };
761
765
 
762
766
  return this.getLocalMediaStream(options)
763
- .then(() => this.updateDirection(options, isConference))
767
+ .then(() => this.updateDirection(options, isConference, audioOnly))
764
768
  .then(() => this.createDataChannel(options))
765
769
  .then(() => {
766
- if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options)) {
770
+ if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
767
771
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
768
772
  this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
769
773
  }
770
774
  })
771
775
  .then(() => this.createLocalOfferOrAnswer(options))
772
- .then((sessionDescription) => this.setLocalSessionDescription(sessionDescription))
776
+ .then(sessionDescription => this.setLocalSessionDescription(sessionDescription))
773
777
  .then(() => this.waitForIceGatheringComplete(iceRestart, iceTimeout))
774
778
  .then(() => this.getLocalSessionDescription())
775
779
  .then(description => {
@@ -892,7 +896,8 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
892
896
  }
893
897
 
894
898
  // Overridden to send `inactive` in conference
895
- updateDirection(options , isConference = false) {
899
+ updateDirection(options , isConference = false,
900
+ audioOnly = false) {
896
901
  if (this._peerConnection === undefined) {
897
902
  return Promise.reject(new Error('Peer connection closed.'));
898
903
  }
@@ -907,14 +912,17 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
907
912
  // if we are stable, assume we are creating a local offer
908
913
  this.logger.debug('SessionDescriptionHandler.updateDirection - setting offer direction');
909
914
  // determine the direction to offer given the current direction and hold state
910
- const directionToOffer = (currentDirection ) => {
915
+ const directionToOffer = (currentDirection , transceiver /* RTCRtpTransceiver */) => {
911
916
  if (isConference) {
917
+ if (audioOnly && transceiver.receiver.track && transceiver.receiver.track.kind === 'video') {
918
+ return 'sendonly';
919
+ }
912
920
  return options && options.hold ? 'sendonly' : 'sendrecv';
913
921
  }
914
922
 
915
923
  switch (currentDirection) {
916
924
  case 'inactive':
917
- return options && options.hold ? 'inactive' : 'recvonly';
925
+ return options && options.hold ? 'inactive' : (isConference && !audioOnly ? 'sendrecv' : 'recvonly');
918
926
  case 'recvonly':
919
927
  return options && options.hold ? 'inactive' : 'recvonly';
920
928
  case 'sendonly':
@@ -930,7 +938,7 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
930
938
  // set the transceiver direction to the offer direction
931
939
  this._peerConnection.getTransceivers().forEach((transceiver) => {
932
940
  if (transceiver.direction /* guarding, but should always be true */) {
933
- const offerDirection = directionToOffer(transceiver.direction);
941
+ const offerDirection = directionToOffer(transceiver.direction, transceiver);
934
942
  if (transceiver.direction !== offerDirection) {
935
943
  // eslint-disable-next-line no-param-reassign
936
944
  transceiver.direction = offerDirection;
@@ -989,6 +997,13 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
989
997
  // set the transceiver direction to the answer direction
990
998
  this._peerConnection.getTransceivers().forEach((transceiver) => {
991
999
  if (transceiver.direction /* guarding, but should always be true */) {
1000
+ const { receiver } = transceiver;
1001
+ if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
1002
+ // eslint-disable-next-line no-param-reassign
1003
+ transceiver.direction = 'inactive';
1004
+ return;
1005
+ }
1006
+
992
1007
  if (transceiver.direction !== 'stopped' && transceiver.direction !== answerDirection) {
993
1008
  // eslint-disable-next-line no-param-reassign
994
1009
  transceiver.direction = answerDirection;
@@ -1027,8 +1042,8 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
1027
1042
  }
1028
1043
  const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
1029
1044
 
1030
- // Do not reuse sender tracks in SFU
1031
- if (sender && !sfu) {
1045
+ // Do not reuse sender video tracks in SFU
1046
+ if (sender && (!sfu || newTrack.kind === 'audio')) {
1032
1047
  trackUpdates.push(
1033
1048
  new Promise((resolve) => {
1034
1049
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -2094,7 +2109,7 @@ class Contact {
2094
2109
 
2095
2110
  return new Contact({
2096
2111
  sourceId: single.id || '',
2097
- name: single.displayName,
2112
+ name: single.displayName || '',
2098
2113
  number: numbers.length ? numbers[0].number : '',
2099
2114
  numbers,
2100
2115
  emails,
@@ -2125,7 +2140,7 @@ class Contact {
2125
2140
 
2126
2141
  return new Contact({
2127
2142
  sourceId: single.id || '',
2128
- name: single.name,
2143
+ name: single.name || '',
2129
2144
  number: numbers.length ? numbers[0].number : '',
2130
2145
  numbers,
2131
2146
  emails,
@@ -2226,7 +2241,7 @@ class Contact {
2226
2241
  } = {}) {
2227
2242
  this.id = id;
2228
2243
  this.uuid = uuid;
2229
- this.name = name;
2244
+ this.name = name || '';
2230
2245
  this.number = number;
2231
2246
  this.numbers = numbers;
2232
2247
  this.email = email;
@@ -3535,17 +3550,66 @@ var updateFrom = (instance , from ) => {
3535
3550
 
3536
3551
  //
3537
3552
 
3553
+
3554
+
3555
+
3556
+
3557
+
3558
+
3559
+
3560
+
3561
+
3562
+
3563
+
3564
+
3565
+
3566
+
3567
+
3568
+
3569
+ class Recording {
3570
+
3571
+
3572
+
3573
+
3574
+
3575
+
3576
+ static parseMany(recordings ) {
3577
+ return recordings.map(item => Recording.parse(item));
3578
+ }
3579
+
3580
+ static parse(plain ) {
3581
+ return new Recording({
3582
+ deleted: plain.deleted,
3583
+ fileName: plain.filename,
3584
+ end: plain.end_time ? moment(plain.end_time).toDate() : null,
3585
+ start: moment(plain.start_time).toDate(),
3586
+ uuid: plain.uuid,
3587
+ });
3588
+ }
3589
+
3590
+ constructor({ deleted, end, fileName, start, uuid } ) {
3591
+ this.deleted = deleted;
3592
+ this.end = end;
3593
+ this.fileName = fileName;
3594
+ this.start = start;
3595
+ this.uuid = uuid;
3596
+ }
3597
+ }
3598
+
3599
+ //
3600
+
3538
3601
 
3539
-
3602
+
3540
3603
 
3541
3604
 
3542
3605
 
3543
3606
 
3544
3607
 
3545
-
3608
+
3546
3609
 
3547
3610
 
3548
3611
 
3612
+
3549
3613
 
3550
3614
 
3551
3615
 
@@ -3558,7 +3622,7 @@ var updateFrom = (instance , from ) => {
3558
3622
 
3559
3623
 
3560
3624
 
3561
-
3625
+
3562
3626
 
3563
3627
 
3564
3628
 
@@ -3573,13 +3637,14 @@ var updateFrom = (instance , from ) => {
3573
3637
 
3574
3638
 
3575
3639
 
3576
-
3640
+
3641
+
3577
3642
 
3578
3643
 
3579
3644
  class CallLog {
3580
3645
 
3581
3646
 
3582
-
3647
+
3583
3648
 
3584
3649
 
3585
3650
 
@@ -3596,7 +3661,7 @@ class CallLog {
3596
3661
 
3597
3662
 
3598
3663
 
3599
-
3664
+
3600
3665
 
3601
3666
  static merge(current , toMerge ) {
3602
3667
  const onlyUnique = (value, index, self) => self.indexOf(value) === index;
@@ -3613,7 +3678,7 @@ class CallLog {
3613
3678
 
3614
3679
  static parse(plain ) {
3615
3680
  return new CallLog({
3616
- answer: moment(plain.answer).toDate(),
3681
+ answer: plain.answer ? moment(plain.answer).toDate() : null,
3617
3682
  answered: plain.answered,
3618
3683
  callDirection: plain.call_direction,
3619
3684
  destination: {
@@ -3627,13 +3692,14 @@ class CallLog {
3627
3692
  id: plain.id,
3628
3693
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3629
3694
  start: moment(plain.start).toDate(),
3630
- end: moment(plain.end).toDate(),
3695
+ end: plain.end ? moment(plain.end).toDate() : null,
3696
+ recordings: Recording.parseMany(plain.recordings),
3631
3697
  });
3632
3698
  }
3633
3699
 
3634
3700
  static parseNew(plain , session ) {
3635
3701
  return new CallLog({
3636
- answer: moment(plain.answer).toDate(),
3702
+ answer: plain.answer ? moment(plain.answer).toDate() : null,
3637
3703
  answered: plain.answered,
3638
3704
  callDirection: plain.call_direction,
3639
3705
  destination: {
@@ -3647,7 +3713,8 @@ class CallLog {
3647
3713
  id: plain.id,
3648
3714
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3649
3715
  start: moment(plain.start).toDate(),
3650
- end: moment(plain.end).toDate(),
3716
+ end: plain.end ? moment(plain.end).toDate() : null,
3717
+ recordings: Recording.parseMany(plain.recordings),
3651
3718
  // @TODO: FIXME add verification declined vs missed call
3652
3719
  newMissedCall: session
3653
3720
  && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
@@ -4883,6 +4950,10 @@ class ApiClient {
4883
4950
  this.fetchOptions = fetchOptions;
4884
4951
  this.client.setFetchOptions(fetchOptions);
4885
4952
  }
4953
+
4954
+ disableErrorLogging() {
4955
+ this.client.disableErrorLogging();
4956
+ }
4886
4957
  }
4887
4958
 
4888
4959
  //
@@ -5372,9 +5443,15 @@ class WebRTCClient extends Emitter {
5372
5443
 
5373
5444
  call(number , enableVideo , audioOnly = false, conference = false) {
5374
5445
  logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
5375
- const inviterOptions = {};
5446
+ const inviterOptions = {
5447
+ sessionDescriptionHandlerOptionsReInvite: {
5448
+ conference,
5449
+ audioOnly,
5450
+ },
5451
+ };
5452
+
5376
5453
  if (audioOnly) {
5377
- inviterOptions.sessionDescriptionHandlerModifiersReInvite = [deactivateVideoModifier];
5454
+ inviterOptions.sessionDescriptionHandlerModifiersReInvite = [stripVideo];
5378
5455
  }
5379
5456
 
5380
5457
  const session = new Inviter(this.userAgent, this._makeURI(number), inviterOptions);
@@ -5403,10 +5480,11 @@ class WebRTCClient extends Emitter {
5403
5480
  sessionDescriptionHandlerOptions: this.getMediaConfiguration(enableVideo || false, conference),
5404
5481
  };
5405
5482
 
5406
- inviteOptions.sessionDescriptionHandlerModifiers = [replaceLocalIpModifier];
5483
+ inviteOptions.sessionDescriptionHandlerOptions.audioOnly = audioOnly;
5407
5484
 
5485
+ inviteOptions.sessionDescriptionHandlerModifiers = [replaceLocalIpModifier];
5408
5486
  if (audioOnly) {
5409
- inviteOptions.sessionDescriptionHandlerModifiers.push(deactivateVideoModifier);
5487
+ inviteOptions.sessionDescriptionHandlerModifiers.push(stripVideo);
5410
5488
  }
5411
5489
 
5412
5490
  // Do not await invite here or we'll miss the Establishing state transition
@@ -5620,6 +5698,9 @@ class WebRTCClient extends Emitter {
5620
5698
  if (!this._isWeb()) {
5621
5699
  options.sessionDescriptionHandlerModifiers = [holdModifier];
5622
5700
  }
5701
+ options.sessionDescriptionHandlerOptions = {
5702
+ constraints: options.constraints,
5703
+ };
5623
5704
 
5624
5705
  // Send re-INVITE
5625
5706
  return session.invite(options);
@@ -5659,6 +5740,9 @@ class WebRTCClient extends Emitter {
5659
5740
  // (eg: holdModifier)
5660
5741
  options.sessionDescriptionHandlerModifiers = [];
5661
5742
  }
5743
+ options.sessionDescriptionHandlerOptions = {
5744
+ constraints: options.constraints,
5745
+ };
5662
5746
 
5663
5747
  // Send re-INVITE
5664
5748
  return session.invite(options);
@@ -5888,7 +5972,8 @@ class WebRTCClient extends Emitter {
5888
5972
  ? this.video.deviceId.exact : undefined;
5889
5973
  }
5890
5974
 
5891
- reinvite(sipSession , newConstraints = null, conference = false) {
5975
+ reinvite(sipSession , newConstraints = null, conference = false,
5976
+ audioOnly = false) {
5892
5977
  if (!sipSession) {
5893
5978
  return false;
5894
5979
  }
@@ -5898,16 +5983,17 @@ class WebRTCClient extends Emitter {
5898
5983
  }
5899
5984
 
5900
5985
  const wasMuted = this.isAudioMuted(sipSession);
5901
- // When upgrading to video, remove the `deactivateVideoModifier` modifiers
5986
+ // When upgrading to video, remove the `stripVideo` modifiers
5902
5987
  if (newConstraints && newConstraints.video) {
5903
5988
  const modifiers = sipSession.sessionDescriptionHandlerModifiersReInvite;
5904
5989
  sipSession.sessionDescriptionHandlerModifiersReInvite = modifiers.filter(modifier =>
5905
- modifier !== deactivateVideoModifier);
5990
+ modifier !== stripVideo);
5906
5991
  }
5907
5992
 
5908
5993
  sipSession.sessionDescriptionHandlerOptionsReInvite = {
5909
5994
  ...sipSession.sessionDescriptionHandlerOptionsReInvite,
5910
5995
  conference,
5996
+ audioOnly,
5911
5997
  };
5912
5998
 
5913
5999
  const shouldDoVideo = newConstraints ? newConstraints.video : this.sessionWantsToDoVideo(sipSession);
@@ -5947,6 +6033,8 @@ class WebRTCClient extends Emitter {
5947
6033
  },
5948
6034
  sessionDescriptionHandlerOptions: {
5949
6035
  constraints,
6036
+ conference,
6037
+ audioOnly,
5950
6038
  offerOptions: {
5951
6039
  iceRestart: false,
5952
6040
  },
@@ -6406,6 +6494,8 @@ class WebRTCClient extends Emitter {
6406
6494
 
6407
6495
  // Invitation and Inviter extends Session
6408
6496
  _setupSession(session ) {
6497
+ const sipSessionId = this.getSipSessionId(session);
6498
+
6409
6499
  // When receiving an Invitation, the delegate is not defined.
6410
6500
  if (!session.delegate) {
6411
6501
  session.delegate = {};
@@ -6429,8 +6519,18 @@ class WebRTCClient extends Emitter {
6429
6519
  };
6430
6520
  };
6431
6521
 
6522
+ const oldInviteRequest = session.onInviteRequest.bind(session);
6523
+ let hadRemoteVideo = false;
6524
+
6525
+ // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
6526
+ // Becase when `onInvite` is called we already got the video track
6527
+ session.onInviteRequest = (request) => {
6528
+ hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
6529
+
6530
+ oldInviteRequest(request);
6531
+ };
6532
+
6432
6533
  session.delegate.onInvite = (request ) => {
6433
- const sipSessionId = this.getSipSessionId(session);
6434
6534
  let updatedCalleeName = null;
6435
6535
  let updatedNumber = null;
6436
6536
  if (session.assertedIdentity) {
@@ -6440,7 +6540,6 @@ class WebRTCClient extends Emitter {
6440
6540
  logger.info('re-invite received', { updatedCalleeName, updatedNumber });
6441
6541
 
6442
6542
  // Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
6443
- const hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
6444
6543
 
6445
6544
  // Update SDP
6446
6545
  // Remote video is handled by the `track` event. Here we're dealing with video stream removal.
@@ -6490,7 +6589,7 @@ class WebRTCClient extends Emitter {
6490
6589
  }
6491
6590
 
6492
6591
  _isAudioOnly(session ) {
6493
- return session.sessionDescriptionHandlerModifiersReInvite.find(modifier => modifier === deactivateVideoModifier);
6592
+ return session.sessionDescriptionHandlerModifiersReInvite.find(modifier => modifier === stripVideo);
6494
6593
  }
6495
6594
 
6496
6595
  _setupMedias(session , newStream ) {
package/esm/api/agentd.js CHANGED
@@ -305,7 +305,13 @@ class IssueReporter {
305
305
  }
306
306
 
307
307
  _isLevelAbove(level1 , level2 ) {
308
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
308
+ const index1 = LOG_LEVELS.indexOf(level1);
309
+ const index2 = LOG_LEVELS.indexOf(level2);
310
+ if (index1 === -1 || index2 === -1) {
311
+ return false;
312
+ }
313
+
314
+ return index1 > index2;
309
315
  }
310
316
 
311
317
  _makeCategory(category ) {
@@ -363,6 +369,7 @@ class ApiRequester {
363
369
 
364
370
 
365
371
 
372
+
366
373
 
367
374
 
368
375
 
@@ -402,6 +409,8 @@ class ApiRequester {
402
409
  this.token = token;
403
410
  }
404
411
 
412
+ this.shouldLogErrors = true;
413
+
405
414
  methods.forEach(method => {
406
415
  // $FlowFixMe
407
416
  ApiRequester.prototype[method] = function sugar(...args) {
@@ -425,6 +434,14 @@ class ApiRequester {
425
434
  this.fetchOptions = options;
426
435
  }
427
436
 
437
+ disableErrorLogging() {
438
+ this.shouldLogErrors = false;
439
+ }
440
+
441
+ enableErrorLogging() {
442
+ this.shouldLogErrors = true;
443
+ }
444
+
428
445
  async call(
429
446
  path ,
430
447
  method = 'get',
@@ -485,7 +502,9 @@ class ApiRequester {
485
502
  ? exceptionClass.fromText(err, response.status)
486
503
  : exceptionClass.fromResponse(err, response.status);
487
504
 
488
- logger.error('API error', error);
505
+ if (this.shouldLogErrors) {
506
+ logger.error('API error', error);
507
+ }
489
508
 
490
509
  throw error;
491
510
  });
@@ -493,7 +512,9 @@ class ApiRequester {
493
512
 
494
513
  return newParse(response, isJson);
495
514
  }).catch(error => {
496
- logger.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
515
+ if (this.shouldLogErrors) {
516
+ logger.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
517
+ }
497
518
 
498
519
  throw error;
499
520
  });
package/esm/api/amid.js CHANGED
@@ -244,7 +244,13 @@ class IssueReporter {
244
244
  }
245
245
 
246
246
  _isLevelAbove(level1 , level2 ) {
247
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
247
+ const index1 = LOG_LEVELS.indexOf(level1);
248
+ const index2 = LOG_LEVELS.indexOf(level2);
249
+ if (index1 === -1 || index2 === -1) {
250
+ return false;
251
+ }
252
+
253
+ return index1 > index2;
248
254
  }
249
255
 
250
256
  _makeCategory(category ) {
@@ -305,7 +305,13 @@ class IssueReporter {
305
305
  }
306
306
 
307
307
  _isLevelAbove(level1 , level2 ) {
308
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
308
+ const index1 = LOG_LEVELS.indexOf(level1);
309
+ const index2 = LOG_LEVELS.indexOf(level2);
310
+ if (index1 === -1 || index2 === -1) {
311
+ return false;
312
+ }
313
+
314
+ return index1 > index2;
309
315
  }
310
316
 
311
317
  _makeCategory(category ) {
@@ -363,6 +369,7 @@ class ApiRequester {
363
369
 
364
370
 
365
371
 
372
+
366
373
 
367
374
 
368
375
 
@@ -402,6 +409,8 @@ class ApiRequester {
402
409
  this.token = token;
403
410
  }
404
411
 
412
+ this.shouldLogErrors = true;
413
+
405
414
  methods.forEach(method => {
406
415
  // $FlowFixMe
407
416
  ApiRequester.prototype[method] = function sugar(...args) {
@@ -425,6 +434,14 @@ class ApiRequester {
425
434
  this.fetchOptions = options;
426
435
  }
427
436
 
437
+ disableErrorLogging() {
438
+ this.shouldLogErrors = false;
439
+ }
440
+
441
+ enableErrorLogging() {
442
+ this.shouldLogErrors = true;
443
+ }
444
+
428
445
  async call(
429
446
  path ,
430
447
  method = 'get',
@@ -485,7 +502,9 @@ class ApiRequester {
485
502
  ? exceptionClass.fromText(err, response.status)
486
503
  : exceptionClass.fromResponse(err, response.status);
487
504
 
488
- logger.error('API error', error);
505
+ if (this.shouldLogErrors) {
506
+ logger.error('API error', error);
507
+ }
489
508
 
490
509
  throw error;
491
510
  });
@@ -493,7 +512,9 @@ class ApiRequester {
493
512
 
494
513
  return newParse(response, isJson);
495
514
  }).catch(error => {
496
- logger.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
515
+ if (this.shouldLogErrors) {
516
+ logger.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
517
+ }
497
518
 
498
519
  throw error;
499
520
  });