@wazo/sdk 0.37.25 → 0.37.29

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 (125) hide show
  1. package/README.md +96 -58
  2. package/dist/wazo-sdk.js +3 -3
  3. package/esm/__tests__/api-client.test.js +2 -2
  4. package/esm/__tests__/web-rtc-client.test.js +10 -5
  5. package/esm/api/agentd.js +1 -1
  6. package/esm/api/amid.js +1 -1
  7. package/esm/api/application.js +1 -1
  8. package/esm/api/auth.js +1 -1
  9. package/esm/api/call-logd.js +1 -1
  10. package/esm/api/calld.js +1 -1
  11. package/esm/api/chatd.js +1 -1
  12. package/esm/api/confd.js +1 -1
  13. package/esm/api/ctid-ng.js +1 -1
  14. package/esm/api/dird.js +2 -2
  15. package/esm/api/webhookd.js +1 -1
  16. package/esm/api-client.js +2 -2
  17. package/esm/checker/Checker.js +10 -5
  18. package/esm/checker/checks/aor.js +2 -2
  19. package/esm/checker/checks/api.js +2 -2
  20. package/esm/checker/checks/index.js +10 -5
  21. package/esm/checker/checks/wazo-websocket.js +1 -1
  22. package/esm/checker/checks/webrtc-transport.js +10 -5
  23. package/esm/checker/checks/webrtc.js +10 -5
  24. package/esm/domain/AdHocAPIConference.js +2 -2
  25. package/esm/domain/CallSession.js +29 -2
  26. package/esm/domain/Contact.js +1 -1
  27. package/esm/domain/Features.js +2 -2
  28. package/esm/domain/Phone/CTIPhone.js +31 -4
  29. package/esm/domain/Phone/WebRTCPhone.js +55 -6
  30. package/esm/domain/SFUNotAvailableError.js +9 -0
  31. package/esm/domain/__tests__/CallSession.test.js +46 -2
  32. package/esm/domain/__tests__/Contact.test.js +1 -1
  33. package/esm/domain/__tests__/IndirectTransfer.test.js +29 -2
  34. package/esm/domain/__tests__/Room.test.js +29 -2
  35. package/esm/index.js +75 -10
  36. package/esm/lib/WazoSessionDescriptionHandler.js +9 -4
  37. package/esm/service/CallApi.js +2 -2
  38. package/esm/service/IssueReporter.js +1 -1
  39. package/esm/service/__tests__/IssueReporter.test.js +1 -1
  40. package/esm/service/getApiClient.js +2 -2
  41. package/esm/simple/Auth.js +74 -10
  42. package/esm/simple/Configuration.js +74 -10
  43. package/esm/simple/Directory.js +2 -2
  44. package/esm/simple/Phone.js +74 -10
  45. package/esm/simple/Websocket.js +1 -1
  46. package/esm/simple/index.js +74 -10
  47. package/esm/simple/room/LocalParticipant.js +74 -10
  48. package/esm/simple/room/Participant.js +74 -10
  49. package/esm/simple/room/RemoteParticipant.js +74 -10
  50. package/esm/simple/room/Room.js +74 -10
  51. package/esm/simple/room/SipRoom.js +74 -10
  52. package/esm/simple/room/Stream.js +74 -10
  53. package/esm/simple/room/__tests__/RemoteParticipant.test.js +74 -10
  54. package/esm/simple/utils.js +74 -10
  55. package/esm/utils/__tests__/api-requester.test.js +1 -1
  56. package/esm/utils/api-requester.js +1 -1
  57. package/esm/web-rtc-client.js +10 -5
  58. package/esm/websocket-client.js +1 -1
  59. package/lib/__tests__/api-client.test.js +2 -2
  60. package/lib/__tests__/web-rtc-client.test.js +10 -5
  61. package/lib/api/agentd.js +1 -1
  62. package/lib/api/amid.js +1 -1
  63. package/lib/api/application.js +1 -1
  64. package/lib/api/auth.js +1 -1
  65. package/lib/api/call-logd.js +1 -1
  66. package/lib/api/calld.js +1 -1
  67. package/lib/api/chatd.js +1 -1
  68. package/lib/api/confd.js +1 -1
  69. package/lib/api/ctid-ng.js +1 -1
  70. package/lib/api/dird.js +2 -2
  71. package/lib/api/webhookd.js +1 -1
  72. package/lib/api-client.js +2 -2
  73. package/lib/checker/Checker.js +10 -5
  74. package/lib/checker/checks/aor.js +2 -2
  75. package/lib/checker/checks/api.js +2 -2
  76. package/lib/checker/checks/index.js +10 -5
  77. package/lib/checker/checks/wazo-websocket.js +1 -1
  78. package/lib/checker/checks/webrtc-transport.js +10 -5
  79. package/lib/checker/checks/webrtc.js +10 -5
  80. package/lib/domain/AdHocAPIConference.js +2 -2
  81. package/lib/domain/CallSession.js +29 -2
  82. package/lib/domain/Contact.js +1 -1
  83. package/lib/domain/Features.js +2 -2
  84. package/lib/domain/Phone/CTIPhone.js +31 -4
  85. package/lib/domain/Phone/WebRTCPhone.js +55 -5
  86. package/lib/domain/SFUNotAvailableError.js +11 -0
  87. package/lib/domain/__tests__/CallSession.test.js +46 -2
  88. package/lib/domain/__tests__/Contact.test.js +1 -1
  89. package/lib/domain/__tests__/IndirectTransfer.test.js +29 -2
  90. package/lib/domain/__tests__/Room.test.js +29 -2
  91. package/lib/index.js +75 -10
  92. package/lib/lib/WazoSessionDescriptionHandler.js +9 -4
  93. package/lib/service/CallApi.js +2 -2
  94. package/lib/service/IssueReporter.js +1 -1
  95. package/lib/service/__tests__/IssueReporter.test.js +1 -1
  96. package/lib/service/getApiClient.js +2 -2
  97. package/lib/simple/Auth.js +74 -10
  98. package/lib/simple/Configuration.js +74 -10
  99. package/lib/simple/Directory.js +2 -2
  100. package/lib/simple/Phone.js +74 -10
  101. package/lib/simple/Websocket.js +1 -1
  102. package/lib/simple/index.js +74 -10
  103. package/lib/simple/room/LocalParticipant.js +74 -10
  104. package/lib/simple/room/Participant.js +74 -10
  105. package/lib/simple/room/RemoteParticipant.js +74 -10
  106. package/lib/simple/room/Room.js +74 -10
  107. package/lib/simple/room/SipRoom.js +74 -10
  108. package/lib/simple/room/Stream.js +74 -10
  109. package/lib/simple/room/__tests__/RemoteParticipant.test.js +74 -10
  110. package/lib/simple/utils.js +74 -10
  111. package/lib/utils/__tests__/api-requester.test.js +1 -1
  112. package/lib/utils/api-requester.js +1 -1
  113. package/lib/web-rtc-client.js +10 -5
  114. package/lib/websocket-client.js +1 -1
  115. package/package.json +1 -1
  116. package/src/domain/CallSession.js +32 -4
  117. package/src/domain/Contact.js +1 -1
  118. package/src/domain/Phone/WebRTCPhone.js +24 -2
  119. package/src/domain/SFUNotAvailableError.js +7 -0
  120. package/src/domain/__tests__/CallSession.test.js +17 -0
  121. package/src/index.js +2 -0
  122. package/src/lib/WazoSessionDescriptionHandler.js +8 -3
  123. package/src/simple/Phone.js +2 -1
  124. package/src/simple/index.js +2 -0
  125. package/src/utils/api-requester.js +1 -1
package/esm/index.js CHANGED
@@ -464,7 +464,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
464
464
 
465
465
  // Use a function here to be able to mock it in tests
466
466
  const realFetch = () => {
467
- if (typeof document !== 'undefined') {
467
+ if (typeof document !== 'undefined' && window.fetch) {
468
468
  // Browser
469
469
  return window.fetch;
470
470
  }
@@ -1924,7 +1924,7 @@ class Contact {
1924
1924
  this[key] = old[key] || this[key];
1925
1925
  });
1926
1926
 
1927
- if (old.lineState && !this.lineState) {
1927
+ if (old.lineState) {
1928
1928
  this.lineState = old.lineState;
1929
1929
  }
1930
1930
 
@@ -3249,13 +3249,16 @@ var updateFrom = (instance , from ) => {
3249
3249
 
3250
3250
 
3251
3251
 
3252
+
3252
3253
 
3253
3254
 
3254
3255
 
3255
3256
 
3256
3257
 
3258
+
3257
3259
 
3258
3260
 
3261
+
3259
3262
 
3260
3263
 
3261
3264
 
@@ -3272,6 +3275,7 @@ var updateFrom = (instance , from ) => {
3272
3275
 
3273
3276
 
3274
3277
 
3278
+
3275
3279
 
3276
3280
 
3277
3281
  class CallSession {
@@ -3291,10 +3295,14 @@ class CallSession {
3291
3295
 
3292
3296
 
3293
3297
 
3294
-
3298
+
3299
+
3300
+ // = creationTime
3295
3301
 
3296
3302
 
3297
3303
 
3304
+
3305
+
3298
3306
 
3299
3307
 
3300
3308
 
@@ -3330,6 +3338,8 @@ class CallSession {
3330
3338
 
3331
3339
 
3332
3340
 
3341
+
3342
+
3333
3343
 
3334
3344
  constructor({
3335
3345
  answered,
@@ -3343,6 +3353,8 @@ class CallSession {
3343
3353
  paused,
3344
3354
  ringing,
3345
3355
  startTime,
3356
+ creationTime,
3357
+ endTime,
3346
3358
  cameraEnabled,
3347
3359
  dialedExtension,
3348
3360
  sipCallId,
@@ -3355,12 +3367,16 @@ class CallSession {
3355
3367
  recording,
3356
3368
  recordingPaused,
3357
3369
  videoRemotelyDowngraded,
3370
+ sipSession,
3371
+ answerTime,
3358
3372
  } ) {
3359
3373
  this.callId = callId;
3360
3374
  this.sipCallId = sipCallId;
3361
3375
  this.displayName = displayName;
3362
3376
  this.number = number;
3377
+ this.creationTime = creationTime;
3363
3378
  this.startTime = startTime;
3379
+ this.endTime = endTime;
3364
3380
  this.isCaller = isCaller;
3365
3381
  this.answered = answered;
3366
3382
  this.answeredBySystem = answeredBySystem;
@@ -3379,6 +3395,8 @@ class CallSession {
3379
3395
  this.recording = recording || false;
3380
3396
  this.recordingPaused = recordingPaused || false;
3381
3397
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3398
+ this.sipSession = sipSession;
3399
+ this.answerTime = answerTime || this.answerTime;
3382
3400
 
3383
3401
  // Useful to compare instead of instanceof with minified code
3384
3402
  this.type = 'CallSession';
@@ -3409,7 +3427,7 @@ class CallSession {
3409
3427
  }
3410
3428
 
3411
3429
  answer() {
3412
- this.answered = true;
3430
+ this.answerTime = new Date();
3413
3431
  }
3414
3432
 
3415
3433
  systemAnswer() {
@@ -3565,6 +3583,15 @@ class CallSession {
3565
3583
  return newFrom(callSession, CallSession);
3566
3584
  }
3567
3585
 
3586
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3587
+ set answered(value ) {
3588
+ this.answerTime = value ? new Date() : null;
3589
+ }
3590
+
3591
+ get answered() {
3592
+ return !!this.answerTime;
3593
+ }
3594
+
3568
3595
  static parseCall(call ) {
3569
3596
  return new CallSession({
3570
3597
  callId: call.id,
@@ -5624,11 +5651,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5624
5651
 
5625
5652
  // $FlowFixMe
5626
5653
  setRemoteSessionDescription(sessionDescription ) {
5627
- const result = super.setRemoteSessionDescription(sessionDescription);
5654
+ try {
5655
+ const result = super.setRemoteSessionDescription(sessionDescription);
5628
5656
 
5629
- this.eventEmitter.emit('setDescription', sessionDescription);
5657
+ this.eventEmitter.emit('setDescription', sessionDescription);
5630
5658
 
5631
- return result;
5659
+ return result;
5660
+ } catch (error) {
5661
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
5662
+ throw error;
5663
+ }
5632
5664
  }
5633
5665
 
5634
5666
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -8776,6 +8808,14 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
8776
8808
  'default': WebSocketClient
8777
8809
  });
8778
8810
 
8811
+ /* */
8812
+ class SFUNotAvailableError extends Error {
8813
+ constructor(message = 'Sorry your user is not configured to support video conference') {
8814
+ super(message);
8815
+ this.name = 'SFUNotAvailableError';
8816
+ }
8817
+ }
8818
+
8779
8819
  var COUNTRIES = {
8780
8820
  BELGIUM: 'BE',
8781
8821
  CANADA: 'CA',
@@ -9173,6 +9213,7 @@ const ON_CAMERA_DISABLED = 'onCameraDisabled';
9173
9213
  const ON_CAMERA_RESUMED = 'onCameraResumed';
9174
9214
  const ON_CALL_CANCELED = 'onCallCanceled';
9175
9215
  const ON_CALL_FAILED = 'onCallFailed';
9216
+ const ON_CALL_REJECTED = 'onCallRejected';
9176
9217
  const ON_CALL_ENDED = 'onCallEnded';
9177
9218
  const ON_CALL_ENDING = 'onCallEnding';
9178
9219
  const ON_MESSAGE = 'onMessage';
@@ -9217,6 +9258,7 @@ const events = [
9217
9258
  ON_CAMERA_DISABLED,
9218
9259
  ON_CALL_FAILED,
9219
9260
  ON_CALL_ENDED,
9261
+ ON_CALL_REJECTED,
9220
9262
  ON_MESSAGE,
9221
9263
  ON_REINVITE,
9222
9264
  ON_TRACK,
@@ -9573,6 +9615,7 @@ class WebRTCPhone extends Emitter {
9573
9615
 
9574
9616
  // Should be called before `_onCallTerminated` or the callCount will not decrement...
9575
9617
  const callSession = this._createCallSession(sipSession);
9618
+ callSession.endTime = new Date();
9576
9619
  const wasCurrentSession = this._onCallTerminated(sipSession);
9577
9620
 
9578
9621
  return this.eventEmitter.emit(ON_CALL_ENDED, callSession, wasCurrentSession);
@@ -9768,6 +9811,7 @@ class WebRTCPhone extends Emitter {
9768
9811
  this.removeIncomingSessions(sipSessionId);
9769
9812
  }
9770
9813
 
9814
+ callSession.answerTime = new Date();
9771
9815
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9772
9816
 
9773
9817
  return callSession;
@@ -9825,6 +9869,7 @@ class WebRTCPhone extends Emitter {
9825
9869
  _onCallTerminated(sipSession ) {
9826
9870
  logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9827
9871
 
9872
+ const sipSessionId = this.getSipSessionId(sipSession);
9828
9873
  const callSession = this._createCallSession(sipSession);
9829
9874
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9830
9875
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9842,7 +9887,6 @@ class WebRTCPhone extends Emitter {
9842
9887
  }, 5);
9843
9888
  }
9844
9889
 
9845
- const sipSessionId = this.getSipSessionId(sipSession);
9846
9890
  if (sipSessionId) {
9847
9891
  this.removeIncomingSessions(sipSessionId);
9848
9892
  }
@@ -9983,6 +10027,7 @@ class WebRTCPhone extends Emitter {
9983
10027
  }
9984
10028
 
9985
10029
  this.shouldSendReinvite = false;
10030
+ callSession.answerTime = new Date();
9986
10031
  this.acceptedSessions[callSession.getId()] = true;
9987
10032
 
9988
10033
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -10292,6 +10337,7 @@ class WebRTCPhone extends Emitter {
10292
10337
  return Promise.resolve(null);
10293
10338
  }
10294
10339
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
10340
+ callSession.creationTime = new Date();
10295
10341
 
10296
10342
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
10297
10343
 
@@ -10487,8 +10533,12 @@ class WebRTCPhone extends Emitter {
10487
10533
  }
10488
10534
 
10489
10535
  const sessionId = this.incomingSessions[0];
10536
+ const sipSession = this.client.getSipSession(sessionId);
10537
+ if (!sipSession) {
10538
+ return null;
10539
+ }
10490
10540
 
10491
- return this._createCallSession(this.client.getSipSession(sessionId));
10541
+ return this._createCallSession(sipSession);
10492
10542
  }
10493
10543
 
10494
10544
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -10566,6 +10616,7 @@ class WebRTCPhone extends Emitter {
10566
10616
  callSession);
10567
10617
  }
10568
10618
 
10619
+ callSession.creationTime = new Date();
10569
10620
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10570
10621
  });
10571
10622
 
@@ -10605,6 +10656,13 @@ class WebRTCPhone extends Emitter {
10605
10656
  this.eventEmitter.emit(ON_CALL_ERROR, e);
10606
10657
  });
10607
10658
 
10659
+ this.client.on(this.client.REJECTED, session => {
10660
+ logger$7.info('WebRTC call rejected', session.id);
10661
+ const callSession = this._createCallSession(session);
10662
+ callSession.endTime = new Date();
10663
+ this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10664
+ });
10665
+
10608
10666
  this.client.on(this.client.UNREGISTERED, () => {
10609
10667
  logger$7.info('WebRTC unregistered');
10610
10668
  this.eventEmitter.emit(ON_UNREGISTERED);
@@ -10817,6 +10875,7 @@ class WebRTCPhone extends Emitter {
10817
10875
  const number = identity ? identity.uri._normal.user : null;
10818
10876
  const { state } = sipSession || {};
10819
10877
  const sessionId = this.getSipSessionId(sipSession);
10878
+ fromSession = fromSession || this.callSessions[sessionId];
10820
10879
 
10821
10880
  const callSession = new CallSession({
10822
10881
  callId: fromSession && fromSession.callId,
@@ -10824,6 +10883,8 @@ class WebRTCPhone extends Emitter {
10824
10883
  sipStatus: state,
10825
10884
  displayName: identity ? identity.displayName || number : number,
10826
10885
  startTime: fromSession ? fromSession.startTime : new Date(),
10886
+ creationTime: fromSession ? fromSession.creationTime : null,
10887
+ endTime: fromSession ? fromSession.endTime : null,
10827
10888
  answered: state === SessionState.Established,
10828
10889
  paused: this.client.isCallHeld(sipSession),
10829
10890
  isCaller: 'incoming' in extra ? !extra.incoming : false,
@@ -10834,6 +10895,7 @@ class WebRTCPhone extends Emitter {
10834
10895
  videoMuted: fromSession ? fromSession.isVideoMuted() : false,
10835
10896
  recording: fromSession ? fromSession.isRecording() : false,
10836
10897
  recordingPaused: false, // @TODO
10898
+ sipSession,
10837
10899
  ...extra,
10838
10900
  });
10839
10901
 
@@ -10862,6 +10924,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10862
10924
  ON_CAMERA_RESUMED: ON_CAMERA_RESUMED,
10863
10925
  ON_CALL_CANCELED: ON_CALL_CANCELED,
10864
10926
  ON_CALL_FAILED: ON_CALL_FAILED,
10927
+ ON_CALL_REJECTED: ON_CALL_REJECTED,
10865
10928
  ON_CALL_ENDED: ON_CALL_ENDED,
10866
10929
  ON_CALL_ENDING: ON_CALL_ENDING,
10867
10930
  ON_MESSAGE: ON_MESSAGE,
@@ -12310,7 +12373,7 @@ class Phone extends Emitter {
12310
12373
 
12311
12374
  checkSfu() {
12312
12375
  if (!this.hasSfu()) {
12313
- throw new Error('Sorry your user is not configured to support video conference');
12376
+ throw new SFUNotAvailableError();
12314
12377
  }
12315
12378
  }
12316
12379
 
@@ -13871,6 +13934,7 @@ const Wazo = {
13871
13934
  InvalidSubscription,
13872
13935
  InvalidAuthorization,
13873
13936
  CanceledCallError,
13937
+ SFUNotAvailableError,
13874
13938
  };
13875
13939
 
13876
13940
  if (window) {
@@ -13913,6 +13977,7 @@ var index = {
13913
13977
  WazoWebSocketClient: WebSocketClient,
13914
13978
  BadResponse,
13915
13979
  ServerError,
13980
+ SFUNotAvailableError,
13916
13981
  Call,
13917
13982
  CallSession,
13918
13983
  CTIPhone,
@@ -15,7 +15,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
15
15
 
16
16
  // Use a function here to be able to mock it in tests
17
17
  const realFetch = () => {
18
- if (typeof document !== 'undefined') {
18
+ if (typeof document !== 'undefined' && window.fetch) {
19
19
  // Browser
20
20
  return window.fetch;
21
21
  }
@@ -487,11 +487,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
487
487
 
488
488
  // $FlowFixMe
489
489
  setRemoteSessionDescription(sessionDescription ) {
490
- const result = super.setRemoteSessionDescription(sessionDescription);
490
+ try {
491
+ const result = super.setRemoteSessionDescription(sessionDescription);
491
492
 
492
- this.eventEmitter.emit('setDescription', sessionDescription);
493
+ this.eventEmitter.emit('setDescription', sessionDescription);
493
494
 
494
- return result;
495
+ return result;
496
+ } catch (error) {
497
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
498
+ throw error;
499
+ }
495
500
  }
496
501
 
497
502
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -1410,7 +1410,7 @@ class Contact {
1410
1410
  this[key] = old[key] || this[key];
1411
1411
  });
1412
1412
 
1413
- if (old.lineState && !this.lineState) {
1413
+ if (old.lineState) {
1414
1414
  this.lineState = old.lineState;
1415
1415
  }
1416
1416
 
@@ -2466,7 +2466,7 @@ const logger$1 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
2466
2466
 
2467
2467
  // Use a function here to be able to mock it in tests
2468
2468
  const realFetch = () => {
2469
- if (typeof document !== 'undefined') {
2469
+ if (typeof document !== 'undefined' && window.fetch) {
2470
2470
  // Browser
2471
2471
  return window.fetch;
2472
2472
  }
@@ -11,7 +11,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
11
11
 
12
12
  // Use a function here to be able to mock it in tests
13
13
  const realFetch = () => {
14
- if (typeof document !== 'undefined') {
14
+ if (typeof document !== 'undefined' && window.fetch) {
15
15
  // Browser
16
16
  return window.fetch;
17
17
  }
@@ -11,7 +11,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
11
11
 
12
12
  // Use a function here to be able to mock it in tests
13
13
  const realFetch = () => {
14
- if (typeof document !== 'undefined') {
14
+ if (typeof document !== 'undefined' && window.fetch) {
15
15
  // Browser
16
16
  return window.fetch;
17
17
  }
@@ -444,7 +444,7 @@ const logger$1 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
444
444
 
445
445
  // Use a function here to be able to mock it in tests
446
446
  const realFetch = () => {
447
- if (typeof document !== 'undefined') {
447
+ if (typeof document !== 'undefined' && window.fetch) {
448
448
  // Browser
449
449
  return window.fetch;
450
450
  }
@@ -1904,7 +1904,7 @@ class Contact {
1904
1904
  this[key] = old[key] || this[key];
1905
1905
  });
1906
1906
 
1907
- if (old.lineState && !this.lineState) {
1907
+ if (old.lineState) {
1908
1908
  this.lineState = old.lineState;
1909
1909
  }
1910
1910
 
@@ -1236,7 +1236,7 @@ class Contact {
1236
1236
  this[key] = old[key] || this[key];
1237
1237
  });
1238
1238
 
1239
- if (old.lineState && !this.lineState) {
1239
+ if (old.lineState) {
1240
1240
  this.lineState = old.lineState;
1241
1241
  }
1242
1242
 
@@ -1951,7 +1951,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1951
1951
 
1952
1952
  // Use a function here to be able to mock it in tests
1953
1953
  const realFetch = () => {
1954
- if (typeof document !== 'undefined') {
1954
+ if (typeof document !== 'undefined' && window.fetch) {
1955
1955
  // Browser
1956
1956
  return window.fetch;
1957
1957
  }
@@ -3248,13 +3248,16 @@ var updateFrom = (instance , from ) => {
3248
3248
 
3249
3249
 
3250
3250
 
3251
+
3251
3252
 
3252
3253
 
3253
3254
 
3254
3255
 
3255
3256
 
3257
+
3256
3258
 
3257
3259
 
3260
+
3258
3261
 
3259
3262
 
3260
3263
 
@@ -3271,6 +3274,7 @@ var updateFrom = (instance , from ) => {
3271
3274
 
3272
3275
 
3273
3276
 
3277
+
3274
3278
 
3275
3279
 
3276
3280
  class CallSession {
@@ -3290,10 +3294,14 @@ class CallSession {
3290
3294
 
3291
3295
 
3292
3296
 
3293
-
3297
+
3298
+
3299
+ // = creationTime
3294
3300
 
3295
3301
 
3296
3302
 
3303
+
3304
+
3297
3305
 
3298
3306
 
3299
3307
 
@@ -3329,6 +3337,8 @@ class CallSession {
3329
3337
 
3330
3338
 
3331
3339
 
3340
+
3341
+
3332
3342
 
3333
3343
  constructor({
3334
3344
  answered,
@@ -3342,6 +3352,8 @@ class CallSession {
3342
3352
  paused,
3343
3353
  ringing,
3344
3354
  startTime,
3355
+ creationTime,
3356
+ endTime,
3345
3357
  cameraEnabled,
3346
3358
  dialedExtension,
3347
3359
  sipCallId,
@@ -3354,12 +3366,16 @@ class CallSession {
3354
3366
  recording,
3355
3367
  recordingPaused,
3356
3368
  videoRemotelyDowngraded,
3369
+ sipSession,
3370
+ answerTime,
3357
3371
  } ) {
3358
3372
  this.callId = callId;
3359
3373
  this.sipCallId = sipCallId;
3360
3374
  this.displayName = displayName;
3361
3375
  this.number = number;
3376
+ this.creationTime = creationTime;
3362
3377
  this.startTime = startTime;
3378
+ this.endTime = endTime;
3363
3379
  this.isCaller = isCaller;
3364
3380
  this.answered = answered;
3365
3381
  this.answeredBySystem = answeredBySystem;
@@ -3378,6 +3394,8 @@ class CallSession {
3378
3394
  this.recording = recording || false;
3379
3395
  this.recordingPaused = recordingPaused || false;
3380
3396
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3397
+ this.sipSession = sipSession;
3398
+ this.answerTime = answerTime || this.answerTime;
3381
3399
 
3382
3400
  // Useful to compare instead of instanceof with minified code
3383
3401
  this.type = 'CallSession';
@@ -3408,7 +3426,7 @@ class CallSession {
3408
3426
  }
3409
3427
 
3410
3428
  answer() {
3411
- this.answered = true;
3429
+ this.answerTime = new Date();
3412
3430
  }
3413
3431
 
3414
3432
  systemAnswer() {
@@ -3564,6 +3582,15 @@ class CallSession {
3564
3582
  return newFrom(callSession, CallSession);
3565
3583
  }
3566
3584
 
3585
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3586
+ set answered(value ) {
3587
+ this.answerTime = value ? new Date() : null;
3588
+ }
3589
+
3590
+ get answered() {
3591
+ return !!this.answerTime;
3592
+ }
3593
+
3567
3594
  static parseCall(call ) {
3568
3595
  return new CallSession({
3569
3596
  callId: call.id,
@@ -5798,11 +5825,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5798
5825
 
5799
5826
  // $FlowFixMe
5800
5827
  setRemoteSessionDescription(sessionDescription ) {
5801
- const result = super.setRemoteSessionDescription(sessionDescription);
5828
+ try {
5829
+ const result = super.setRemoteSessionDescription(sessionDescription);
5802
5830
 
5803
- this.eventEmitter.emit('setDescription', sessionDescription);
5831
+ this.eventEmitter.emit('setDescription', sessionDescription);
5804
5832
 
5805
- return result;
5833
+ return result;
5834
+ } catch (error) {
5835
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
5836
+ throw error;
5837
+ }
5806
5838
  }
5807
5839
 
5808
5840
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -8454,6 +8486,7 @@ const ON_CAMERA_DISABLED = 'onCameraDisabled';
8454
8486
  const ON_CAMERA_RESUMED = 'onCameraResumed';
8455
8487
  const ON_CALL_CANCELED = 'onCallCanceled';
8456
8488
  const ON_CALL_FAILED = 'onCallFailed';
8489
+ const ON_CALL_REJECTED = 'onCallRejected';
8457
8490
  const ON_CALL_ENDED = 'onCallEnded';
8458
8491
  const ON_CALL_ENDING = 'onCallEnding';
8459
8492
  const ON_MESSAGE = 'onMessage';
@@ -8498,6 +8531,7 @@ const events = [
8498
8531
  ON_CAMERA_DISABLED,
8499
8532
  ON_CALL_FAILED,
8500
8533
  ON_CALL_ENDED,
8534
+ ON_CALL_REJECTED,
8501
8535
  ON_MESSAGE,
8502
8536
  ON_REINVITE,
8503
8537
  ON_TRACK,
@@ -8854,6 +8888,7 @@ class WebRTCPhone extends Emitter {
8854
8888
 
8855
8889
  // Should be called before `_onCallTerminated` or the callCount will not decrement...
8856
8890
  const callSession = this._createCallSession(sipSession);
8891
+ callSession.endTime = new Date();
8857
8892
  const wasCurrentSession = this._onCallTerminated(sipSession);
8858
8893
 
8859
8894
  return this.eventEmitter.emit(ON_CALL_ENDED, callSession, wasCurrentSession);
@@ -9049,6 +9084,7 @@ class WebRTCPhone extends Emitter {
9049
9084
  this.removeIncomingSessions(sipSessionId);
9050
9085
  }
9051
9086
 
9087
+ callSession.answerTime = new Date();
9052
9088
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9053
9089
 
9054
9090
  return callSession;
@@ -9106,6 +9142,7 @@ class WebRTCPhone extends Emitter {
9106
9142
  _onCallTerminated(sipSession ) {
9107
9143
  logger$8.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9108
9144
 
9145
+ const sipSessionId = this.getSipSessionId(sipSession);
9109
9146
  const callSession = this._createCallSession(sipSession);
9110
9147
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9111
9148
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9123,7 +9160,6 @@ class WebRTCPhone extends Emitter {
9123
9160
  }, 5);
9124
9161
  }
9125
9162
 
9126
- const sipSessionId = this.getSipSessionId(sipSession);
9127
9163
  if (sipSessionId) {
9128
9164
  this.removeIncomingSessions(sipSessionId);
9129
9165
  }
@@ -9264,6 +9300,7 @@ class WebRTCPhone extends Emitter {
9264
9300
  }
9265
9301
 
9266
9302
  this.shouldSendReinvite = false;
9303
+ callSession.answerTime = new Date();
9267
9304
  this.acceptedSessions[callSession.getId()] = true;
9268
9305
 
9269
9306
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9573,6 +9610,7 @@ class WebRTCPhone extends Emitter {
9573
9610
  return Promise.resolve(null);
9574
9611
  }
9575
9612
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9613
+ callSession.creationTime = new Date();
9576
9614
 
9577
9615
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9578
9616
 
@@ -9768,8 +9806,12 @@ class WebRTCPhone extends Emitter {
9768
9806
  }
9769
9807
 
9770
9808
  const sessionId = this.incomingSessions[0];
9809
+ const sipSession = this.client.getSipSession(sessionId);
9810
+ if (!sipSession) {
9811
+ return null;
9812
+ }
9771
9813
 
9772
- return this._createCallSession(this.client.getSipSession(sessionId));
9814
+ return this._createCallSession(sipSession);
9773
9815
  }
9774
9816
 
9775
9817
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -9847,6 +9889,7 @@ class WebRTCPhone extends Emitter {
9847
9889
  callSession);
9848
9890
  }
9849
9891
 
9892
+ callSession.creationTime = new Date();
9850
9893
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
9851
9894
  });
9852
9895
 
@@ -9886,6 +9929,13 @@ class WebRTCPhone extends Emitter {
9886
9929
  this.eventEmitter.emit(ON_CALL_ERROR, e);
9887
9930
  });
9888
9931
 
9932
+ this.client.on(this.client.REJECTED, session => {
9933
+ logger$8.info('WebRTC call rejected', session.id);
9934
+ const callSession = this._createCallSession(session);
9935
+ callSession.endTime = new Date();
9936
+ this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
9937
+ });
9938
+
9889
9939
  this.client.on(this.client.UNREGISTERED, () => {
9890
9940
  logger$8.info('WebRTC unregistered');
9891
9941
  this.eventEmitter.emit(ON_UNREGISTERED);
@@ -10098,6 +10148,7 @@ class WebRTCPhone extends Emitter {
10098
10148
  const number = identity ? identity.uri._normal.user : null;
10099
10149
  const { state } = sipSession || {};
10100
10150
  const sessionId = this.getSipSessionId(sipSession);
10151
+ fromSession = fromSession || this.callSessions[sessionId];
10101
10152
 
10102
10153
  const callSession = new CallSession({
10103
10154
  callId: fromSession && fromSession.callId,
@@ -10105,6 +10156,8 @@ class WebRTCPhone extends Emitter {
10105
10156
  sipStatus: state,
10106
10157
  displayName: identity ? identity.displayName || number : number,
10107
10158
  startTime: fromSession ? fromSession.startTime : new Date(),
10159
+ creationTime: fromSession ? fromSession.creationTime : null,
10160
+ endTime: fromSession ? fromSession.endTime : null,
10108
10161
  answered: state === SessionState.Established,
10109
10162
  paused: this.client.isCallHeld(sipSession),
10110
10163
  isCaller: 'incoming' in extra ? !extra.incoming : false,
@@ -10115,6 +10168,7 @@ class WebRTCPhone extends Emitter {
10115
10168
  videoMuted: fromSession ? fromSession.isVideoMuted() : false,
10116
10169
  recording: fromSession ? fromSession.isRecording() : false,
10117
10170
  recordingPaused: false, // @TODO
10171
+ sipSession,
10118
10172
  ...extra,
10119
10173
  });
10120
10174
 
@@ -10143,6 +10197,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10143
10197
  ON_CAMERA_RESUMED: ON_CAMERA_RESUMED,
10144
10198
  ON_CALL_CANCELED: ON_CALL_CANCELED,
10145
10199
  ON_CALL_FAILED: ON_CALL_FAILED,
10200
+ ON_CALL_REJECTED: ON_CALL_REJECTED,
10146
10201
  ON_CALL_ENDED: ON_CALL_ENDED,
10147
10202
  ON_CALL_ENDING: ON_CALL_ENDING,
10148
10203
  ON_MESSAGE: ON_MESSAGE,
@@ -10172,6 +10227,14 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10172
10227
  'default': WebRTCPhone
10173
10228
  });
10174
10229
 
10230
+ /* */
10231
+ class SFUNotAvailableError extends Error {
10232
+ constructor(message = 'Sorry your user is not configured to support video conference') {
10233
+ super(message);
10234
+ this.name = 'SFUNotAvailableError';
10235
+ }
10236
+ }
10237
+
10175
10238
  //
10176
10239
 
10177
10240
  const logger$7 = IssueReporter$1.loggerFor('simple-phone');
@@ -10556,7 +10619,7 @@ class Phone extends Emitter {
10556
10619
 
10557
10620
  checkSfu() {
10558
10621
  if (!this.hasSfu()) {
10559
- throw new Error('Sorry your user is not configured to support video conference');
10622
+ throw new SFUNotAvailableError();
10560
10623
  }
10561
10624
  }
10562
10625
 
@@ -13469,6 +13532,7 @@ const Wazo = {
13469
13532
  InvalidSubscription,
13470
13533
  InvalidAuthorization,
13471
13534
  CanceledCallError,
13535
+ SFUNotAvailableError,
13472
13536
  };
13473
13537
 
13474
13538
  if (window) {