@wazo/sdk 1.0.0-alpha.1 → 1.0.0-alpha.3

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 (73) hide show
  1. package/dist/wazo-sdk.js +6 -6
  2. package/esm/__tests__/__voice__/call.test.js +45 -2
  3. package/esm/domain/Phone/CTIPhone.js +2 -2
  4. package/esm/domain/Phone/WebRTCPhone.js +6 -7
  5. package/esm/index.js +1 -1
  6. package/esm/service/CallApi.js +4 -4
  7. package/esm/simple/Phone.js +1 -0
  8. package/esm/state-machine/call-state-machine.js +1 -1
  9. package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -1
  10. package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  11. package/esm/types/index.d.ts +1 -1
  12. package/esm/types/index.d.ts.map +1 -1
  13. package/esm/types/service/CallApi.d.ts +5 -5
  14. package/esm/types/service/CallApi.d.ts.map +1 -1
  15. package/esm/types/simple/Phone.d.ts.map +1 -1
  16. package/esm/types/state-machine/softphone-state-machine.d.ts +1 -1
  17. package/esm/types/state-machine/utils.d.ts +1 -1
  18. package/esm/types/state-machine/utils.d.ts.map +1 -1
  19. package/esm/types/utils/sdp.d.ts +2 -0
  20. package/esm/types/utils/sdp.d.ts.map +1 -1
  21. package/esm/types/utils/webrtc.d.ts +1 -0
  22. package/esm/types/utils/webrtc.d.ts.map +1 -1
  23. package/esm/types/voice/call.d.ts +27 -12
  24. package/esm/types/voice/call.d.ts.map +1 -1
  25. package/esm/types/voice/softphone.d.ts +22 -13
  26. package/esm/types/voice/softphone.d.ts.map +1 -1
  27. package/esm/utils/sdp.js +13 -0
  28. package/esm/utils/webrtc.js +20 -0
  29. package/esm/voice/call.js +115 -33
  30. package/esm/voice/softphone.js +105 -25
  31. package/lib/__tests__/__voice__/call.test.js +44 -1
  32. package/lib/domain/Phone/CTIPhone.js +2 -2
  33. package/lib/domain/Phone/WebRTCPhone.js +5 -6
  34. package/lib/index.js +2 -2
  35. package/lib/service/CallApi.js +2 -2
  36. package/lib/simple/Phone.js +1 -0
  37. package/lib/state-machine/call-state-machine.js +1 -1
  38. package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
  39. package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  40. package/lib/types/index.d.ts +1 -1
  41. package/lib/types/index.d.ts.map +1 -1
  42. package/lib/types/service/CallApi.d.ts +5 -5
  43. package/lib/types/service/CallApi.d.ts.map +1 -1
  44. package/lib/types/simple/Phone.d.ts.map +1 -1
  45. package/lib/types/state-machine/softphone-state-machine.d.ts +1 -1
  46. package/lib/types/state-machine/utils.d.ts +1 -1
  47. package/lib/types/state-machine/utils.d.ts.map +1 -1
  48. package/lib/types/utils/sdp.d.ts +2 -0
  49. package/lib/types/utils/sdp.d.ts.map +1 -1
  50. package/lib/types/utils/webrtc.d.ts +1 -0
  51. package/lib/types/utils/webrtc.d.ts.map +1 -1
  52. package/lib/types/voice/call.d.ts +27 -12
  53. package/lib/types/voice/call.d.ts.map +1 -1
  54. package/lib/types/voice/softphone.d.ts +22 -13
  55. package/lib/types/voice/softphone.d.ts.map +1 -1
  56. package/lib/utils/sdp.js +16 -1
  57. package/lib/utils/webrtc.js +22 -1
  58. package/lib/voice/call.js +112 -31
  59. package/lib/voice/softphone.js +109 -25
  60. package/package.json +1 -1
  61. package/src/__tests__/__voice__/call.test.ts +48 -2
  62. package/src/domain/Phone/CTIPhone.ts +3 -2
  63. package/src/domain/Phone/WebRTCPhone.ts +9 -9
  64. package/src/index.ts +1 -1
  65. package/src/service/CallApi.ts +7 -7
  66. package/src/simple/Phone.ts +1 -0
  67. package/src/state-machine/call-state-machine.ts +1 -1
  68. package/src/state-machine/utils.ts +2 -2
  69. package/src/utils/sdp.ts +16 -0
  70. package/src/utils/webrtc.ts +23 -1
  71. package/src/voice/call.ts +149 -43
  72. package/src/voice/softphone.ts +130 -31
  73. package/src/web-rtc-client.ts +1 -1
package/src/voice/call.ts CHANGED
@@ -8,13 +8,16 @@ import { SessionDescriptionHandler } from 'sip.js/lib/platform/web';
8
8
  import { SessionDescriptionHandlerOptions } from 'sip.js/lib/api';
9
9
  import type { IncomingRequestMessage } from 'sip.js/lib/core/messages/incoming-request-message';
10
10
 
11
- import callStateMachine, { type ActionTypes, Actions, type EstablishedActionTypes, EstablishedActions, States, EstablishedStates, type CallActorRef } from '../state-machine/call-state-machine';
11
+ import callStateMachine, { type ActionTypes, Actions, type EstablishedActionTypes, EstablishedActions, States, type StateTypes, EstablishedStates, type EstablishedStateTypes, type CallActorRef } from '../state-machine/call-state-machine';
12
12
  import { SipCall, PeerConnection } from '../domain/types';
13
+ import ApiCall from '../domain/Call';
14
+ import newFrom from '../utils/new-from';
15
+ import updateFrom from '../utils/update-from';
13
16
  import IssueReporter from '../service/IssueReporter';
14
- import { Softphone } from './softphone';
15
- import { getSipSessionId } from '../utils/sdp';
17
+ import softphone, { EVENT_TERMINATE_SOUND, Softphone } from './softphone';
18
+ import { getCallDisplayName, getCallNumber, getSipSessionId } from '../utils/sdp';
16
19
  import { assertCan, assertState, getState } from '../state-machine/utils';
17
- import { downgradeToAudio, getLocalStream, getLocalVideoStream, getPeerConnection, getRemoteStream, getRemoteVideoStream, getStreamFromConstraints, getWebRtcStats, hasALocalVideoTrack, hasLocalVideo, hasRemoteVideo, isVideoRemotelyHeld, setLocalMediaStream, toggleVideo, upgradeToVideo } from '../utils/webrtc';
20
+ import { downgradeToAudio, getLocalStream, getLocalVideoStream, getPeerConnection, getRemoteStream, getRemoteVideoStream, getStreamFromConstraints, getWebRtcStats, hasALocalVideoTrack, hasLocalVideo, hasRemoteVideo, isVideoMuted, isVideoRemotelyHeld, setLocalMediaStream, toggleVideo, upgradeToVideo } from '../utils/webrtc';
18
21
 
19
22
  const logger = IssueReporter.loggerFor('call');
20
23
 
@@ -30,7 +33,8 @@ export type ReinviteOptions = {
30
33
  };
31
34
 
32
35
  // Events
33
- export const EVENT_CALL_ACCEPTED = 'accepted';
36
+ export const EVENT_CALL_REMOTLY_ACCEPTED = 'remotelyAccepted';
37
+ export const EVENT_CALL_LOCALLY_ACCEPTED = 'locallyAccepted';
34
38
  export const EVENT_CALL_CANCELED = 'canceled';
35
39
  export const EVENT_PROGRESS = 'progress';
36
40
  export const EVENT_EARLY_MEDIA = 'earlyMedia';
@@ -53,15 +57,12 @@ export const EVENT_SHARE_SCREEN_ENDED = 'onScreenShareEnded';
53
57
  export const EVENT_WEB_RTC_STATS = 'webRtcStats';
54
58
  export const EVENT_CAMERA_RESUMED = 'onCameraResumed';
55
59
  export const EVENT_CAMERA_DISABLED = 'onCameraDisabled';
56
- export const EVENT_TERMINATE_SOUND = 'terminateSound';
57
60
 
58
61
  export const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
59
62
  export const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
60
63
  export const MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
61
64
 
62
65
  class Call extends EventEmitter {
63
- eventEmitter: EventEmitter;
64
-
65
66
  callActor: CallActorRef;
66
67
 
67
68
  // Wazo call id, used in Wazo Websocket and API
@@ -81,8 +82,69 @@ class Call extends EventEmitter {
81
82
 
82
83
  shouldSendReinvite = false;
83
84
 
85
+ recording = false;
86
+
87
+ displayName: string | null;
88
+
89
+ number: string | null;
90
+
84
91
  currentScreenShare: Record<string, any> | null;
85
92
 
93
+ static newFrom(call: Call) {
94
+ return newFrom(call, Call);
95
+ }
96
+
97
+ static parseCall(apiCall: ApiCall): Call {
98
+ const sipCall = {
99
+ id: apiCall.sipCallId,
100
+ stateChange: {
101
+ addListener: () => {},
102
+ },
103
+ remoteIdentity: {
104
+ uri: {
105
+ _normal: {
106
+ user: apiCall.calleeNumber,
107
+ },
108
+ },
109
+ },
110
+ // Mock sdk so `hasLocalVideo` will return true.
111
+ sessionDescriptionHandler: {
112
+ localMediaStream: {
113
+ getTracks: () => (apiCall.isVideo ? [{ kind: 'video', readyState: 'live' }] : []),
114
+ },
115
+ },
116
+ } as any;
117
+
118
+ const call = new Call(sipCall, softphone);
119
+ // call._sendAction(Actions.ES);
120
+ call.apiId = apiCall.id;
121
+ call.answerTime = new Date(+apiCall.startingTime);
122
+
123
+ // Update call state
124
+ const snapshot = call.callActor.getSnapshot();
125
+
126
+ if (apiCall.isUp()) {
127
+ snapshot.value = { [States.ESTABLISHED]: EstablishedStates.ONGOING };
128
+ }
129
+
130
+ if (apiCall.muted) {
131
+ snapshot.value = { [States.ESTABLISHED]: EstablishedStates.MUTED };
132
+ }
133
+
134
+ if (apiCall.isRinging()) {
135
+ snapshot.value = States.RINGING;
136
+ }
137
+
138
+ if (apiCall.isRecording()) {
139
+ call.recording = true;
140
+ }
141
+
142
+ // @ts-ignore
143
+ call.callActor.update(snapshot);
144
+
145
+ return call;
146
+ }
147
+
86
148
  constructor(sipCall: SipCall, phone: Softphone) {
87
149
  super();
88
150
 
@@ -94,6 +156,9 @@ class Call extends EventEmitter {
94
156
  this.phone = phone;
95
157
  this.sipCall = sipCall;
96
158
 
159
+ this.number = getCallNumber(sipCall);
160
+ this.displayName = getCallDisplayName(sipCall);
161
+
97
162
  this._bindEvents();
98
163
  }
99
164
 
@@ -111,6 +176,8 @@ class Call extends EventEmitter {
111
176
  return this.phone.client.answer(this.sipCall as Invitation, options.withCamera).then(() => {
112
177
  logger.info('call - accepted', { id: this.id, ...options });
113
178
 
179
+ this.emit(EVENT_CALL_LOCALLY_ACCEPTED, this);
180
+
114
181
  return this.id;
115
182
  }).catch(e => {
116
183
  logger.error(e);
@@ -123,7 +190,7 @@ class Call extends EventEmitter {
123
190
  assertCan(this.callActor, Actions.REJECT);
124
191
  logger.info('call - reject', { id: this.id });
125
192
 
126
- this.eventEmitter.emit(EVENT_TERMINATE_SOUND, 'call rejected locally');
193
+ this.phone.emit(EVENT_TERMINATE_SOUND, 'call rejected locally');
127
194
 
128
195
  this.shouldSendReinvite = false;
129
196
 
@@ -137,7 +204,7 @@ class Call extends EventEmitter {
137
204
  await this.phone.client.hangup(this.sipCall);
138
205
 
139
206
  // Remove this call from softphone's calls
140
- this.phone.removeCall(this);
207
+ this.phone.onCallTerminated(this);
141
208
 
142
209
  return true;
143
210
  }
@@ -151,7 +218,7 @@ class Call extends EventEmitter {
151
218
  }
152
219
  }
153
220
 
154
- startConference(withCalls: Call[]) {
221
+ startConference(/* withCalls: Call[] */) {
155
222
  // @TODO
156
223
  // const participants = [this, ...withCalls].reduce((acc: Record<string, any>, call: Call) => {
157
224
  // acc[call.talkingToIds[0]] = call;
@@ -174,7 +241,7 @@ class Call extends EventEmitter {
174
241
 
175
242
  this.phone.client.mute(this.sipCall);
176
243
 
177
- this.eventEmitter.emit(EVENT_CALL_MUTED);
244
+ this.emit(EVENT_CALL_MUTED);
178
245
  }
179
246
 
180
247
  unMute() {
@@ -185,7 +252,7 @@ class Call extends EventEmitter {
185
252
 
186
253
  this.phone.client.unmute(this.sipCall);
187
254
 
188
- this.eventEmitter.emit(EVENT_CALL_UN_MUTED);
255
+ this.emit(EVENT_CALL_UN_MUTED);
189
256
  }
190
257
 
191
258
  async hold() {
@@ -208,7 +275,7 @@ class Call extends EventEmitter {
208
275
 
209
276
  const promise = this.phone.client.hold(this.sipCall, this.isConference(), hasVideo);
210
277
 
211
- this.eventEmitter.emit(EVENT_CALL_HELD);
278
+ this.emit(EVENT_CALL_HELD);
212
279
 
213
280
  return promise;
214
281
  }
@@ -244,7 +311,7 @@ class Call extends EventEmitter {
244
311
  }
245
312
  };
246
313
 
247
- this.eventEmitter.emit(EVENT_CALL_RESUMED);
314
+ this.emit(EVENT_CALL_RESUMED);
248
315
 
249
316
  return promise.then(() => {
250
317
  const stream = this.getLocalVideoStream();
@@ -261,7 +328,7 @@ class Call extends EventEmitter {
261
328
  logger.info('call - turn camera on', { id: this.id });
262
329
  toggleVideo(this.sipCall, true);
263
330
 
264
- this.eventEmitter.emit(EVENT_CAMERA_RESUMED);
331
+ this.emit(EVENT_CAMERA_RESUMED);
265
332
  }
266
333
 
267
334
  turnCameraOff(): void {
@@ -269,15 +336,39 @@ class Call extends EventEmitter {
269
336
  logger.info('call - turn camera off', { id: this.id });
270
337
  toggleVideo(this.sipCall, false);
271
338
 
272
- this.eventEmitter.emit(EVENT_CAMERA_DISABLED);
339
+ this.emit(EVENT_CAMERA_DISABLED);
340
+ }
341
+
342
+ isMuted() {
343
+ return this._hasEstablishedState(EstablishedStates.MUTED);
344
+ }
345
+
346
+ isCameraMuted() {
347
+ return isVideoMuted(this.sipCall);
273
348
  }
274
349
 
275
350
  isHeld() {
276
- return getState(this.callActor) === EstablishedStates.HELD;
351
+ return this._hasEstablishedState(EstablishedStates.HELD);
352
+ }
353
+
354
+ isEstablishing() {
355
+ return this.sipCall.state === SessionState.Establishing;
277
356
  }
278
357
 
279
358
  isEstablished() {
280
- return getState(this.callActor) === States.ESTABLISHED;
359
+ return States.ESTABLISHED in (this.state as Record<StateTypes, EstablishedStateTypes>);
360
+ }
361
+
362
+ isRinging() {
363
+ return this.state === States.RINGING;
364
+ }
365
+
366
+ isOutgoing() {
367
+ return this.sipCall instanceof Invitation;
368
+ }
369
+
370
+ isIncoming() {
371
+ return !this.isOutgoing();
281
372
  }
282
373
 
283
374
  isConference(): boolean {
@@ -288,7 +379,7 @@ class Call extends EventEmitter {
288
379
  assertState(this.callActor, States.ESTABLISHED);
289
380
  logger.info('call - transfer', { id: this.id, target });
290
381
 
291
- this.phone.client.transfer(this.sipCall, target);
382
+ return this.phone.client.transfer(this.sipCall, target);
292
383
  }
293
384
 
294
385
  atxfer(): Record<string, any> | null | undefined {
@@ -446,7 +537,7 @@ class Call extends EventEmitter {
446
537
  console.warn(e);
447
538
  }
448
539
 
449
- this.eventEmitter.emit(EVENT_SHARE_SCREEN_ENDED);
540
+ this.emit(EVENT_SHARE_SCREEN_ENDED);
450
541
  this.currentScreenShare = null;
451
542
 
452
543
  return reinvited;
@@ -461,7 +552,7 @@ class Call extends EventEmitter {
461
552
 
462
553
  onAccepted() {
463
554
  this._sendAction(Actions.REMOTLY_ACCEPTED);
464
- this.emit(EVENT_CALL_ACCEPTED);
555
+ this.emit(EVENT_CALL_REMOTLY_ACCEPTED);
465
556
  }
466
557
 
467
558
  onProgress() {
@@ -480,12 +571,16 @@ class Call extends EventEmitter {
480
571
  this.emit(EVENT_CALL_ERROR, error);
481
572
  }
482
573
 
574
+ onCallIncoming() {
575
+ this._sendAction(Actions.INCOMING_CALL);
576
+ }
577
+
483
578
  onRejected() {
484
579
  this.endTime = new Date();
485
580
 
486
581
  this.emit(EVENT_CALL_REJECTED);
487
582
 
488
- this.phone.removeCall(this);
583
+ this.phone.onCallTerminated(this);
489
584
  }
490
585
 
491
586
  onNetworkStats(stats: Record<string, any>, previousStats: Record<string, any>) {
@@ -528,17 +623,28 @@ class Call extends EventEmitter {
528
623
  this.emit(EVENT_REINVITE, request, updatedCalleeName, updatedNumber, hadRemoteVideo);
529
624
  }
530
625
 
626
+ updateFrom(call: Call) {
627
+ updateFrom(this, call);
628
+ }
629
+
630
+ is(otherCall: Call) {
631
+ return otherCall && this.id && this.id === otherCall.id;
632
+ }
633
+
531
634
  get id() {
532
635
  return getSipSessionId(this.sipCall);
533
636
  }
534
637
 
535
- get number() {
536
- const identity = this.sipCall.remoteIdentity || this.sipCall.assertedIdentity;
537
- // @ts-ignore: private
538
- return identity ? identity.uri._normal.user : null;
638
+ get state(): StateTypes | Record<StateTypes, EstablishedStateTypes> {
639
+ return getState(this.callActor) as StateTypes | Record<StateTypes, EstablishedStateTypes>;
640
+ }
641
+
642
+ private _hasEstablishedState(establishedState: EstablishedStateTypes) {
643
+ const state = this.state as Record<StateTypes, EstablishedStateTypes>;
644
+ return States.ESTABLISHED in state && state[States.ESTABLISHED] === establishedState;
539
645
  }
540
646
 
541
- _bindEvents() {
647
+ private _bindEvents() {
542
648
  if (this.sipCall instanceof Invitation) {
543
649
  // Monkey patch to know when canceled with the CANCEL message
544
650
  const onCancel = (this.sipCall as Invitation)._onCancel.bind(this.sipCall);
@@ -548,7 +654,7 @@ class Call extends EventEmitter {
548
654
  onCancel(message);
549
655
  const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
550
656
 
551
- this.eventEmitter.emit(EVENT_CALL_CANCELED, elsewhere);
657
+ this.emit(EVENT_CALL_CANCELED, elsewhere);
552
658
  };
553
659
  }
554
660
 
@@ -556,7 +662,7 @@ class Call extends EventEmitter {
556
662
  switch (newState) {
557
663
  case SessionState.Terminating:
558
664
  logger.info('call - terminating', { id: this.id });
559
- this.eventEmitter.emit(EVENT_CALL_TERMINATING);
665
+ this.emit(EVENT_CALL_TERMINATING);
560
666
  break;
561
667
 
562
668
  case SessionState.Terminated:
@@ -566,7 +672,9 @@ class Call extends EventEmitter {
566
672
  // Should be called before `_onCallTerminated` or the callCount will not decrement...
567
673
  this.endTime = new Date();
568
674
 
569
- return this.eventEmitter.emit(EVENT_CALL_ENDED);
675
+ this.emit(EVENT_CALL_ENDED);
676
+
677
+ return this.phone.onCallTerminated(this);
570
678
  }
571
679
 
572
680
  default:
@@ -599,10 +707,10 @@ class Call extends EventEmitter {
599
707
  });
600
708
 
601
709
  if (kind === 'audio') {
602
- return this.eventEmitter.emit(EVENT_AUDIO_STREAM, stream);
710
+ return this.emit(EVENT_AUDIO_STREAM, stream);
603
711
  }
604
712
 
605
- return this.eventEmitter.emit(EVENT_VIDEO_STREAM, stream, event.track.id, event);
713
+ return this.emit(EVENT_VIDEO_STREAM, stream, event.track.id, event);
606
714
  };
607
715
 
608
716
  peerConnection.onremovestream = (event: any) => {
@@ -610,13 +718,11 @@ class Call extends EventEmitter {
610
718
  id: event.stream.id,
611
719
  tracks: event.stream.getTracks(),
612
720
  });
613
- this.eventEmitter.emit(EVENT_REMOVE_STREAM, event.stream);
721
+ this.emit(EVENT_REMOVE_STREAM, event.stream);
614
722
  };
615
-
616
- // Client events
617
723
  }
618
724
 
619
- _downgradeToAudio(withMessage = true) {
725
+ private _downgradeToAudio(withMessage = true) {
620
726
  assertState(this.callActor, States.ESTABLISHED);
621
727
  logger.info('call - downgrade to audio', { id: this.id, withMessage });
622
728
 
@@ -630,7 +736,7 @@ class Call extends EventEmitter {
630
736
  }
631
737
 
632
738
  // Returns true if we need to send a re-INVITE request
633
- async _upgradeToVideo(options: ReinviteOptions = {}): Promise<boolean> {
739
+ private async _upgradeToVideo(options: ReinviteOptions = {}): Promise<boolean> {
634
740
  assertState(this.callActor, States.ESTABLISHED);
635
741
  logger.info('call - upgrade to video', { id: this.id, ...options });
636
742
 
@@ -660,7 +766,7 @@ class Call extends EventEmitter {
660
766
  return false;
661
767
  }
662
768
 
663
- _sendReinviteMessage(isUpgrade: boolean) {
769
+ private _sendReinviteMessage(isUpgrade: boolean) {
664
770
  assertState(this.callActor, States.ESTABLISHED);
665
771
  logger.info('call - sending reinvite message', { id: this.id, isUpgrade });
666
772
 
@@ -679,7 +785,7 @@ class Call extends EventEmitter {
679
785
  }, 2500);
680
786
  }
681
787
 
682
- _onScreenSharing(screenStream: MediaStream, hadVideo: boolean, desktop?: boolean | null | undefined) {
788
+ private _onScreenSharing(screenStream: MediaStream, hadVideo: boolean, desktop?: boolean | null | undefined) {
683
789
  const screenTrack = screenStream.getVideoTracks()[0];
684
790
  const pc = this.phone.client.getPeerConnection(this.id);
685
791
  const sender = pc && pc.getSenders && pc.getSenders().find((s) => s && s.track && s.track.kind === 'video');
@@ -690,7 +796,7 @@ class Call extends EventEmitter {
690
796
  screenTrack.onended = () => {
691
797
  logger.info('call - on screenshare ended', { hadVideo, id: this.id, screenTrack });
692
798
 
693
- this.eventEmitter.emit(EVENT_SHARE_SCREEN_ENDING);
799
+ this.emit(EVENT_SHARE_SCREEN_ENDING);
694
800
  };
695
801
  }
696
802
 
@@ -702,10 +808,10 @@ class Call extends EventEmitter {
702
808
  };
703
809
 
704
810
  setLocalMediaStream(this.sipCall, screenStream);
705
- this.eventEmitter.emit(EVENT_SHARE_SCREEN_STARTED, screenStream);
811
+ this.emit(EVENT_SHARE_SCREEN_STARTED, screenStream);
706
812
  }
707
813
 
708
- _sendAction(action: ActionTypes | EstablishedActionTypes) {
814
+ private _sendAction(action: ActionTypes | EstablishedActionTypes) {
709
815
  this.callActor.send({ type: action });
710
816
  }
711
817
  }