@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
@@ -276,7 +276,13 @@ class IssueReporter {
276
276
  }
277
277
 
278
278
  _isLevelAbove(level1 , level2 ) {
279
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
279
+ const index1 = LOG_LEVELS.indexOf(level1);
280
+ const index2 = LOG_LEVELS.indexOf(level2);
281
+ if (index1 === -1 || index2 === -1) {
282
+ return false;
283
+ }
284
+
285
+ return index1 > index2;
280
286
  }
281
287
 
282
288
  _makeCategory(category ) {
@@ -405,6 +411,7 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
405
411
  const iceRestart = options.offerOptions ? options.offerOptions.iceRestart : false;
406
412
 
407
413
  const isConference = options ? !!options.conference : false;
414
+ const audioOnly = options ? !!options.audioOnly : false;
408
415
 
409
416
  // We should wait for ice when iceRestart (reinvite) or for the first invite
410
417
  // We shouldn't wait for ice when holding or resuming the call
@@ -431,16 +438,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
431
438
  };
432
439
 
433
440
  return this.getLocalMediaStream(options)
434
- .then(() => this.updateDirection(options, isConference))
441
+ .then(() => this.updateDirection(options, isConference, audioOnly))
435
442
  .then(() => this.createDataChannel(options))
436
443
  .then(() => {
437
- if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options)) {
444
+ if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
438
445
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
439
446
  this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
440
447
  }
441
448
  })
442
449
  .then(() => this.createLocalOfferOrAnswer(options))
443
- .then((sessionDescription) => this.setLocalSessionDescription(sessionDescription))
450
+ .then(sessionDescription => this.setLocalSessionDescription(sessionDescription))
444
451
  .then(() => this.waitForIceGatheringComplete(iceRestart, iceTimeout))
445
452
  .then(() => this.getLocalSessionDescription())
446
453
  .then(description => {
@@ -563,7 +570,8 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
563
570
  }
564
571
 
565
572
  // Overridden to send `inactive` in conference
566
- updateDirection(options , isConference = false) {
573
+ updateDirection(options , isConference = false,
574
+ audioOnly = false) {
567
575
  if (this._peerConnection === undefined) {
568
576
  return Promise.reject(new Error('Peer connection closed.'));
569
577
  }
@@ -578,14 +586,17 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
578
586
  // if we are stable, assume we are creating a local offer
579
587
  this.logger.debug('SessionDescriptionHandler.updateDirection - setting offer direction');
580
588
  // determine the direction to offer given the current direction and hold state
581
- const directionToOffer = (currentDirection ) => {
589
+ const directionToOffer = (currentDirection , transceiver /* RTCRtpTransceiver */) => {
582
590
  if (isConference) {
591
+ if (audioOnly && transceiver.receiver.track && transceiver.receiver.track.kind === 'video') {
592
+ return 'sendonly';
593
+ }
583
594
  return options && options.hold ? 'sendonly' : 'sendrecv';
584
595
  }
585
596
 
586
597
  switch (currentDirection) {
587
598
  case 'inactive':
588
- return options && options.hold ? 'inactive' : 'recvonly';
599
+ return options && options.hold ? 'inactive' : (isConference && !audioOnly ? 'sendrecv' : 'recvonly');
589
600
  case 'recvonly':
590
601
  return options && options.hold ? 'inactive' : 'recvonly';
591
602
  case 'sendonly':
@@ -601,7 +612,7 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
601
612
  // set the transceiver direction to the offer direction
602
613
  this._peerConnection.getTransceivers().forEach((transceiver) => {
603
614
  if (transceiver.direction /* guarding, but should always be true */) {
604
- const offerDirection = directionToOffer(transceiver.direction);
615
+ const offerDirection = directionToOffer(transceiver.direction, transceiver);
605
616
  if (transceiver.direction !== offerDirection) {
606
617
  // eslint-disable-next-line no-param-reassign
607
618
  transceiver.direction = offerDirection;
@@ -660,6 +671,13 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
660
671
  // set the transceiver direction to the answer direction
661
672
  this._peerConnection.getTransceivers().forEach((transceiver) => {
662
673
  if (transceiver.direction /* guarding, but should always be true */) {
674
+ const { receiver } = transceiver;
675
+ if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
676
+ // eslint-disable-next-line no-param-reassign
677
+ transceiver.direction = 'inactive';
678
+ return;
679
+ }
680
+
663
681
  if (transceiver.direction !== 'stopped' && transceiver.direction !== answerDirection) {
664
682
  // eslint-disable-next-line no-param-reassign
665
683
  transceiver.direction = answerDirection;
@@ -698,8 +716,8 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
698
716
  }
699
717
  const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
700
718
 
701
- // Do not reuse sender tracks in SFU
702
- if (sender && !sfu) {
719
+ // Do not reuse sender video tracks in SFU
720
+ if (sender && (!sfu || newTrack.kind === 'audio')) {
703
721
  trackUpdates.push(
704
722
  new Promise((resolve) => {
705
723
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -1173,7 +1173,7 @@ class Contact {
1173
1173
 
1174
1174
  return new Contact({
1175
1175
  sourceId: single.id || '',
1176
- name: single.displayName,
1176
+ name: single.displayName || '',
1177
1177
  number: numbers.length ? numbers[0].number : '',
1178
1178
  numbers,
1179
1179
  emails,
@@ -1204,7 +1204,7 @@ class Contact {
1204
1204
 
1205
1205
  return new Contact({
1206
1206
  sourceId: single.id || '',
1207
- name: single.name,
1207
+ name: single.name || '',
1208
1208
  number: numbers.length ? numbers[0].number : '',
1209
1209
  numbers,
1210
1210
  emails,
@@ -1305,7 +1305,7 @@ class Contact {
1305
1305
  } = {}) {
1306
1306
  this.id = id;
1307
1307
  this.uuid = uuid;
1308
- this.name = name;
1308
+ this.name = name || '';
1309
1309
  this.number = number;
1310
1310
  this.numbers = numbers;
1311
1311
  this.email = email;
@@ -1678,17 +1678,66 @@ class Session {
1678
1678
 
1679
1679
  //
1680
1680
 
1681
+
1682
+
1683
+
1684
+
1685
+
1686
+
1687
+
1688
+
1689
+
1690
+
1691
+
1692
+
1693
+
1694
+
1695
+
1696
+
1697
+ class Recording {
1698
+
1699
+
1700
+
1701
+
1702
+
1703
+
1704
+ static parseMany(recordings ) {
1705
+ return recordings.map(item => Recording.parse(item));
1706
+ }
1707
+
1708
+ static parse(plain ) {
1709
+ return new Recording({
1710
+ deleted: plain.deleted,
1711
+ fileName: plain.filename,
1712
+ end: plain.end_time ? moment(plain.end_time).toDate() : null,
1713
+ start: moment(plain.start_time).toDate(),
1714
+ uuid: plain.uuid,
1715
+ });
1716
+ }
1717
+
1718
+ constructor({ deleted, end, fileName, start, uuid } ) {
1719
+ this.deleted = deleted;
1720
+ this.end = end;
1721
+ this.fileName = fileName;
1722
+ this.start = start;
1723
+ this.uuid = uuid;
1724
+ }
1725
+ }
1726
+
1727
+ //
1728
+
1681
1729
 
1682
-
1730
+
1683
1731
 
1684
1732
 
1685
1733
 
1686
1734
 
1687
1735
 
1688
-
1736
+
1689
1737
 
1690
1738
 
1691
1739
 
1740
+
1692
1741
 
1693
1742
 
1694
1743
 
@@ -1701,7 +1750,7 @@ class Session {
1701
1750
 
1702
1751
 
1703
1752
 
1704
-
1753
+
1705
1754
 
1706
1755
 
1707
1756
 
@@ -1716,13 +1765,14 @@ class Session {
1716
1765
 
1717
1766
 
1718
1767
 
1719
-
1768
+
1769
+
1720
1770
 
1721
1771
 
1722
1772
  class CallLog {
1723
1773
 
1724
1774
 
1725
-
1775
+
1726
1776
 
1727
1777
 
1728
1778
 
@@ -1739,7 +1789,7 @@ class CallLog {
1739
1789
 
1740
1790
 
1741
1791
 
1742
-
1792
+
1743
1793
 
1744
1794
  static merge(current , toMerge ) {
1745
1795
  const onlyUnique = (value, index, self) => self.indexOf(value) === index;
@@ -1756,7 +1806,7 @@ class CallLog {
1756
1806
 
1757
1807
  static parse(plain ) {
1758
1808
  return new CallLog({
1759
- answer: moment(plain.answer).toDate(),
1809
+ answer: plain.answer ? moment(plain.answer).toDate() : null,
1760
1810
  answered: plain.answered,
1761
1811
  callDirection: plain.call_direction,
1762
1812
  destination: {
@@ -1770,13 +1820,14 @@ class CallLog {
1770
1820
  id: plain.id,
1771
1821
  duration: (plain.duration || 0) * 1000, // duration is in seconds
1772
1822
  start: moment(plain.start).toDate(),
1773
- end: moment(plain.end).toDate(),
1823
+ end: plain.end ? moment(plain.end).toDate() : null,
1824
+ recordings: Recording.parseMany(plain.recordings),
1774
1825
  });
1775
1826
  }
1776
1827
 
1777
1828
  static parseNew(plain , session ) {
1778
1829
  return new CallLog({
1779
- answer: moment(plain.answer).toDate(),
1830
+ answer: plain.answer ? moment(plain.answer).toDate() : null,
1780
1831
  answered: plain.answered,
1781
1832
  callDirection: plain.call_direction,
1782
1833
  destination: {
@@ -1790,7 +1841,8 @@ class CallLog {
1790
1841
  id: plain.id,
1791
1842
  duration: (plain.duration || 0) * 1000, // duration is in seconds
1792
1843
  start: moment(plain.start).toDate(),
1793
- end: moment(plain.end).toDate(),
1844
+ end: plain.end ? moment(plain.end).toDate() : null,
1845
+ recordings: Recording.parseMany(plain.recordings),
1794
1846
  // @TODO: FIXME add verification declined vs missed call
1795
1847
  newMissedCall: session
1796
1848
  && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
@@ -2266,7 +2318,13 @@ class IssueReporter {
2266
2318
  }
2267
2319
 
2268
2320
  _isLevelAbove(level1 , level2 ) {
2269
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
2321
+ const index1 = LOG_LEVELS.indexOf(level1);
2322
+ const index2 = LOG_LEVELS.indexOf(level2);
2323
+ if (index1 === -1 || index2 === -1) {
2324
+ return false;
2325
+ }
2326
+
2327
+ return index1 > index2;
2270
2328
  }
2271
2329
 
2272
2330
  _makeCategory(category ) {
@@ -2324,6 +2382,7 @@ class ApiRequester {
2324
2382
 
2325
2383
 
2326
2384
 
2385
+
2327
2386
 
2328
2387
 
2329
2388
 
@@ -2363,6 +2422,8 @@ class ApiRequester {
2363
2422
  this.token = token;
2364
2423
  }
2365
2424
 
2425
+ this.shouldLogErrors = true;
2426
+
2366
2427
  methods.forEach(method => {
2367
2428
  // $FlowFixMe
2368
2429
  ApiRequester.prototype[method] = function sugar(...args) {
@@ -2386,6 +2447,14 @@ class ApiRequester {
2386
2447
  this.fetchOptions = options;
2387
2448
  }
2388
2449
 
2450
+ disableErrorLogging() {
2451
+ this.shouldLogErrors = false;
2452
+ }
2453
+
2454
+ enableErrorLogging() {
2455
+ this.shouldLogErrors = true;
2456
+ }
2457
+
2389
2458
  async call(
2390
2459
  path ,
2391
2460
  method = 'get',
@@ -2446,7 +2515,9 @@ class ApiRequester {
2446
2515
  ? exceptionClass.fromText(err, response.status)
2447
2516
  : exceptionClass.fromResponse(err, response.status);
2448
2517
 
2449
- logger$1.error('API error', error);
2518
+ if (this.shouldLogErrors) {
2519
+ logger$1.error('API error', error);
2520
+ }
2450
2521
 
2451
2522
  throw error;
2452
2523
  });
@@ -2454,7 +2525,9 @@ class ApiRequester {
2454
2525
 
2455
2526
  return newParse(response, isJson);
2456
2527
  }).catch(error => {
2457
- logger$1.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
2528
+ if (this.shouldLogErrors) {
2529
+ logger$1.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
2530
+ }
2458
2531
 
2459
2532
  throw error;
2460
2533
  });
@@ -4321,6 +4394,10 @@ class ApiClient {
4321
4394
  this.fetchOptions = fetchOptions;
4322
4395
  this.client.setFetchOptions(fetchOptions);
4323
4396
  }
4397
+
4398
+ disableErrorLogging() {
4399
+ this.client.disableErrorLogging();
4400
+ }
4324
4401
  }
4325
4402
 
4326
4403
  /* eslint-disable dot-notation */
@@ -272,7 +272,13 @@ class IssueReporter {
272
272
  }
273
273
 
274
274
  _isLevelAbove(level1 , level2 ) {
275
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
275
+ const index1 = LOG_LEVELS.indexOf(level1);
276
+ const index2 = LOG_LEVELS.indexOf(level2);
277
+ if (index1 === -1 || index2 === -1) {
278
+ return false;
279
+ }
280
+
281
+ return index1 > index2;
276
282
  }
277
283
 
278
284
  _makeCategory(category ) {
@@ -272,7 +272,13 @@ class IssueReporter {
272
272
  }
273
273
 
274
274
  _isLevelAbove(level1 , level2 ) {
275
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
275
+ const index1 = LOG_LEVELS.indexOf(level1);
276
+ const index2 = LOG_LEVELS.indexOf(level2);
277
+ if (index1 === -1 || index2 === -1) {
278
+ return false;
279
+ }
280
+
281
+ return index1 > index2;
276
282
  }
277
283
 
278
284
  _makeCategory(category ) {
@@ -286,11 +292,22 @@ var IssueReporter$1 = new IssueReporter();
286
292
 
287
293
  jest.mock('../../utils/api-requester');
288
294
 
289
- IssueReporter$1.enable();
295
+ let oldLog;
296
+ let oldError;
290
297
 
291
298
  class MyError extends Error {}
292
299
 
293
300
  describe('IssueReporter', () => {
301
+ beforeAll(() => {
302
+ oldLog = console.log;
303
+ oldError = console.error;
304
+
305
+ console.log = () => {};
306
+ console.error = () => {};
307
+
308
+ IssueReporter$1.enable();
309
+ });
310
+
294
311
  beforeEach(() => {
295
312
  jest.resetAllMocks();
296
313
 
@@ -299,12 +316,19 @@ describe('IssueReporter', () => {
299
316
  }));
300
317
  });
301
318
 
319
+ afterAll(() => {
320
+ console.log = oldLog;
321
+ console.error = oldError;
322
+ });
323
+
302
324
  it('should compute level order', () => {
303
325
  expect(IssueReporter$1._isLevelAbove('info', 'trace')).toBeTruthy();
304
326
  expect(IssueReporter$1._isLevelAbove('trace', 'warn')).toBeFalsy();
305
327
  expect(IssueReporter$1._isLevelAbove('error', 'warn')).toBeTruthy();
306
328
  expect(IssueReporter$1._isLevelAbove('info', 'warn')).toBeFalsy();
307
329
  expect(IssueReporter$1._isLevelAbove('trace', 'trace')).toBeFalsy();
330
+ expect(IssueReporter$1._isLevelAbove('trace', 'something')).toBeFalsy();
331
+ expect(IssueReporter$1._isLevelAbove('something', 'trace')).toBeFalsy();
308
332
  });
309
333
 
310
334
  it('should send if verbosity is higher than required', () => {
@@ -309,7 +309,13 @@ class IssueReporter {
309
309
  }
310
310
 
311
311
  _isLevelAbove(level1 , level2 ) {
312
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
312
+ const index1 = LOG_LEVELS.indexOf(level1);
313
+ const index2 = LOG_LEVELS.indexOf(level2);
314
+ if (index1 === -1 || index2 === -1) {
315
+ return false;
316
+ }
317
+
318
+ return index1 > index2;
313
319
  }
314
320
 
315
321
  _makeCategory(category ) {
@@ -367,6 +373,7 @@ class ApiRequester {
367
373
 
368
374
 
369
375
 
376
+
370
377
 
371
378
 
372
379
 
@@ -406,6 +413,8 @@ class ApiRequester {
406
413
  this.token = token;
407
414
  }
408
415
 
416
+ this.shouldLogErrors = true;
417
+
409
418
  methods.forEach(method => {
410
419
  // $FlowFixMe
411
420
  ApiRequester.prototype[method] = function sugar(...args) {
@@ -429,6 +438,14 @@ class ApiRequester {
429
438
  this.fetchOptions = options;
430
439
  }
431
440
 
441
+ disableErrorLogging() {
442
+ this.shouldLogErrors = false;
443
+ }
444
+
445
+ enableErrorLogging() {
446
+ this.shouldLogErrors = true;
447
+ }
448
+
432
449
  async call(
433
450
  path ,
434
451
  method = 'get',
@@ -489,7 +506,9 @@ class ApiRequester {
489
506
  ? exceptionClass.fromText(err, response.status)
490
507
  : exceptionClass.fromResponse(err, response.status);
491
508
 
492
- logger$1.error('API error', error);
509
+ if (this.shouldLogErrors) {
510
+ logger$1.error('API error', error);
511
+ }
493
512
 
494
513
  throw error;
495
514
  });
@@ -497,7 +516,9 @@ class ApiRequester {
497
516
 
498
517
  return newParse(response, isJson);
499
518
  }).catch(error => {
500
- logger$1.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
519
+ if (this.shouldLogErrors) {
520
+ logger$1.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
521
+ }
501
522
 
502
523
  throw error;
503
524
  });
@@ -1547,7 +1568,7 @@ class Contact {
1547
1568
 
1548
1569
  return new Contact({
1549
1570
  sourceId: single.id || '',
1550
- name: single.displayName,
1571
+ name: single.displayName || '',
1551
1572
  number: numbers.length ? numbers[0].number : '',
1552
1573
  numbers,
1553
1574
  emails,
@@ -1578,7 +1599,7 @@ class Contact {
1578
1599
 
1579
1600
  return new Contact({
1580
1601
  sourceId: single.id || '',
1581
- name: single.name,
1602
+ name: single.name || '',
1582
1603
  number: numbers.length ? numbers[0].number : '',
1583
1604
  numbers,
1584
1605
  emails,
@@ -1679,7 +1700,7 @@ class Contact {
1679
1700
  } = {}) {
1680
1701
  this.id = id;
1681
1702
  this.uuid = uuid;
1682
- this.name = name;
1703
+ this.name = name || '';
1683
1704
  this.number = number;
1684
1705
  this.numbers = numbers;
1685
1706
  this.email = email;
@@ -2988,17 +3009,66 @@ var updateFrom = (instance , from ) => {
2988
3009
 
2989
3010
  //
2990
3011
 
3012
+
3013
+
3014
+
3015
+
3016
+
3017
+
3018
+
3019
+
3020
+
3021
+
3022
+
3023
+
3024
+
3025
+
3026
+
3027
+
3028
+ class Recording {
3029
+
3030
+
3031
+
3032
+
3033
+
3034
+
3035
+ static parseMany(recordings ) {
3036
+ return recordings.map(item => Recording.parse(item));
3037
+ }
3038
+
3039
+ static parse(plain ) {
3040
+ return new Recording({
3041
+ deleted: plain.deleted,
3042
+ fileName: plain.filename,
3043
+ end: plain.end_time ? moment(plain.end_time).toDate() : null,
3044
+ start: moment(plain.start_time).toDate(),
3045
+ uuid: plain.uuid,
3046
+ });
3047
+ }
3048
+
3049
+ constructor({ deleted, end, fileName, start, uuid } ) {
3050
+ this.deleted = deleted;
3051
+ this.end = end;
3052
+ this.fileName = fileName;
3053
+ this.start = start;
3054
+ this.uuid = uuid;
3055
+ }
3056
+ }
3057
+
3058
+ //
3059
+
2991
3060
 
2992
-
3061
+
2993
3062
 
2994
3063
 
2995
3064
 
2996
3065
 
2997
3066
 
2998
-
3067
+
2999
3068
 
3000
3069
 
3001
3070
 
3071
+
3002
3072
 
3003
3073
 
3004
3074
 
@@ -3011,7 +3081,7 @@ var updateFrom = (instance , from ) => {
3011
3081
 
3012
3082
 
3013
3083
 
3014
-
3084
+
3015
3085
 
3016
3086
 
3017
3087
 
@@ -3026,13 +3096,14 @@ var updateFrom = (instance , from ) => {
3026
3096
 
3027
3097
 
3028
3098
 
3029
-
3099
+
3100
+
3030
3101
 
3031
3102
 
3032
3103
  class CallLog {
3033
3104
 
3034
3105
 
3035
-
3106
+
3036
3107
 
3037
3108
 
3038
3109
 
@@ -3049,7 +3120,7 @@ class CallLog {
3049
3120
 
3050
3121
 
3051
3122
 
3052
-
3123
+
3053
3124
 
3054
3125
  static merge(current , toMerge ) {
3055
3126
  const onlyUnique = (value, index, self) => self.indexOf(value) === index;
@@ -3066,7 +3137,7 @@ class CallLog {
3066
3137
 
3067
3138
  static parse(plain ) {
3068
3139
  return new CallLog({
3069
- answer: moment(plain.answer).toDate(),
3140
+ answer: plain.answer ? moment(plain.answer).toDate() : null,
3070
3141
  answered: plain.answered,
3071
3142
  callDirection: plain.call_direction,
3072
3143
  destination: {
@@ -3080,13 +3151,14 @@ class CallLog {
3080
3151
  id: plain.id,
3081
3152
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3082
3153
  start: moment(plain.start).toDate(),
3083
- end: moment(plain.end).toDate(),
3154
+ end: plain.end ? moment(plain.end).toDate() : null,
3155
+ recordings: Recording.parseMany(plain.recordings),
3084
3156
  });
3085
3157
  }
3086
3158
 
3087
3159
  static parseNew(plain , session ) {
3088
3160
  return new CallLog({
3089
- answer: moment(plain.answer).toDate(),
3161
+ answer: plain.answer ? moment(plain.answer).toDate() : null,
3090
3162
  answered: plain.answered,
3091
3163
  callDirection: plain.call_direction,
3092
3164
  destination: {
@@ -3100,7 +3172,8 @@ class CallLog {
3100
3172
  id: plain.id,
3101
3173
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3102
3174
  start: moment(plain.start).toDate(),
3103
- end: moment(plain.end).toDate(),
3175
+ end: plain.end ? moment(plain.end).toDate() : null,
3176
+ recordings: Recording.parseMany(plain.recordings),
3104
3177
  // @TODO: FIXME add verification declined vs missed call
3105
3178
  newMissedCall: session
3106
3179
  && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
@@ -4321,6 +4394,10 @@ class ApiClient {
4321
4394
  this.fetchOptions = fetchOptions;
4322
4395
  this.client.setFetchOptions(fetchOptions);
4323
4396
  }
4397
+
4398
+ disableErrorLogging() {
4399
+ this.client.disableErrorLogging();
4400
+ }
4324
4401
  }
4325
4402
 
4326
4403
  /* eslint-disable dot-notation */