@wazo/sdk 1.0.0-alpha.0 → 1.0.0-alpha.10

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 (162) hide show
  1. package/README.md +16 -7
  2. package/dist/wazo-sdk.js +6 -6
  3. package/esm/__tests__/__voice__/call.test.js +57 -2
  4. package/esm/__tests__/api-client.test.js +20 -1
  5. package/esm/api/auth.js +16 -2
  6. package/esm/checker/checks/webrtc.js +2 -2
  7. package/esm/domain/CallLog.js +2 -3
  8. package/esm/domain/Phone/CTIPhone.js +2 -2
  9. package/esm/domain/Phone/WebRTCPhone.js +64 -63
  10. package/esm/index.js +5 -1
  11. package/esm/service/CallApi.js +4 -4
  12. package/esm/simple/Auth.js +19 -15
  13. package/esm/simple/Phone.js +6 -5
  14. package/esm/simple/__tests__/Auth.test.js +8 -64
  15. package/esm/simple/index.js +2 -1
  16. package/esm/simple/room/Room.js +2 -2
  17. package/esm/simple/room/SipRoom.js +2 -2
  18. package/esm/state-machine/call-state-machine.js +2 -2
  19. package/esm/state-machine/softphone-state-machine.js +1 -2
  20. package/esm/state-machine/utils.js +8 -3
  21. package/esm/types/api/auth.d.ts +3 -0
  22. package/esm/types/api/auth.d.ts.map +1 -1
  23. package/esm/types/checker/checks/index.d.ts +1 -1
  24. package/esm/types/checker/checks/webrtc-transport.d.ts +2 -2
  25. package/esm/types/checker/checks/webrtc-transport.d.ts.map +1 -1
  26. package/esm/types/domain/CallLog.d.ts.map +1 -1
  27. package/esm/types/domain/CallSession.d.ts +3 -3
  28. package/esm/types/domain/CallSession.d.ts.map +1 -1
  29. package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -1
  30. package/esm/types/domain/Phone/WebRTCPhone.d.ts +22 -22
  31. package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  32. package/esm/types/domain/types.d.ts +0 -4
  33. package/esm/types/domain/types.d.ts.map +1 -1
  34. package/esm/types/index.d.ts +5 -1
  35. package/esm/types/index.d.ts.map +1 -1
  36. package/esm/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
  37. package/esm/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
  38. package/esm/types/service/CallApi.d.ts +5 -5
  39. package/esm/types/service/CallApi.d.ts.map +1 -1
  40. package/esm/types/simple/Auth.d.ts +6 -1
  41. package/esm/types/simple/Auth.d.ts.map +1 -1
  42. package/esm/types/simple/Phone.d.ts +8 -8
  43. package/esm/types/simple/Phone.d.ts.map +1 -1
  44. package/esm/types/simple/index.d.ts +3 -1
  45. package/esm/types/simple/index.d.ts.map +1 -1
  46. package/esm/types/state-machine/softphone-state-machine.d.ts +1 -2
  47. package/esm/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  48. package/esm/types/state-machine/utils.d.ts +2 -2
  49. package/esm/types/state-machine/utils.d.ts.map +1 -1
  50. package/esm/types/utils/api-requester.d.ts.map +1 -1
  51. package/esm/types/utils/sdp.d.ts +3 -2
  52. package/esm/types/utils/sdp.d.ts.map +1 -1
  53. package/esm/types/utils/webrtc.d.ts +1 -0
  54. package/esm/types/utils/webrtc.d.ts.map +1 -1
  55. package/esm/types/voice/call.d.ts +30 -12
  56. package/esm/types/voice/call.d.ts.map +1 -1
  57. package/esm/types/voice/softphone.d.ts +25 -13
  58. package/esm/types/voice/softphone.d.ts.map +1 -1
  59. package/esm/types/web-rtc-client.d.ts +39 -38
  60. package/esm/types/web-rtc-client.d.ts.map +1 -1
  61. package/esm/utils/__tests__/api-requester.test.js +17 -0
  62. package/esm/utils/api-requester.js +9 -1
  63. package/esm/utils/sdp.js +22 -9
  64. package/esm/utils/webrtc.js +24 -4
  65. package/esm/voice/call.js +130 -38
  66. package/esm/voice/softphone.js +145 -35
  67. package/esm/web-rtc-client.js +61 -58
  68. package/lib/__tests__/__voice__/call.test.js +56 -1
  69. package/lib/__tests__/api-client.test.js +20 -1
  70. package/lib/api/auth.js +16 -2
  71. package/lib/checker/checks/webrtc.js +1 -1
  72. package/lib/domain/CallLog.js +2 -3
  73. package/lib/domain/Phone/CTIPhone.js +2 -2
  74. package/lib/domain/Phone/WebRTCPhone.js +63 -62
  75. package/lib/index.js +11 -3
  76. package/lib/service/CallApi.js +2 -2
  77. package/lib/simple/Auth.js +21 -15
  78. package/lib/simple/Phone.js +3 -2
  79. package/lib/simple/__tests__/Auth.test.js +11 -64
  80. package/lib/simple/index.js +2 -1
  81. package/lib/simple/room/Room.js +1 -1
  82. package/lib/simple/room/SipRoom.js +1 -1
  83. package/lib/state-machine/call-state-machine.js +2 -2
  84. package/lib/state-machine/softphone-state-machine.js +1 -2
  85. package/lib/state-machine/utils.js +8 -3
  86. package/lib/types/api/auth.d.ts +3 -0
  87. package/lib/types/api/auth.d.ts.map +1 -1
  88. package/lib/types/checker/checks/index.d.ts +1 -1
  89. package/lib/types/checker/checks/webrtc-transport.d.ts +2 -2
  90. package/lib/types/checker/checks/webrtc-transport.d.ts.map +1 -1
  91. package/lib/types/domain/CallLog.d.ts.map +1 -1
  92. package/lib/types/domain/CallSession.d.ts +3 -3
  93. package/lib/types/domain/CallSession.d.ts.map +1 -1
  94. package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
  95. package/lib/types/domain/Phone/WebRTCPhone.d.ts +22 -22
  96. package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  97. package/lib/types/domain/types.d.ts +0 -4
  98. package/lib/types/domain/types.d.ts.map +1 -1
  99. package/lib/types/index.d.ts +5 -1
  100. package/lib/types/index.d.ts.map +1 -1
  101. package/lib/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
  102. package/lib/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
  103. package/lib/types/service/CallApi.d.ts +5 -5
  104. package/lib/types/service/CallApi.d.ts.map +1 -1
  105. package/lib/types/simple/Auth.d.ts +6 -1
  106. package/lib/types/simple/Auth.d.ts.map +1 -1
  107. package/lib/types/simple/Phone.d.ts +8 -8
  108. package/lib/types/simple/Phone.d.ts.map +1 -1
  109. package/lib/types/simple/index.d.ts +3 -1
  110. package/lib/types/simple/index.d.ts.map +1 -1
  111. package/lib/types/state-machine/softphone-state-machine.d.ts +1 -2
  112. package/lib/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  113. package/lib/types/state-machine/utils.d.ts +2 -2
  114. package/lib/types/state-machine/utils.d.ts.map +1 -1
  115. package/lib/types/utils/api-requester.d.ts.map +1 -1
  116. package/lib/types/utils/sdp.d.ts +3 -2
  117. package/lib/types/utils/sdp.d.ts.map +1 -1
  118. package/lib/types/utils/webrtc.d.ts +1 -0
  119. package/lib/types/utils/webrtc.d.ts.map +1 -1
  120. package/lib/types/voice/call.d.ts +30 -12
  121. package/lib/types/voice/call.d.ts.map +1 -1
  122. package/lib/types/voice/softphone.d.ts +25 -13
  123. package/lib/types/voice/softphone.d.ts.map +1 -1
  124. package/lib/types/web-rtc-client.d.ts +39 -38
  125. package/lib/types/web-rtc-client.d.ts.map +1 -1
  126. package/lib/utils/__tests__/api-requester.test.js +17 -0
  127. package/lib/utils/api-requester.js +9 -1
  128. package/lib/utils/sdp.js +25 -10
  129. package/lib/utils/webrtc.js +25 -4
  130. package/lib/voice/call.js +131 -36
  131. package/lib/voice/softphone.js +150 -35
  132. package/lib/web-rtc-client.js +59 -57
  133. package/package.json +1 -1
  134. package/src/__tests__/__voice__/call.test.ts +63 -2
  135. package/src/__tests__/api-client.test.ts +22 -1
  136. package/src/api/auth.ts +30 -3
  137. package/src/checker/checks/webrtc-transport.ts +2 -2
  138. package/src/checker/checks/webrtc.ts +2 -2
  139. package/src/domain/CallLog.ts +2 -3
  140. package/src/domain/CallSession.ts +3 -3
  141. package/src/domain/Phone/CTIPhone.ts +3 -2
  142. package/src/domain/Phone/WebRTCPhone.ts +95 -93
  143. package/src/domain/types.ts +0 -5
  144. package/src/index.ts +6 -1
  145. package/src/lib/WazoSessionDescriptionHandler.ts +3 -3
  146. package/src/service/CallApi.ts +7 -7
  147. package/src/simple/Auth.ts +21 -16
  148. package/src/simple/Phone.ts +12 -11
  149. package/src/simple/__tests__/Auth.test.ts +9 -87
  150. package/src/simple/index.ts +2 -1
  151. package/src/simple/room/Room.ts +3 -3
  152. package/src/simple/room/SipRoom.ts +3 -3
  153. package/src/state-machine/call-state-machine.ts +2 -2
  154. package/src/state-machine/softphone-state-machine.ts +1 -2
  155. package/src/state-machine/utils.ts +12 -5
  156. package/src/utils/__tests__/api-requester.test.ts +20 -0
  157. package/src/utils/api-requester.ts +9 -1
  158. package/src/utils/sdp.ts +26 -11
  159. package/src/utils/webrtc.ts +27 -5
  160. package/src/voice/call.ts +169 -50
  161. package/src/voice/softphone.ts +180 -41
  162. package/src/web-rtc-client.ts +106 -99
@@ -51,6 +51,7 @@ const logger = IssueReporter_1.default ? IssueReporter_1.default.loggerFor('webr
51
51
  const statsLogger = IssueReporter_1.default ? IssueReporter_1.default.loggerFor('webrtc-stats') : console;
52
52
  // events
53
53
  const REGISTERED = 'registered';
54
+ const REGISTERING = 'registering';
54
55
  const UNREGISTERED = 'unregistered';
55
56
  const REGISTRATION_FAILED = 'registrationFailed';
56
57
  const INVITE = 'invite';
@@ -68,7 +69,7 @@ const ON_ERROR = 'onError';
68
69
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
69
70
  const ON_NETWORK_STATS = 'onNetworkStats';
70
71
  const ON_DISCONNECTED = 'onDisconnected';
71
- exports.events = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
72
+ exports.events = [REGISTERED, REGISTERING, UNREGISTERED, REGISTRATION_FAILED, INVITE];
72
73
  exports.transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
73
74
  class CanceledCallError extends Error {
74
75
  }
@@ -85,7 +86,9 @@ class WebRTCClient extends Emitter_1.default {
85
86
  this.skipRegister = config.skipRegister;
86
87
  this._buildConfig(config, session).then((newConfig) => {
87
88
  this.config = newConfig;
88
- this.userAgent = this.createUserAgent(uaConfigOverrides);
89
+ if (!this.userAgent) {
90
+ this.userAgent = this.createUserAgent(uaConfigOverrides);
91
+ }
89
92
  });
90
93
  this.audioOutputDeviceId = config.audioDeviceOutput;
91
94
  this.audioOutputVolume = config.audioOutputVolume || 1;
@@ -110,6 +113,7 @@ class WebRTCClient extends Emitter_1.default {
110
113
  this.heartbeat.setOnHeartbeatTimeout(this._onHeartbeatTimeout.bind(this));
111
114
  // sugar
112
115
  this.REGISTERED = REGISTERED;
116
+ this.REGISTERING = REGISTERING;
113
117
  this.UNREGISTERED = UNREGISTERED;
114
118
  this.REGISTRATION_FAILED = REGISTRATION_FAILED;
115
119
  this.INVITE = INVITE;
@@ -151,7 +155,7 @@ class WebRTCClient extends Emitter_1.default {
151
155
  logger.info('sdk webrtc on invite', {
152
156
  method: 'delegate.onInvite',
153
157
  clientId: this.clientId,
154
- id: invitation.id,
158
+ id: (0, sdp_1.getSipCallId)(invitation),
155
159
  remoteURI: invitation.remoteURI,
156
160
  });
157
161
  this._setupSession(invitation);
@@ -218,7 +222,7 @@ class WebRTCClient extends Emitter_1.default {
218
222
  // @ts-ignore: private
219
223
  this.registerer.waitingToggle(false);
220
224
  }
221
- this.eventEmitter.emit(UNREGISTERED);
225
+ this.eventEmitter.emit(UNREGISTERED, error);
222
226
  }
223
227
  });
224
228
  }
@@ -242,6 +246,7 @@ class WebRTCClient extends Emitter_1.default {
242
246
  return Promise.resolve();
243
247
  }
244
248
  logger.info('sdk webrtc registering...', logInfo);
249
+ this.eventEmitter.emit(REGISTERING);
245
250
  if (!this.userAgent) {
246
251
  logger.info('sdk webrtc recreating User Agent');
247
252
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
@@ -425,7 +430,7 @@ class WebRTCClient extends Emitter_1.default {
425
430
  this._setupSession(session);
426
431
  }
427
432
  if (conference) {
428
- this.conferences[(0, sdp_1.getSipSessionId)(session)] = true;
433
+ this.conferences[(0, sdp_1.getSipCallId)(session)] = true;
429
434
  }
430
435
  const inviteOptions = {
431
436
  requestDelegate: {
@@ -441,7 +446,7 @@ class WebRTCClient extends Emitter_1.default {
441
446
  },
442
447
  onReject: (response) => {
443
448
  logger.info('on call rejected', {
444
- id: session === null || session === void 0 ? void 0 : session.id,
449
+ id: (0, sdp_1.getSipCallId)(session),
445
450
  // @ts-ignore: fromTag does not exist
446
451
  fromTag: session === null || session === void 0 ? void 0 : session.fromTag,
447
452
  });
@@ -471,7 +476,7 @@ class WebRTCClient extends Emitter_1.default {
471
476
  answer(session, enableVideo) {
472
477
  logger.info('sdk webrtc answer call', {
473
478
  clientId: this.clientId,
474
- id: session.id,
479
+ id: (0, sdp_1.getSipCallId)(session),
475
480
  enableVideo,
476
481
  });
477
482
  if (!session || !session.accept) {
@@ -487,7 +492,7 @@ class WebRTCClient extends Emitter_1.default {
487
492
  if (session.isCanceled) {
488
493
  const message = 'accepted a canceled session (or was canceled during the accept phase).';
489
494
  logger.error(message, {
490
- id: session.id,
495
+ id: (0, sdp_1.getSipCallId)(session),
491
496
  });
492
497
  this.onCallEnded(session);
493
498
  throw new CanceledCallError(message);
@@ -495,7 +500,7 @@ class WebRTCClient extends Emitter_1.default {
495
500
  logger.info('sdk webrtc answer, accepted.');
496
501
  this._onAccepted(session);
497
502
  }).catch(e => {
498
- logger.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
503
+ logger.error(`answer call error for ${(0, sdp_1.getSipCallId)(session)}`, e);
499
504
  throw e;
500
505
  });
501
506
  }
@@ -506,7 +511,7 @@ class WebRTCClient extends Emitter_1.default {
506
511
  try {
507
512
  this._stopSendingStats(session);
508
513
  this._cleanupMedia(session);
509
- delete this.sipSessions[(0, sdp_1.getSipSessionId)(session)];
514
+ delete this.sipSessions[(0, sdp_1.getSipCallId)(session)];
510
515
  // Check if Invitation or Inviter (Invitation = incoming call)
511
516
  const isInviter = session instanceof api_1.Inviter;
512
517
  // @see github.com/onsip/SIP.js/blob/f11dfd584bc9788ccfc94e03034020672b738975/src/platform/web/simple-user/simple-user.ts#L1004
@@ -529,7 +534,7 @@ class WebRTCClient extends Emitter_1.default {
529
534
  }
530
535
  // Fetch and emit an event at `interval` with session network stats
531
536
  startNetworkMonitoring(session, interval = 1000) {
532
- const sessionId = (0, sdp_1.getSipSessionId)(session);
537
+ const sessionId = (0, sdp_1.getSipCallId)(session);
533
538
  logger.info('starting network inspection', {
534
539
  id: sessionId,
535
540
  clientId: this.clientId,
@@ -538,7 +543,7 @@ class WebRTCClient extends Emitter_1.default {
538
543
  this.networkMonitoringInterval[sessionId] = setInterval(() => this._fetchNetworkStats(sessionId), interval);
539
544
  }
540
545
  stopNetworkMonitoring(session) {
541
- const sessionId = (0, sdp_1.getSipSessionId)(session);
546
+ const sessionId = (0, sdp_1.getSipCallId)(session);
542
547
  const exists = (sessionId in this.networkMonitoringInterval);
543
548
  logger.info('stopping network inspection', {
544
549
  clientId: this.clientId,
@@ -555,7 +560,7 @@ class WebRTCClient extends Emitter_1.default {
555
560
  return __awaiter(this, void 0, void 0, function* () {
556
561
  logger.info('sdk webrtc reject call', {
557
562
  clientId: this.clientId,
558
- id: session.id,
563
+ id: (0, sdp_1.getSipCallId)(session),
559
564
  });
560
565
  try {
561
566
  if (session instanceof api_1.Invitation) {
@@ -612,13 +617,13 @@ class WebRTCClient extends Emitter_1.default {
612
617
  }
613
618
  mute(session) {
614
619
  logger.info('sdk webrtc mute', {
615
- id: session.id,
620
+ id: (0, sdp_1.getSipCallId)(session),
616
621
  });
617
622
  (0, webrtc_1.toggleAudio)(session, true);
618
623
  }
619
624
  unmute(session) {
620
625
  logger.info('sdk webrtc unmute', {
621
- id: session.id,
626
+ id: (0, sdp_1.getSipCallId)(session),
622
627
  });
623
628
  (0, webrtc_1.toggleAudio)(session, false);
624
629
  }
@@ -655,18 +660,18 @@ class WebRTCClient extends Emitter_1.default {
655
660
  }
656
661
  toggleCameraOn(session) {
657
662
  logger.info('sdk webrtc toggle camera on', {
658
- id: session.id,
663
+ id: (0, sdp_1.getSipCallId)(session),
659
664
  });
660
665
  (0, webrtc_1.toggleVideo)(session, false);
661
666
  }
662
667
  toggleCameraOff(session) {
663
668
  logger.info('sdk webrtc toggle camera off', {
664
- id: session.id,
669
+ id: (0, sdp_1.getSipCallId)(session),
665
670
  });
666
671
  (0, webrtc_1.toggleVideo)(session, true);
667
672
  }
668
673
  hold(session, isConference = false, hadVideo = false) {
669
- const sessionId = (0, sdp_1.getSipSessionId)(session);
674
+ const sessionId = (0, sdp_1.getSipCallId)(session);
670
675
  const hasVideo = hadVideo || this.hasLocalVideo(sessionId);
671
676
  logger.info('sdk webrtc hold', {
672
677
  sessionId,
@@ -714,7 +719,7 @@ class WebRTCClient extends Emitter_1.default {
714
719
  });
715
720
  }
716
721
  unhold(session, isConference = false) {
717
- const sessionId = (0, sdp_1.getSipSessionId)(session);
722
+ const sessionId = (0, sdp_1.getSipCallId)(session);
718
723
  const hasVideo = sessionId in this.heldSessions && this.heldSessions[sessionId].hasVideo;
719
724
  logger.info('sdk webrtc unhold', {
720
725
  sessionId,
@@ -729,7 +734,7 @@ class WebRTCClient extends Emitter_1.default {
729
734
  return Promise.resolve();
730
735
  }
731
736
  this.unmute(session);
732
- delete this.heldSessions[(0, sdp_1.getSipSessionId)(session)];
737
+ delete this.heldSessions[(0, sdp_1.getSipCallId)(session)];
733
738
  session.sessionDescriptionHandlerOptionsReInvite = {
734
739
  hold: false,
735
740
  conference: isConference,
@@ -754,7 +759,7 @@ class WebRTCClient extends Emitter_1.default {
754
759
  return this.heldSessions[sessionId];
755
760
  }
756
761
  isCallHeld(session) {
757
- return (0, sdp_1.getSipSessionId)(session) in this.heldSessions;
762
+ return (0, sdp_1.getSipCallId)(session) in this.heldSessions;
758
763
  }
759
764
  isVideoRemotelyHeld(sessionId) {
760
765
  return (0, webrtc_1.isVideoRemotelyHeld)(this.heldSessions[sessionId]);
@@ -764,7 +769,7 @@ class WebRTCClient extends Emitter_1.default {
764
769
  return false;
765
770
  }
766
771
  logger.info('Sending DTMF', {
767
- id: (0, sdp_1.getSipSessionId)(session),
772
+ id: (0, sdp_1.getSipCallId)(session),
768
773
  tone,
769
774
  });
770
775
  return session.sessionDescriptionHandler.sendDtmf(tone);
@@ -781,7 +786,7 @@ class WebRTCClient extends Emitter_1.default {
781
786
  transfer(session, target) {
782
787
  this.hold(session);
783
788
  logger.info('Transfering a session', {
784
- id: (0, sdp_1.getSipSessionId)(session),
789
+ id: (0, sdp_1.getSipCallId)(session),
785
790
  target,
786
791
  });
787
792
  const options = {
@@ -804,21 +809,21 @@ class WebRTCClient extends Emitter_1.default {
804
809
  atxfer(session) {
805
810
  this.hold(session);
806
811
  logger.info('webrtc transfer started', {
807
- id: (0, sdp_1.getSipSessionId)(session),
812
+ id: (0, sdp_1.getSipCallId)(session),
808
813
  });
809
814
  const result = {
810
815
  newSession: null,
811
816
  init: (target) => __awaiter(this, void 0, void 0, function* () {
812
817
  logger.info('webrtc transfer initialized', {
813
- id: (0, sdp_1.getSipSessionId)(session),
818
+ id: (0, sdp_1.getSipCallId)(session),
814
819
  target,
815
820
  });
816
821
  result.newSession = yield this.call(target);
817
822
  }),
818
823
  complete: () => {
819
824
  logger.info('webrtc transfer completed', {
820
- id: (0, sdp_1.getSipSessionId)(session),
821
- referId: (0, sdp_1.getSipSessionId)(result.newSession),
825
+ id: (0, sdp_1.getSipCallId)(session),
826
+ referId: (0, sdp_1.getSipCallId)(result.newSession),
822
827
  });
823
828
  session.refer(result.newSession);
824
829
  },
@@ -835,7 +840,7 @@ class WebRTCClient extends Emitter_1.default {
835
840
  return;
836
841
  }
837
842
  logger.info('send WebRTC message', {
838
- sipId: sipSession.id,
843
+ sipId: (0, sdp_1.getSipCallId)(sipSession),
839
844
  contentType,
840
845
  });
841
846
  try {
@@ -990,7 +995,7 @@ class WebRTCClient extends Emitter_1.default {
990
995
  }
991
996
  const sdh = session.sessionDescriptionHandler;
992
997
  const pc = sdh.peerConnection;
993
- const sessionId = (0, sdp_1.getSipSessionId)(session);
998
+ const sessionId = (0, sdp_1.getSipCallId)(session);
994
999
  const localStream = this.getLocalStream(sessionId);
995
1000
  logger.info('changing video input device', {
996
1001
  id,
@@ -1053,7 +1058,7 @@ class WebRTCClient extends Emitter_1.default {
1053
1058
  const desktop = newConstraints && newConstraints.desktop;
1054
1059
  logger.info('Sending reinvite', {
1055
1060
  clientId: this.clientId,
1056
- id: (0, sdp_1.getSipSessionId)(sipSession),
1061
+ id: (0, sdp_1.getSipCallId)(sipSession),
1057
1062
  newConstraints,
1058
1063
  conference,
1059
1064
  audioOnly,
@@ -1085,7 +1090,7 @@ class WebRTCClient extends Emitter_1.default {
1085
1090
  sipSession.incomingInviteRequest.message.body = response.message.body;
1086
1091
  }
1087
1092
  logger.info('on re-INVITE accepted', {
1088
- id: (0, sdp_1.getSipSessionId)(sipSession),
1093
+ id: (0, sdp_1.getSipCallId)(sipSession),
1089
1094
  wasMuted,
1090
1095
  shouldDoScreenSharing,
1091
1096
  });
@@ -1200,7 +1205,7 @@ class WebRTCClient extends Emitter_1.default {
1200
1205
  }
1201
1206
  onCallEnded(session) {
1202
1207
  this._cleanupMedia(session);
1203
- delete this.sipSessions[(0, sdp_1.getSipSessionId)(session)];
1208
+ delete this.sipSessions[(0, sdp_1.getSipCallId)(session)];
1204
1209
  this._stopSendingStats(session);
1205
1210
  this.stopNetworkMonitoring(session);
1206
1211
  }
@@ -1213,14 +1218,14 @@ class WebRTCClient extends Emitter_1.default {
1213
1218
  this.userAgent.attemptReconnection();
1214
1219
  }
1215
1220
  storeSipSession(session) {
1216
- const id = (0, sdp_1.getSipSessionId)(session);
1221
+ const id = (0, sdp_1.getSipCallId)(session);
1217
1222
  logger.info('storing sip session', { id, clientId: this.clientId });
1218
1223
  this.sipSessions[id] = session;
1219
1224
  }
1220
1225
  getSipSession(id) {
1221
- return id in this.sipSessions ? this.sipSessions[id.substring(0, sdp_1.SIP_ID_LENGTH)] : null;
1226
+ return id in this.sipSessions ? this.sipSessions[id] : null;
1222
1227
  }
1223
- getSipSessionIds() {
1228
+ getSipCallIds() {
1224
1229
  return Object.keys(this.sipSessions);
1225
1230
  }
1226
1231
  updateLocalStream(sipSessionId, newStream) {
@@ -1263,8 +1268,8 @@ class WebRTCClient extends Emitter_1.default {
1263
1268
  return audio;
1264
1269
  });
1265
1270
  }
1266
- _onTransportError() {
1267
- logger.error('on transport error');
1271
+ _onTransportError(reason) {
1272
+ logger.warn('on transport error', { reason });
1268
1273
  this.eventEmitter.emit(TRANSPORT_ERROR);
1269
1274
  this.attemptReconnection();
1270
1275
  }
@@ -1319,7 +1324,7 @@ class WebRTCClient extends Emitter_1.default {
1319
1324
  }
1320
1325
  }
1321
1326
  // We can invoke disconnect() with an error that can be catcher by `onDisconnect`, so we have to trigger it here.
1322
- this._onTransportError();
1327
+ this._onTransportError('heartbeat timeout');
1323
1328
  }
1324
1329
  });
1325
1330
  }
@@ -1377,7 +1382,7 @@ class WebRTCClient extends Emitter_1.default {
1377
1382
  }
1378
1383
  // Invitation and Inviter extends Session
1379
1384
  _setupSession(session) {
1380
- const sipSessionId = (0, sdp_1.getSipSessionId)(session);
1385
+ const sipSessionId = (0, sdp_1.getSipCallId)(session);
1381
1386
  // When receiving an Invitation, the delegate is not defined.
1382
1387
  if (!session.delegate) {
1383
1388
  session.delegate = {};
@@ -1441,19 +1446,16 @@ class WebRTCClient extends Emitter_1.default {
1441
1446
  _onProgress(session_1) {
1442
1447
  return __awaiter(this, arguments, void 0, function* (session, early = false) {
1443
1448
  yield this._setupMedias(session);
1444
- const sessionId = (0, sdp_1.getSipSessionId)(session).substr(0, 20);
1449
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1445
1450
  (0, webrtc_1.updateRemoteStream)(session);
1446
- logger.info('progress received', {
1447
- sessionId,
1448
- early,
1449
- });
1451
+ logger.info('progress received', { sessionId, early });
1450
1452
  this.eventEmitter.emit(early ? ON_EARLY_MEDIA : ON_PROGRESS, session);
1451
1453
  });
1452
1454
  }
1453
1455
  _onAccepted(session_1, sessionDialog_1) {
1454
1456
  return __awaiter(this, arguments, void 0, function* (session, sessionDialog, withEvent = true, initAllTracks = true) {
1455
1457
  logger.info('on call accepted', {
1456
- id: session.id,
1458
+ id: (0, sdp_1.getSipCallId)(session),
1457
1459
  clientId: this.clientId,
1458
1460
  remoteTag: session.remoteTag,
1459
1461
  });
@@ -1499,7 +1501,7 @@ class WebRTCClient extends Emitter_1.default {
1499
1501
  return;
1500
1502
  }
1501
1503
  // Safari hack, because you cannot call .play() from a non user action
1502
- const sessionId = (0, sdp_1.getSipSessionId)(session);
1504
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1503
1505
  const isConference = this.isConference(sessionId);
1504
1506
  if (sessionId in this.audioElements) {
1505
1507
  logger.info('html element already exists for session', {
@@ -1545,7 +1547,7 @@ class WebRTCClient extends Emitter_1.default {
1545
1547
  });
1546
1548
  }
1547
1549
  _cleanupMedia(session) {
1548
- const sessionId = (0, sdp_1.getSipSessionId)(session);
1550
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1549
1551
  const localStream = this.getLocalStream(sessionId);
1550
1552
  if (localStream) {
1551
1553
  (0, webrtc_1.cleanupStream)(localStream);
@@ -1564,7 +1566,7 @@ class WebRTCClient extends Emitter_1.default {
1564
1566
  };
1565
1567
  if (this._hasAudio() && (0, webrtc_1.isWeb)()) {
1566
1568
  if (session) {
1567
- cleanLocalElement((0, sdp_1.getSipSessionId)(session));
1569
+ cleanLocalElement((0, sdp_1.getSipCallId)(session));
1568
1570
  }
1569
1571
  else {
1570
1572
  Object.keys(this.audioElements).forEach(id => cleanLocalElement(id));
@@ -1584,7 +1586,7 @@ class WebRTCClient extends Emitter_1.default {
1584
1586
  if (!pc) {
1585
1587
  return;
1586
1588
  }
1587
- const sessionId = (0, sdp_1.getSipSessionId)(session);
1589
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1588
1590
  (0, getstats_1.default)(pc, (result) => {
1589
1591
  const { results, internal, nomore } = result, stats = __rest(result, ["results", "internal", "nomore"]);
1590
1592
  this.statsIntervals[sessionId] = nomore;
@@ -1592,7 +1594,7 @@ class WebRTCClient extends Emitter_1.default {
1592
1594
  }, SEND_STATS_DELAY);
1593
1595
  }
1594
1596
  _stopSendingStats(session) {
1595
- const sessionId = (0, sdp_1.getSipSessionId)(session);
1597
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1596
1598
  logger.trace('Check for stopping stats', {
1597
1599
  sessionId,
1598
1600
  ids: Object.keys(this.statsIntervals),
@@ -1649,18 +1651,18 @@ class WebRTCClient extends Emitter_1.default {
1649
1651
  return __awaiter(this, arguments, void 0, function* (session, options = {}) {
1650
1652
  if (session.state === session_state_1.SessionState.Terminated || session.state === session_state_1.SessionState.Terminating) {
1651
1653
  const error = 'Trying to accept a terminated sipSession.';
1652
- logger.warn(error, { state: session.state, sessionId: session.id });
1654
+ logger.warn(error, { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1653
1655
  throw new Error(error);
1654
1656
  }
1655
1657
  if (session.state !== session_state_1.SessionState.Initial) {
1656
1658
  const error = 'Trying to accept a non Initial sipSession.';
1657
- logger.warn(error, { state: session.state, sessionId: session.id });
1659
+ logger.warn(error, { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1658
1660
  throw new Error(error);
1659
1661
  }
1660
1662
  // @ts-ignore: private
1661
1663
  if (!session.incomingInviteRequest.acceptable) {
1662
1664
  const error = 'Trying to reject a non `acceptable` session';
1663
- logger.warn(error, { state: session.state, sessionId: session.id });
1665
+ logger.warn(error, { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1664
1666
  throw new Error(error);
1665
1667
  }
1666
1668
  try {
@@ -1674,12 +1676,12 @@ class WebRTCClient extends Emitter_1.default {
1674
1676
  _reject(session_1) {
1675
1677
  return __awaiter(this, arguments, void 0, function* (session, options = {}) {
1676
1678
  if (session.state !== session_state_1.SessionState.Initial && session.state !== session_state_1.SessionState.Establishing) {
1677
- logger.warn('Trying to reject a session in a wrong state', { state: session.state, sessionId: session.id });
1679
+ logger.warn('Trying to reject a session in a wrong state', { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1678
1680
  return;
1679
1681
  }
1680
1682
  // @ts-ignore: private
1681
1683
  if (!session.incomingInviteRequest.rejectable) {
1682
- logger.warn('Trying to reject a non `rejectable` session', { state: session.state, sessionId: session.id });
1684
+ logger.warn('Trying to reject a non `rejectable` session', { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1683
1685
  return;
1684
1686
  }
1685
1687
  try {
@@ -1693,7 +1695,7 @@ class WebRTCClient extends Emitter_1.default {
1693
1695
  _cancel(session_1) {
1694
1696
  return __awaiter(this, arguments, void 0, function* (session, options = {}) {
1695
1697
  if (session.state !== session_state_1.SessionState.Initial && session.state !== session_state_1.SessionState.Establishing) {
1696
- logger.warn('Trying to cancel a session in a wrong state', { state: session.state, sessionId: session.id });
1698
+ logger.warn('Trying to cancel a session in a wrong state', { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1697
1699
  return;
1698
1700
  }
1699
1701
  try {
@@ -1707,7 +1709,7 @@ class WebRTCClient extends Emitter_1.default {
1707
1709
  _bye(session_1) {
1708
1710
  return __awaiter(this, arguments, void 0, function* (session, options = {}) {
1709
1711
  if (session.state !== session_state_1.SessionState.Established) {
1710
- logger.warn('Trying to end a session in a wrong state', { state: session.state, sessionId: session.id });
1712
+ logger.warn('Trying to end a session in a wrong state', { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1711
1713
  return null;
1712
1714
  }
1713
1715
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wazo/sdk",
3
- "version": "1.0.0-alpha.0",
3
+ "version": "1.0.0-alpha.10",
4
4
  "description": "Wazo's JavaScript Software Development Kit.",
5
5
  "main": "index.js",
6
6
  "types": "lib/types/index.d.ts",
@@ -3,8 +3,9 @@ import { Inviter, UserAgent, type URI } from 'sip.js';
3
3
 
4
4
  import softphone from '../../voice/softphone';
5
5
  import Call from '../../voice/call';
6
- import { Actions, States } from '../../state-machine/call-state-machine';
6
+ import { Actions, EstablishedStates, States } from '../../state-machine/call-state-machine';
7
7
  import { Actions as SoftphoneActions } from '../../state-machine/softphone-state-machine';
8
+ import ApiCall from '../../domain/Call';
8
9
 
9
10
  import InvalidStateTransition from '../../domain/InvalidStateTransition';
10
11
 
@@ -33,6 +34,7 @@ jest.mock('../../web-rtc-client', () => jest.fn().mockImplementation(() => ({
33
34
  answer: jest.fn(() => Promise.resolve()),
34
35
  hangup: jest.fn(() => Promise.resolve()),
35
36
  register: jest.fn(() => Promise.resolve()),
37
+ onCallEnded: jest.fn(() => Promise.resolve()),
36
38
  setOnHeartbeatTimeout: jest.fn(() => Promise.resolve()),
37
39
  setOnHeartbeatCallback: jest.fn(() => Promise.resolve()),
38
40
  on: jest.fn(),
@@ -42,11 +44,45 @@ const ua = new UserAgent(uaOptions);
42
44
  const sipCall = new Inviter(ua, UserAgent.makeURI('sip:1234@my.stack.io') as URI);
43
45
 
44
46
  softphone.connect();
47
+ // @ts-ignore: private method
45
48
  softphone._sendAction(SoftphoneActions.REGISTER_DONE);
46
49
 
47
50
  const invalidStateTransition = (state: string, action: string) => new InvalidStateTransition(`Invalid state transition from ${state} with action ${action}`, state, action);
48
51
 
49
52
  describe('Call', () => {
53
+ describe('parsing an API call', () => {
54
+ it('Should parse an API call and transform it to a Call instance', async () => {
55
+ const apiCall = new ApiCall({
56
+ id: '1234',
57
+ sipCallId: 'abcd',
58
+ isCaller: false,
59
+ isVideo: true,
60
+ recording: true,
61
+ callerName: '',
62
+ callerNumber: '',
63
+ calleeName: '',
64
+ calleeNumber: '0123423223',
65
+ dialedExtension: '',
66
+ lineId: null,
67
+ muted: true,
68
+ onHold: false,
69
+ startingTime: new Date(),
70
+ status: 'Up',
71
+ talkingToIds: [],
72
+ });
73
+ const call = Call.parseCall(apiCall);
74
+
75
+ expect(call.recording).toBeTruthy();
76
+ expect(call.id).toBe(apiCall.sipCallId);
77
+ expect(call.apiId).toBe(apiCall.id);
78
+ expect(call.number).toBe(apiCall.calleeNumber);
79
+ expect(call.answerTime).toStrictEqual(apiCall.startingTime);
80
+ expect(call.isMuted()).toBeTruthy();
81
+ expect(call.state).toStrictEqual({ [States.ESTABLISHED]: EstablishedStates.MUTED });
82
+ expect(call.isEstablished()).toBeTruthy();
83
+ });
84
+ });
85
+
50
86
  describe('accept', () => {
51
87
  it('Should throw an error when accepting a not ringing call', async () => {
52
88
  const call = new Call(sipCall, softphone);
@@ -54,16 +90,24 @@ describe('Call', () => {
54
90
  await expect(call.accept()).rejects.toThrowError(invalidStateTransition(States.IDLE, Actions.ACCEPT));
55
91
  });
56
92
 
57
- it.only('Should throw an error when the softphone is not registered', async () => {
93
+ it('Should throw an error when the softphone is not registered', async () => {
58
94
  const call = new Call(sipCall, softphone);
95
+ // @ts-ignore: private method
59
96
  call._sendAction(Actions.INCOMING_CALL);
97
+ // @ts-ignore: private method
60
98
  softphone._sendAction(SoftphoneActions.TRANSPORT_CLOSED);
61
99
 
62
100
  await expect(call.accept()).rejects.toThrowError(invalidStateTransition(States.RINGING, Actions.ACCEPT));
101
+
102
+ // Revert softphone state
103
+ softphone.connect();
104
+ // @ts-ignore: private method
105
+ softphone._sendAction(SoftphoneActions.REGISTER_DONE);
63
106
  });
64
107
 
65
108
  it('Should not throw an error when accepting a not ringing call', async () => {
66
109
  const call = new Call(sipCall, softphone);
110
+ // @ts-ignore: private method
67
111
  call._sendAction(Actions.INCOMING_CALL);
68
112
 
69
113
  await call.accept();
@@ -80,11 +124,28 @@ describe('Call', () => {
80
124
 
81
125
  it('Should not throw an error when terminating an established call', async () => {
82
126
  const call = new Call(sipCall, softphone);
127
+ // @ts-ignore: private method
83
128
  call._sendAction(Actions.MAKE_CALL);
129
+ // @ts-ignore: private method
84
130
  call._sendAction(Actions.REMOTLY_ACCEPTED);
85
131
 
86
132
  await call.hangup();
87
133
  expect(softphone.client.hangup).toHaveBeenCalled();
88
134
  });
89
135
  });
136
+
137
+ describe('state propagation', () => {
138
+ it('Should update the call state in events', (done) => {
139
+ const call = new Call(sipCall, softphone);
140
+ // @ts-ignore: private method
141
+ call._sendAction(Actions.MAKE_CALL);
142
+
143
+ call.on('remotelyAccepted', () => {
144
+ expect(call.state).toStrictEqual({ [States.ESTABLISHED]: EstablishedStates.ONGOING });
145
+ done();
146
+ });
147
+
148
+ call.onAccepted();
149
+ });
150
+ });
90
151
  });
@@ -131,7 +131,6 @@ describe('With correct API results', () => {
131
131
  body: JSON.stringify({ saml_session_id: samlSessionId }),
132
132
  signal: expect.any(Object),
133
133
  headers: {
134
- 'X-Auth-Token': token,
135
134
  'Content-Type': 'application/json',
136
135
  Accept: 'application/json',
137
136
  },
@@ -140,6 +139,28 @@ describe('With correct API results', () => {
140
139
  });
141
140
  });
142
141
 
142
+ describe('samlLogIn mobile test', () => {
143
+ it('should retrieve user token', async () => {
144
+ Wazo.Auth.mobile = true;
145
+ const samlSessionId = 'a1b2C3d4';
146
+ const result = await client.auth.samlLogIn(samlSessionId);
147
+
148
+ expect(result).toBeInstanceOf(Session);
149
+ expect(result?.token).toBe(1);
150
+ expect(global.fetch).toBeCalledWith(`https://${server}/api/auth/${authVersion}/token`, {
151
+ method: 'post',
152
+ body: JSON.stringify({ saml_session_id: samlSessionId }),
153
+ signal: expect.any(Object),
154
+ headers: {
155
+ 'Content-Type': 'application/json',
156
+ 'Wazo-Session-Type': 'mobile',
157
+ Accept: 'application/json',
158
+ },
159
+ agent: null,
160
+ });
161
+ });
162
+ });
163
+
143
164
  describe('logOut test', () => {
144
165
  it('should delete the specified token', async () => {
145
166
  const oldToken = 123;