@wazo/sdk 1.0.0-alpha.6 → 1.0.0-alpha.8

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 (35) hide show
  1. package/dist/wazo-sdk.js +2 -2
  2. package/esm/state-machine/softphone-state-machine.js +1 -2
  3. package/esm/state-machine/utils.js +7 -2
  4. package/esm/types/state-machine/softphone-state-machine.d.ts +0 -1
  5. package/esm/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  6. package/esm/types/state-machine/utils.d.ts +1 -1
  7. package/esm/types/state-machine/utils.d.ts.map +1 -1
  8. package/esm/types/voice/call.d.ts +1 -0
  9. package/esm/types/voice/call.d.ts.map +1 -1
  10. package/esm/types/voice/softphone.d.ts.map +1 -1
  11. package/esm/types/web-rtc-client.d.ts +2 -1
  12. package/esm/types/web-rtc-client.d.ts.map +1 -1
  13. package/esm/voice/call.js +5 -0
  14. package/esm/voice/softphone.js +24 -6
  15. package/esm/web-rtc-client.js +8 -4
  16. package/lib/state-machine/softphone-state-machine.js +1 -2
  17. package/lib/state-machine/utils.js +7 -2
  18. package/lib/types/state-machine/softphone-state-machine.d.ts +0 -1
  19. package/lib/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  20. package/lib/types/state-machine/utils.d.ts +1 -1
  21. package/lib/types/state-machine/utils.d.ts.map +1 -1
  22. package/lib/types/voice/call.d.ts +1 -0
  23. package/lib/types/voice/call.d.ts.map +1 -1
  24. package/lib/types/voice/softphone.d.ts.map +1 -1
  25. package/lib/types/web-rtc-client.d.ts +2 -1
  26. package/lib/types/web-rtc-client.d.ts.map +1 -1
  27. package/lib/voice/call.js +5 -0
  28. package/lib/voice/softphone.js +25 -6
  29. package/lib/web-rtc-client.js +7 -4
  30. package/package.json +1 -1
  31. package/src/state-machine/softphone-state-machine.ts +1 -2
  32. package/src/state-machine/utils.ts +9 -2
  33. package/src/voice/call.ts +6 -0
  34. package/src/voice/softphone.ts +31 -7
  35. package/src/web-rtc-client.ts +10 -4
@@ -81,6 +81,7 @@ class Softphone extends events_1.EventEmitter {
81
81
  this.audioRingVolume = 1;
82
82
  const server = __1.default.Auth.getHost();
83
83
  const session = __1.default.Auth.getSession();
84
+ logger.info('softphone - connect', { server, session: !!session });
84
85
  if (!server || !session) {
85
86
  throw new Error('Please connect to the server using `Wazo.Auth.logIn` or `Wazo.Auth.authenticate` before using Room.connect().');
86
87
  }
@@ -101,6 +102,7 @@ class Softphone extends events_1.EventEmitter {
101
102
  return __awaiter(this, void 0, void 0, function* () {
102
103
  (0, utils_1.assertCan)(this.softphoneActor, softphone_state_machine_1.Actions.UNREGISTER);
103
104
  if (!this.client) {
105
+ logger.info('softphone - disconnect, not client to disconnect, bailing');
104
106
  return null;
105
107
  }
106
108
  // Terminate all calls
@@ -115,7 +117,8 @@ class Softphone extends events_1.EventEmitter {
115
117
  connectWithCredentials(server_1, sipLine_1, displayName_1) {
116
118
  return __awaiter(this, arguments, void 0, function* (server, sipLine, displayName, rawOptions = {}) {
117
119
  (0, utils_1.assertCan)(this.softphoneActor, softphone_state_machine_1.Actions.REGISTER);
118
- this.softphoneActor.send({ type: softphone_state_machine_1.Actions.REGISTER });
120
+ logger.info('softphone - connect with credentials', { server, username: sipLine.username, displayName, options: rawOptions });
121
+ this._sendAction(softphone_state_machine_1.Actions.REGISTER);
119
122
  const [host, port = 443] = server.split(':');
120
123
  let options = Object.assign({}, rawOptions);
121
124
  options.media = options.media || {
@@ -162,6 +165,7 @@ class Softphone extends events_1.EventEmitter {
162
165
  try {
163
166
  sipCall = this.client.call(options.params.To, options.withCamera, options.audioOnly, options.conference, options);
164
167
  const call = new call_1.default(sipCall, this);
168
+ call.onMakeCall();
165
169
  this.calls.push(call);
166
170
  this.emit(exports.EVENT_OUTGOING, call);
167
171
  return call;
@@ -231,7 +235,8 @@ class Softphone extends events_1.EventEmitter {
231
235
  this.calls.filter(call => !call.isHeld() && call.id === (exceptCall === null || exceptCall === void 0 ? void 0 : exceptCall.id)).forEach(call => call.hold());
232
236
  }
233
237
  startHeartbeat() {
234
- logger.info('softphone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
238
+ var _a;
239
+ logger.info('softphone - start heartbeat', { client: !!this.client, hasHeartbeat: (_a = this.client) === null || _a === void 0 ? void 0 : _a.hasHeartbeat() });
235
240
  if (!this.client || this.client.hasHeartbeat()) {
236
241
  return;
237
242
  }
@@ -362,18 +367,26 @@ class Softphone extends events_1.EventEmitter {
362
367
  });
363
368
  this.client.on(this.client.UNREGISTERED, () => {
364
369
  logger.info('softphone - unregistered');
370
+ if (!(0, utils_1.can)(this.softphoneActor, softphone_state_machine_1.Actions.UNREGISTER)) {
371
+ logger.warn('softphone - cannot unregister', { state: this.state });
372
+ return;
373
+ }
374
+ this._sendAction(softphone_state_machine_1.Actions.UNREGISTER);
365
375
  this.emit(exports.EVENT_UNREGISTERED);
366
- this._sendAction(softphone_state_machine_1.Actions.UNREGISTERED);
367
376
  });
368
377
  this.client.on(this.client.ON_DISCONNECTED, () => {
369
378
  logger.info('softphone - disconnected');
370
- this.emit(exports.EVENT_DISCONNECTED);
379
+ if (!(0, utils_1.can)(this.softphoneActor, softphone_state_machine_1.Actions.TRANSPORT_CLOSED)) {
380
+ logger.warn('softphone - cannot disconnected', { state: this.state });
381
+ return;
382
+ }
371
383
  this._sendAction(softphone_state_machine_1.Actions.TRANSPORT_CLOSED);
384
+ this.emit(exports.EVENT_DISCONNECTED);
372
385
  });
373
386
  this.client.on(this.client.REGISTERED, () => {
374
387
  logger.info('softphone - registered', { state: (0, utils_1.getState)(this.softphoneActor) });
375
388
  if (!(0, utils_1.can)(this.softphoneActor, softphone_state_machine_1.Actions.REGISTER_DONE)) {
376
- logger.warn('softphone - registered but not in REGISTERING state', { state: (0, utils_1.getState)(this.softphoneActor) });
389
+ logger.warn('softphone - registered but not in REGISTERING state', { state: this.state });
377
390
  return;
378
391
  }
379
392
  this.stopHeartbeat();
@@ -389,9 +402,13 @@ class Softphone extends events_1.EventEmitter {
389
402
  }
390
403
  });
391
404
  this.client.on(this.client.CONNECTED, () => {
392
- logger.info('softphone - connected');
405
+ logger.info('softphone - connected', { state: this.state });
393
406
  this.stopHeartbeat();
394
407
  });
408
+ this.client.on(this.client.REGISTERING, () => {
409
+ logger.info('softphone - registering', { state: this.state });
410
+ this._sendAction(softphone_state_machine_1.Actions.REGISTER);
411
+ });
395
412
  this.client.on(this.client.DISCONNECTED, () => {
396
413
  logger.info('softphone - disconnected');
397
414
  this.emit(exports.EVENT_DISCONNECTED);
@@ -417,7 +434,9 @@ class Softphone extends events_1.EventEmitter {
417
434
  });
418
435
  }
419
436
  _sendAction(action) {
437
+ const was = this.state;
420
438
  this.softphoneActor.send({ type: action });
439
+ logger.trace('softphone - send action', { action, was, state: this.state });
421
440
  }
422
441
  _getCall(sipCall) {
423
442
  return this.calls.find(call => call.id === (0, sdp_1.getSipCallId)(sipCall));
@@ -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
  }
@@ -112,6 +113,7 @@ class WebRTCClient extends Emitter_1.default {
112
113
  this.heartbeat.setOnHeartbeatTimeout(this._onHeartbeatTimeout.bind(this));
113
114
  // sugar
114
115
  this.REGISTERED = REGISTERED;
116
+ this.REGISTERING = REGISTERING;
115
117
  this.UNREGISTERED = UNREGISTERED;
116
118
  this.REGISTRATION_FAILED = REGISTRATION_FAILED;
117
119
  this.INVITE = INVITE;
@@ -244,6 +246,7 @@ class WebRTCClient extends Emitter_1.default {
244
246
  return Promise.resolve();
245
247
  }
246
248
  logger.info('sdk webrtc registering...', logInfo);
249
+ this.eventEmitter.emit(REGISTERING);
247
250
  if (!this.userAgent) {
248
251
  logger.info('sdk webrtc recreating User Agent');
249
252
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
@@ -1265,8 +1268,8 @@ class WebRTCClient extends Emitter_1.default {
1265
1268
  return audio;
1266
1269
  });
1267
1270
  }
1268
- _onTransportError() {
1269
- logger.error('on transport error');
1271
+ _onTransportError(reason) {
1272
+ logger.warn('on transport error', { reason });
1270
1273
  this.eventEmitter.emit(TRANSPORT_ERROR);
1271
1274
  this.attemptReconnection();
1272
1275
  }
@@ -1321,7 +1324,7 @@ class WebRTCClient extends Emitter_1.default {
1321
1324
  }
1322
1325
  }
1323
1326
  // We can invoke disconnect() with an error that can be catcher by `onDisconnect`, so we have to trigger it here.
1324
- this._onTransportError();
1327
+ this._onTransportError('heartbeat timeout');
1325
1328
  }
1326
1329
  });
1327
1330
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wazo/sdk",
3
- "version": "1.0.0-alpha.6",
3
+ "version": "1.0.0-alpha.8",
4
4
  "description": "Wazo's JavaScript Software Development Kit.",
5
5
  "main": "index.js",
6
6
  "types": "lib/types/index.d.ts",
@@ -12,7 +12,6 @@ export const Actions = {
12
12
  REGISTER: 'register',
13
13
  REGISTER_DONE: 'registerDone',
14
14
  UNREGISTER: 'unregister',
15
- UNREGISTERED: 'unregistered',
16
15
  TRANSPORT_CLOSED: 'transportClosed',
17
16
  } as const;
18
17
 
@@ -32,7 +31,7 @@ const softphoneMachine = setup({}).createMachine({
32
31
  on: {
33
32
  [Actions.REGISTER_DONE]: States.REGISTERED,
34
33
  [Actions.TRANSPORT_CLOSED]: States.UNREGISTERED,
35
- [Actions.UNREGISTERED]: States.UNREGISTERED,
34
+ [Actions.UNREGISTER]: States.UNREGISTERED,
36
35
  },
37
36
  },
38
37
  [States.REGISTERED]: {
@@ -16,8 +16,15 @@ export const can = (actor: SoftphoneActorRef | CallActorRef, action: SoftphoneAc
16
16
  return actor.getSnapshot().can({ type: action });
17
17
  };
18
18
 
19
- export const hasState = (actor: SoftphoneActorRef | CallActorRef, state: SoftphoneStates | CallStates): boolean => {
20
- return getState(actor) === state;
19
+ export const hasState = (actor: SoftphoneActorRef | CallActorRef, state: SoftphoneStates | CallStates, innerState?: EstablishedStateTypes): boolean => {
20
+ const currentState = getState(actor);
21
+
22
+ // When using nested states, we'll have an object here
23
+ if (typeof currentState === 'object') {
24
+ return innerState ? state in currentState && currentState[state as CallStates] === innerState : state in currentState;
25
+ }
26
+
27
+ return currentState === state;
21
28
  };
22
29
 
23
30
  export const waitUntilState = (actor: SoftphoneActorRef | CallActorRef, state: SoftphoneStates | CallStates, timeout = 5000): Promise<unknown> => {
package/src/voice/call.ts CHANGED
@@ -550,6 +550,10 @@ class Call extends EventEmitter {
550
550
  this._onScreenSharing(localStream as MediaStream, false, desktop);
551
551
  }
552
552
 
553
+ onMakeCall() {
554
+ this._sendAction(Actions.MAKE_CALL);
555
+ }
556
+
553
557
  onAccepted() {
554
558
  this._sendAction(Actions.REMOTLY_ACCEPTED);
555
559
  this.emit(EVENT_CALL_REMOTLY_ACCEPTED);
@@ -816,7 +820,9 @@ class Call extends EventEmitter {
816
820
  }
817
821
 
818
822
  private _sendAction(action: ActionTypes | EstablishedActionTypes) {
823
+ const was = this.state;
819
824
  this.callActor.send({ type: action });
825
+ logger.trace('call - send action', { action, was, state: this.state });
820
826
  }
821
827
  }
822
828
 
@@ -93,6 +93,8 @@ export class Softphone extends EventEmitter {
93
93
  const server = Wazo.Auth.getHost();
94
94
  const session = Wazo.Auth.getSession();
95
95
 
96
+ logger.info('softphone - connect', { server, session: !!session });
97
+
96
98
  if (!server || !session) {
97
99
  throw new Error('Please connect to the server using `Wazo.Auth.logIn` or `Wazo.Auth.authenticate` before using Room.connect().');
98
100
  }
@@ -116,6 +118,7 @@ export class Softphone extends EventEmitter {
116
118
  async disconnect() {
117
119
  assertCan(this.softphoneActor, Actions.UNREGISTER);
118
120
  if (!this.client) {
121
+ logger.info('softphone - disconnect, not client to disconnect, bailing');
119
122
  return null;
120
123
  }
121
124
 
@@ -137,7 +140,9 @@ export class Softphone extends EventEmitter {
137
140
  ): Promise<void> {
138
141
  assertCan(this.softphoneActor, Actions.REGISTER);
139
142
 
140
- this.softphoneActor.send({ type: Actions.REGISTER });
143
+ logger.info('softphone - connect with credentials', { server, username: sipLine.username, displayName, options: rawOptions });
144
+
145
+ this._sendAction(Actions.REGISTER);
141
146
 
142
147
  const [host, port = 443] = server.split(':');
143
148
  let options = { ...rawOptions };
@@ -207,6 +212,7 @@ export class Softphone extends EventEmitter {
207
212
  try {
208
213
  sipCall = this.client.call(options.params.To, options.withCamera, options.audioOnly, options.conference, options) as SipCall;
209
214
  const call = new Call(sipCall, this);
215
+ call.onMakeCall();
210
216
 
211
217
  this.calls.push(call);
212
218
  this.emit(EVENT_OUTGOING, call);
@@ -290,7 +296,7 @@ export class Softphone extends EventEmitter {
290
296
  }
291
297
 
292
298
  startHeartbeat() {
293
- logger.info('softphone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
299
+ logger.info('softphone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client?.hasHeartbeat() });
294
300
  if (!this.client || this.client.hasHeartbeat()) {
295
301
  return;
296
302
  }
@@ -455,22 +461,32 @@ export class Softphone extends EventEmitter {
455
461
 
456
462
  this.client.on(this.client.UNREGISTERED, () => {
457
463
  logger.info('softphone - unregistered');
458
- this.emit(EVENT_UNREGISTERED);
464
+ if (!can(this.softphoneActor, Actions.UNREGISTER)) {
465
+ logger.warn('softphone - cannot unregister', { state: this.state });
466
+ return;
467
+ }
468
+
469
+ this._sendAction(Actions.UNREGISTER);
459
470
 
460
- this._sendAction(Actions.UNREGISTERED);
471
+ this.emit(EVENT_UNREGISTERED);
461
472
  });
462
473
 
463
474
  this.client.on(this.client.ON_DISCONNECTED, () => {
464
475
  logger.info('softphone - disconnected');
465
- this.emit(EVENT_DISCONNECTED);
476
+ if (!can(this.softphoneActor, Actions.TRANSPORT_CLOSED)) {
477
+ logger.warn('softphone - cannot disconnected', { state: this.state });
478
+ return;
479
+ }
466
480
 
467
481
  this._sendAction(Actions.TRANSPORT_CLOSED);
482
+
483
+ this.emit(EVENT_DISCONNECTED);
468
484
  });
469
485
 
470
486
  this.client.on(this.client.REGISTERED, () => {
471
487
  logger.info('softphone - registered', { state: getState(this.softphoneActor) });
472
488
  if (!can(this.softphoneActor, Actions.REGISTER_DONE)) {
473
- logger.warn('softphone - registered but not in REGISTERING state', { state: getState(this.softphoneActor) });
489
+ logger.warn('softphone - registered but not in REGISTERING state', { state: this.state });
474
490
  return;
475
491
  }
476
492
 
@@ -491,10 +507,16 @@ export class Softphone extends EventEmitter {
491
507
  });
492
508
 
493
509
  this.client.on(this.client.CONNECTED, () => {
494
- logger.info('softphone - connected');
510
+ logger.info('softphone - connected', { state: this.state });
495
511
  this.stopHeartbeat();
496
512
  });
497
513
 
514
+ this.client.on(this.client.REGISTERING, () => {
515
+ logger.info('softphone - registering', { state: this.state });
516
+
517
+ this._sendAction(Actions.REGISTER);
518
+ });
519
+
498
520
  this.client.on(this.client.DISCONNECTED, () => {
499
521
  logger.info('softphone - disconnected');
500
522
  this.emit(EVENT_DISCONNECTED);
@@ -528,7 +550,9 @@ export class Softphone extends EventEmitter {
528
550
  }
529
551
 
530
552
  private _sendAction(action: ActionTypes) {
553
+ const was = this.state;
531
554
  this.softphoneActor.send({ type: action });
555
+ logger.trace('softphone - send action', { action, was, state: this.state });
532
556
  }
533
557
 
534
558
  private _getCall(sipCall: SipCall): Call | undefined {
@@ -39,6 +39,7 @@ const logger = IssueReporter ? IssueReporter.loggerFor('webrtc-client') : consol
39
39
  const statsLogger = IssueReporter ? IssueReporter.loggerFor('webrtc-stats') : console;
40
40
  // events
41
41
  const REGISTERED = 'registered';
42
+ const REGISTERING = 'registering';
42
43
  const UNREGISTERED = 'unregistered';
43
44
  const REGISTRATION_FAILED = 'registrationFailed';
44
45
  const INVITE = 'invite';
@@ -57,7 +58,7 @@ const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
57
58
  const ON_NETWORK_STATS = 'onNetworkStats';
58
59
  const ON_DISCONNECTED = 'onDisconnected';
59
60
 
60
- export const events = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
61
+ export const events = [REGISTERED, REGISTERING, UNREGISTERED, REGISTRATION_FAILED, INVITE];
61
62
  export const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
62
63
  export class CanceledCallError extends Error {}
63
64
 
@@ -119,6 +120,8 @@ export default class WebRTCClient extends Emitter {
119
120
 
120
121
  REGISTERED: string;
121
122
 
123
+ REGISTERING: string;
124
+
122
125
  UNREGISTERED: string;
123
126
 
124
127
  REGISTRATION_FAILED: string;
@@ -196,6 +199,7 @@ export default class WebRTCClient extends Emitter {
196
199
  this.heartbeat.setOnHeartbeatTimeout(this._onHeartbeatTimeout.bind(this));
197
200
  // sugar
198
201
  this.REGISTERED = REGISTERED;
202
+ this.REGISTERING = REGISTERING;
199
203
  this.UNREGISTERED = UNREGISTERED;
200
204
  this.REGISTRATION_FAILED = REGISTRATION_FAILED;
201
205
  this.INVITE = INVITE;
@@ -343,6 +347,8 @@ export default class WebRTCClient extends Emitter {
343
347
 
344
348
  logger.info('sdk webrtc registering...', logInfo);
345
349
 
350
+ this.eventEmitter.emit(REGISTERING);
351
+
346
352
  if (!this.userAgent) {
347
353
  logger.info('sdk webrtc recreating User Agent');
348
354
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
@@ -1547,8 +1553,8 @@ export default class WebRTCClient extends Emitter {
1547
1553
  return audio;
1548
1554
  }
1549
1555
 
1550
- _onTransportError(): void {
1551
- logger.error('on transport error');
1556
+ _onTransportError(reason?: string): void {
1557
+ logger.warn('on transport error', { reason });
1552
1558
  this.eventEmitter.emit(TRANSPORT_ERROR);
1553
1559
  this.attemptReconnection();
1554
1560
  }
@@ -1610,7 +1616,7 @@ export default class WebRTCClient extends Emitter {
1610
1616
  }
1611
1617
 
1612
1618
  // We can invoke disconnect() with an error that can be catcher by `onDisconnect`, so we have to trigger it here.
1613
- this._onTransportError();
1619
+ this._onTransportError('heartbeat timeout');
1614
1620
  }
1615
1621
  }
1616
1622