@wazo/sdk 0.39.14 → 0.40.0
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.
- package/README.md +2 -2
- package/dist/wazo-sdk.js +12 -12
- package/esm/__tests__/api-client.test.js +0 -10
- package/esm/__tests__/web-rtc-client.test.js +2 -15
- package/esm/api/amid.js +12 -4
- package/esm/api/chatd.js +0 -1
- package/esm/api/dird.js +7 -10
- package/esm/checker/checks/ice-ipv4.js +2 -3
- package/esm/checker/checks/symmetric-nat.js +7 -4
- package/esm/domain/AdHocAPIConference.js +1 -1
- package/esm/domain/CallLog.js +1 -1
- package/esm/domain/Contact.js +2 -1
- package/esm/domain/MeetingAuthorization.js +6 -0
- package/esm/domain/Phone/CTIPhone.js +2 -0
- package/esm/domain/Phone/WebRTCPhone.js +23 -18
- package/esm/domain/Session.js +2 -2
- package/esm/domain/__tests__/Agent.test.js +0 -2
- package/esm/domain/__tests__/Call.test.js +0 -1
- package/esm/domain/__tests__/CallLog.test.js +0 -1
- package/esm/domain/__tests__/CallSession.test.js +1 -2
- package/esm/domain/__tests__/Contact.test.js +2 -4
- package/esm/domain/__tests__/IndirectTransfer.test.js +0 -1
- package/esm/domain/__tests__/Profile.test.js +0 -1
- package/esm/domain/__tests__/Room.test.js +1 -25
- package/esm/domain/__tests__/Session.test.js +13 -14
- package/esm/domain/__tests__/SipLine.test.js +2 -3
- package/esm/index.js +42 -88
- package/esm/lib/WazoSessionDescriptionHandler.js +9 -15
- package/esm/service/IssueReporter.js +1 -3
- package/esm/service/__tests__/IssueReporter.test.js +0 -1
- package/esm/simple/Phone.js +1 -1
- package/esm/simple/Websocket.js +2 -2
- package/esm/simple/index.js +5 -4
- package/esm/simple/room/Room.js +15 -15
- package/esm/simple/room/SipRoom.js +1 -1
- package/esm/simple/room/Stream.js +1 -2
- package/esm/simple/room/__tests__/Participant.test.js +0 -2
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +1 -2
- package/esm/types/api/amid.d.ts.map +1 -1
- package/esm/types/api/auth.d.ts +2 -2
- package/esm/types/api/auth.d.ts.map +1 -1
- package/esm/types/api/call-logd.d.ts +3 -3
- package/esm/types/api/call-logd.d.ts.map +1 -1
- package/esm/types/api/chatd.d.ts +9 -22
- package/esm/types/api/chatd.d.ts.map +1 -1
- package/esm/types/api/dird.d.ts +21 -14
- package/esm/types/api/dird.d.ts.map +1 -1
- package/esm/types/checker/checks/ice-ipv4.d.ts.map +1 -1
- package/esm/types/checker/checks/index.d.ts +1 -1
- package/esm/types/checker/checks/symmetric-nat.d.ts.map +1 -1
- package/esm/types/checker/checks/webrtc-transport.d.ts +2 -2
- package/esm/types/checker/checks/webrtc-transport.d.ts.map +1 -1
- package/esm/types/domain/Agent.d.ts +1 -1
- package/esm/types/domain/Agent.d.ts.map +1 -1
- package/esm/types/domain/CallLog.d.ts +14 -26
- package/esm/types/domain/CallLog.d.ts.map +1 -1
- package/esm/types/domain/CallSession.d.ts +3 -4
- package/esm/types/domain/CallSession.d.ts.map +1 -1
- package/esm/types/domain/Contact.d.ts +8 -0
- package/esm/types/domain/Contact.d.ts.map +1 -1
- package/esm/types/domain/MeetingAuthorization.d.ts +6 -0
- package/esm/types/domain/MeetingAuthorization.d.ts.map +1 -1
- package/esm/types/domain/Phone/CTIPhone.d.ts +2 -0
- package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/esm/types/domain/Phone/Phone.d.ts +12 -2
- package/esm/types/domain/Phone/Phone.d.ts.map +1 -1
- package/esm/types/domain/Phone/WebRTCPhone.d.ts +24 -20
- package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/esm/types/domain/Room.d.ts +10 -12
- package/esm/types/domain/Room.d.ts.map +1 -1
- package/esm/types/domain/Session.d.ts +1 -1
- package/esm/types/domain/Session.d.ts.map +1 -1
- package/esm/types/domain/SipLine.d.ts +3 -3
- package/esm/types/domain/SipLine.d.ts.map +1 -1
- package/esm/types/domain/types.d.ts +64 -10
- package/esm/types/domain/types.d.ts.map +1 -1
- package/esm/types/index.d.ts +51 -314
- package/esm/types/index.d.ts.map +1 -1
- package/esm/types/lib/WazoSessionDescriptionHandler.d.ts +5 -4
- package/esm/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
- package/esm/types/service/CallApi.d.ts +3 -3
- package/esm/types/service/CallApi.d.ts.map +1 -1
- package/esm/types/service/IssueReporter.d.ts.map +1 -1
- package/esm/types/simple/Auth.d.ts +0 -40
- package/esm/types/simple/Auth.d.ts.map +1 -1
- package/esm/types/simple/Phone.d.ts +0 -113
- package/esm/types/simple/Phone.d.ts.map +1 -1
- package/esm/types/simple/Websocket.d.ts +0 -16
- package/esm/types/simple/Websocket.d.ts.map +1 -1
- package/esm/types/simple/index.d.ts +8 -8
- package/esm/types/simple/index.d.ts.map +1 -1
- package/esm/types/simple/room/Participant.d.ts +4 -3
- package/esm/types/simple/room/Participant.d.ts.map +1 -1
- package/esm/types/simple/room/Room.d.ts +29 -18
- package/esm/types/simple/room/Room.d.ts.map +1 -1
- package/esm/types/simple/room/SipRoom.d.ts +1 -1
- package/esm/types/simple/room/SipRoom.d.ts.map +1 -1
- package/esm/types/simple/room/Stream.d.ts +1 -1
- package/esm/types/simple/room/Stream.d.ts.map +1 -1
- package/esm/types/utils/PhoneNumberUtil.d.ts +1 -1
- package/esm/types/utils/PhoneNumberUtil.d.ts.map +1 -1
- package/esm/types/utils/api-requester.d.ts +1 -1
- package/esm/types/utils/api-requester.d.ts.map +1 -1
- package/esm/types/utils/sdp.d.ts +20 -5
- package/esm/types/utils/sdp.d.ts.map +1 -1
- package/esm/types/web-rtc-client.d.ts +51 -49
- package/esm/types/web-rtc-client.d.ts.map +1 -1
- package/esm/types/websocket-client.d.ts.map +1 -1
- package/esm/utils/__tests__/PhoneNumberUtil.test.js +0 -6
- package/esm/utils/__tests__/api-requester.test.js +0 -2
- package/esm/utils/__tests__/sdp.test.js +4 -18
- package/esm/utils/api-requester.js +1 -2
- package/esm/utils/sdp.js +8 -3
- package/esm/web-rtc-client.js +99 -136
- package/esm/websocket-client.js +1 -2
- package/index.js +1 -0
- package/lib/__tests__/api-client.test.js +0 -10
- package/lib/__tests__/web-rtc-client.test.js +2 -15
- package/lib/api/amid.js +12 -4
- package/lib/api/chatd.js +0 -1
- package/lib/api/dird.js +19 -22
- package/lib/checker/checks/ice-ipv4.js +2 -3
- package/lib/checker/checks/symmetric-nat.js +7 -4
- package/lib/domain/AdHocAPIConference.js +1 -1
- package/lib/domain/CallLog.js +1 -1
- package/lib/domain/Contact.js +2 -1
- package/lib/domain/MeetingAuthorization.js +6 -0
- package/lib/domain/Phone/CTIPhone.js +2 -0
- package/lib/domain/Phone/WebRTCPhone.js +23 -18
- package/lib/domain/Session.js +2 -2
- package/lib/domain/__tests__/Agent.test.js +0 -2
- package/lib/domain/__tests__/Call.test.js +0 -1
- package/lib/domain/__tests__/CallLog.test.js +0 -1
- package/lib/domain/__tests__/CallSession.test.js +1 -2
- package/lib/domain/__tests__/Contact.test.js +2 -4
- package/lib/domain/__tests__/IndirectTransfer.test.js +0 -1
- package/lib/domain/__tests__/Profile.test.js +0 -1
- package/lib/domain/__tests__/Room.test.js +1 -25
- package/lib/domain/__tests__/Session.test.js +13 -14
- package/lib/domain/__tests__/SipLine.test.js +2 -3
- package/lib/index.js +93 -99
- package/lib/lib/WazoSessionDescriptionHandler.js +9 -15
- package/lib/service/IssueReporter.js +1 -3
- package/lib/service/__tests__/IssueReporter.test.js +0 -1
- package/lib/simple/Phone.js +1 -1
- package/lib/simple/Websocket.js +2 -2
- package/lib/simple/index.js +2 -1
- package/lib/simple/room/Room.js +17 -15
- package/lib/simple/room/SipRoom.js +1 -1
- package/lib/simple/room/Stream.js +1 -2
- package/lib/simple/room/__tests__/Participant.test.js +0 -2
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +1 -2
- package/lib/types/api/amid.d.ts.map +1 -1
- package/lib/types/api/auth.d.ts +2 -2
- package/lib/types/api/auth.d.ts.map +1 -1
- package/lib/types/api/call-logd.d.ts +3 -3
- package/lib/types/api/call-logd.d.ts.map +1 -1
- package/lib/types/api/chatd.d.ts +9 -22
- package/lib/types/api/chatd.d.ts.map +1 -1
- package/lib/types/api/dird.d.ts +21 -14
- package/lib/types/api/dird.d.ts.map +1 -1
- package/lib/types/checker/checks/ice-ipv4.d.ts.map +1 -1
- package/lib/types/checker/checks/index.d.ts +1 -1
- package/lib/types/checker/checks/symmetric-nat.d.ts.map +1 -1
- package/lib/types/checker/checks/webrtc-transport.d.ts +2 -2
- package/lib/types/checker/checks/webrtc-transport.d.ts.map +1 -1
- package/lib/types/domain/Agent.d.ts +1 -1
- package/lib/types/domain/Agent.d.ts.map +1 -1
- package/lib/types/domain/CallLog.d.ts +14 -26
- package/lib/types/domain/CallLog.d.ts.map +1 -1
- package/lib/types/domain/CallSession.d.ts +3 -4
- package/lib/types/domain/CallSession.d.ts.map +1 -1
- package/lib/types/domain/Contact.d.ts +8 -0
- package/lib/types/domain/Contact.d.ts.map +1 -1
- package/lib/types/domain/MeetingAuthorization.d.ts +6 -0
- package/lib/types/domain/MeetingAuthorization.d.ts.map +1 -1
- package/lib/types/domain/Phone/CTIPhone.d.ts +2 -0
- package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/lib/types/domain/Phone/Phone.d.ts +12 -2
- package/lib/types/domain/Phone/Phone.d.ts.map +1 -1
- package/lib/types/domain/Phone/WebRTCPhone.d.ts +24 -20
- package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/lib/types/domain/Room.d.ts +10 -12
- package/lib/types/domain/Room.d.ts.map +1 -1
- package/lib/types/domain/Session.d.ts +1 -1
- package/lib/types/domain/Session.d.ts.map +1 -1
- package/lib/types/domain/SipLine.d.ts +3 -3
- package/lib/types/domain/SipLine.d.ts.map +1 -1
- package/lib/types/domain/types.d.ts +64 -10
- package/lib/types/domain/types.d.ts.map +1 -1
- package/lib/types/index.d.ts +51 -314
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/lib/WazoSessionDescriptionHandler.d.ts +5 -4
- package/lib/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
- package/lib/types/service/CallApi.d.ts +3 -3
- package/lib/types/service/CallApi.d.ts.map +1 -1
- package/lib/types/service/IssueReporter.d.ts.map +1 -1
- package/lib/types/simple/Auth.d.ts +0 -40
- package/lib/types/simple/Auth.d.ts.map +1 -1
- package/lib/types/simple/Phone.d.ts +0 -113
- package/lib/types/simple/Phone.d.ts.map +1 -1
- package/lib/types/simple/Websocket.d.ts +0 -16
- package/lib/types/simple/Websocket.d.ts.map +1 -1
- package/lib/types/simple/index.d.ts +8 -8
- package/lib/types/simple/index.d.ts.map +1 -1
- package/lib/types/simple/room/Participant.d.ts +4 -3
- package/lib/types/simple/room/Participant.d.ts.map +1 -1
- package/lib/types/simple/room/Room.d.ts +29 -18
- package/lib/types/simple/room/Room.d.ts.map +1 -1
- package/lib/types/simple/room/SipRoom.d.ts +1 -1
- package/lib/types/simple/room/SipRoom.d.ts.map +1 -1
- package/lib/types/simple/room/Stream.d.ts +1 -1
- package/lib/types/simple/room/Stream.d.ts.map +1 -1
- package/lib/types/utils/PhoneNumberUtil.d.ts +1 -1
- package/lib/types/utils/PhoneNumberUtil.d.ts.map +1 -1
- package/lib/types/utils/api-requester.d.ts +1 -1
- package/lib/types/utils/api-requester.d.ts.map +1 -1
- package/lib/types/utils/sdp.d.ts +20 -5
- package/lib/types/utils/sdp.d.ts.map +1 -1
- package/lib/types/web-rtc-client.d.ts +51 -49
- package/lib/types/web-rtc-client.d.ts.map +1 -1
- package/lib/types/websocket-client.d.ts.map +1 -1
- package/lib/utils/__tests__/PhoneNumberUtil.test.js +0 -6
- package/lib/utils/__tests__/api-requester.test.js +0 -2
- package/lib/utils/__tests__/sdp.test.js +6 -18
- package/lib/utils/api-requester.js +2 -3
- package/lib/utils/sdp.js +9 -3
- package/lib/web-rtc-client.js +105 -140
- package/lib/websocket-client.js +1 -2
- package/package.json +5 -18
- package/src/__tests__/api-client.test.ts +10 -19
- package/src/__tests__/web-rtc-client.test.ts +13 -25
- package/src/api/amid.ts +13 -4
- package/src/api/auth.ts +2 -5
- package/src/api/call-logd.ts +3 -3
- package/src/api/chatd.ts +10 -24
- package/src/api/dird.ts +33 -39
- package/src/checker/checks/ice-ipv4.ts +4 -5
- package/src/checker/checks/symmetric-nat.ts +11 -7
- package/src/checker/checks/webrtc-transport.ts +2 -2
- package/src/domain/AdHocAPIConference.ts +1 -1
- package/src/domain/Agent.ts +1 -1
- package/src/domain/CallLog.ts +19 -27
- package/src/domain/CallSession.ts +3 -4
- package/src/domain/Contact.ts +3 -1
- package/src/domain/MeetingAuthorization.ts +13 -0
- package/src/domain/Phone/CTIPhone.ts +4 -0
- package/src/domain/Phone/Phone.ts +11 -2
- package/src/domain/Phone/WebRTCPhone.ts +60 -52
- package/src/domain/Room.ts +12 -14
- package/src/domain/Session.ts +3 -3
- package/src/domain/SipLine.ts +3 -3
- package/src/domain/__tests__/Agent.test.ts +3 -5
- package/src/domain/__tests__/Call.test.ts +4 -5
- package/src/domain/__tests__/CallLog.test.ts +1 -3
- package/src/domain/__tests__/CallSession.test.ts +10 -11
- package/src/domain/__tests__/Contact.test.ts +2 -4
- package/src/domain/__tests__/IndirectTransfer.test.ts +6 -7
- package/src/domain/__tests__/Profile.test.ts +3 -4
- package/src/domain/__tests__/Room.test.ts +27 -51
- package/src/domain/__tests__/Session.test.ts +27 -28
- package/src/domain/__tests__/SipLine.test.ts +4 -5
- package/src/domain/types.ts +64 -11
- package/src/index.ts +51 -111
- package/src/lib/WazoSessionDescriptionHandler.ts +24 -30
- package/src/service/CallApi.ts +3 -3
- package/src/service/IssueReporter.ts +3 -5
- package/src/service/__tests__/IssueReporter.test.ts +1 -2
- package/src/simple/Auth.ts +1 -41
- package/src/simple/Phone.ts +9 -116
- package/src/simple/Websocket.ts +4 -20
- package/src/simple/index.ts +8 -7
- package/src/simple/room/Participant.ts +4 -3
- package/src/simple/room/Room.ts +44 -36
- package/src/simple/room/SipRoom.ts +4 -4
- package/src/simple/room/Stream.ts +2 -3
- package/src/simple/room/__tests__/Participant.test.ts +2 -4
- package/src/simple/room/__tests__/RemoteParticipant.test.ts +4 -3
- package/src/types/wazo.d.ts +1 -0
- package/src/utils/PhoneNumberUtil.ts +1 -1
- package/src/utils/__tests__/PhoneNumberUtil.test.ts +0 -6
- package/src/utils/__tests__/api-requester.test.ts +3 -4
- package/src/utils/__tests__/sdp.test.ts +16 -30
- package/src/utils/api-requester.ts +1 -4
- package/src/utils/sdp.ts +38 -17
- package/src/web-rtc-client.ts +196 -234
- package/src/websocket-client.ts +2 -3
- package/lib/.DS_Store +0 -0
|
@@ -74,7 +74,6 @@ client.setToken(token);
|
|
|
74
74
|
describe('With correct API results', () => {
|
|
75
75
|
beforeEach(() => {
|
|
76
76
|
jest.resetModules();
|
|
77
|
-
// @ts-expect-error
|
|
78
77
|
global.fetch = jest.fn(() => Promise.resolve(mockedJson));
|
|
79
78
|
});
|
|
80
79
|
describe('logIn test', () => {
|
|
@@ -87,13 +86,11 @@ describe('With correct API results', () => {
|
|
|
87
86
|
Authorization: `Basic ${Base64.encode(`${username}:${password}`)}`,
|
|
88
87
|
'Content-Type': 'application/json',
|
|
89
88
|
};
|
|
90
|
-
// @ts-expect-error
|
|
91
89
|
const result = await client.auth.logIn({
|
|
92
90
|
username,
|
|
93
91
|
password,
|
|
94
92
|
});
|
|
95
93
|
expect(result).toBeInstanceOf(Session);
|
|
96
|
-
// @ts-expect-error
|
|
97
94
|
expect(result.token).toBe(1);
|
|
98
95
|
expect(global.fetch).toBeCalledWith(`https://${server}/api/auth/${authVersion}/token`, {
|
|
99
96
|
method: 'post',
|
|
@@ -107,7 +104,6 @@ describe('With correct API results', () => {
|
|
|
107
104
|
describe('logOut test', () => {
|
|
108
105
|
it('should delete the specified token', async () => {
|
|
109
106
|
const oldToken = 123;
|
|
110
|
-
// @ts-expect-error
|
|
111
107
|
await client.auth.logOut(oldToken);
|
|
112
108
|
expect(global.fetch).toBeCalledWith(`https://${server}/api/auth/${authVersion}/token/${oldToken}`, {
|
|
113
109
|
method: 'delete',
|
|
@@ -122,7 +118,6 @@ describe('With correct API results', () => {
|
|
|
122
118
|
describe('With unAuthorized API results', () => {
|
|
123
119
|
beforeEach(() => {
|
|
124
120
|
jest.resetModules();
|
|
125
|
-
// @ts-expect-error
|
|
126
121
|
global.fetch = jest.fn(() => Promise.resolve(mockedUnAuthorized));
|
|
127
122
|
});
|
|
128
123
|
describe('checkLogin test', () => {
|
|
@@ -143,7 +138,6 @@ describe('With unAuthorized API results', () => {
|
|
|
143
138
|
describe('With not found API results', () => {
|
|
144
139
|
beforeEach(() => {
|
|
145
140
|
jest.resetModules();
|
|
146
|
-
// @ts-expect-error
|
|
147
141
|
global.fetch = jest.fn(() => Promise.resolve(mockedNotFound));
|
|
148
142
|
});
|
|
149
143
|
describe('fetchVoicemail test', () => {
|
|
@@ -176,13 +170,11 @@ describe('With not found API results', () => {
|
|
|
176
170
|
describe('With erroneous text API results', () => {
|
|
177
171
|
beforeEach(() => {
|
|
178
172
|
jest.resetModules();
|
|
179
|
-
// @ts-expect-error
|
|
180
173
|
global.fetch = jest.fn(() => Promise.resolve(mockedTextError));
|
|
181
174
|
});
|
|
182
175
|
it('throw an exception when the response is >= 500', async () => {
|
|
183
176
|
let error = null;
|
|
184
177
|
try {
|
|
185
|
-
// @ts-expect-error
|
|
186
178
|
await client.auth.logIn({
|
|
187
179
|
username,
|
|
188
180
|
password,
|
|
@@ -200,13 +192,11 @@ describe('With erroneous text API results', () => {
|
|
|
200
192
|
describe('With erroneous json API results', () => {
|
|
201
193
|
beforeEach(() => {
|
|
202
194
|
jest.resetModules();
|
|
203
|
-
// @ts-expect-error
|
|
204
195
|
global.fetch = jest.fn(() => Promise.resolve(mockedJsonError));
|
|
205
196
|
});
|
|
206
197
|
it('throw an exception when the response is >= 500', async () => {
|
|
207
198
|
let error = null;
|
|
208
199
|
try {
|
|
209
|
-
// @ts-expect-error
|
|
210
200
|
await client.auth.logIn({
|
|
211
201
|
username,
|
|
212
202
|
password,
|
|
@@ -3,15 +3,12 @@ jest.mock('sip.js/lib/platform/web/transport');
|
|
|
3
3
|
jest.mock('sip.js/lib/api/user-agent', () => ({
|
|
4
4
|
start: () => { },
|
|
5
5
|
UserAgent: class UserAgent {
|
|
6
|
-
|
|
7
|
-
static makeURI = () => { };
|
|
8
|
-
// @ts-ignore
|
|
6
|
+
static makeURI = () => null;
|
|
9
7
|
start = () => { };
|
|
10
8
|
transport = {};
|
|
11
9
|
},
|
|
12
10
|
}));
|
|
13
|
-
|
|
14
|
-
const client = new WebRTCClient({});
|
|
11
|
+
const client = new WebRTCClient({}, null, undefined);
|
|
15
12
|
describe('WebRTC client', () => {
|
|
16
13
|
it('should compute muted/unmuted state', async () => {
|
|
17
14
|
const mutedSession = {
|
|
@@ -60,13 +57,9 @@ describe('WebRTC client', () => {
|
|
|
60
57
|
},
|
|
61
58
|
},
|
|
62
59
|
};
|
|
63
|
-
// @ts-expect-error
|
|
64
60
|
expect(client.isAudioMuted(mutedSession)).toBeTruthy();
|
|
65
|
-
// @ts-expect-error
|
|
66
61
|
expect(client.isAudioMuted(oldKindMuted)).toBeTruthy();
|
|
67
|
-
// @ts-expect-error
|
|
68
62
|
expect(client.isAudioMuted(unMutedSession)).toBeFalsy();
|
|
69
|
-
// @ts-expect-error
|
|
70
63
|
expect(client.isAudioMuted(oldKindUnmuted)).toBeFalsy();
|
|
71
64
|
});
|
|
72
65
|
});
|
|
@@ -126,26 +119,20 @@ describe('changeAudioInputDevice', () => {
|
|
|
126
119
|
},
|
|
127
120
|
});
|
|
128
121
|
it('should change the audio input track if the provided id is different', async () => {
|
|
129
|
-
// @ts-expect-error
|
|
130
122
|
client.setMediaConstraints(constraints);
|
|
131
123
|
expect(client.getAudioDeviceId()).toBe(defaultId);
|
|
132
|
-
// @ts-expect-error
|
|
133
124
|
const result = await client.changeAudioInputDevice(deviceId, session);
|
|
134
125
|
expect(result).toBeTruthy();
|
|
135
126
|
});
|
|
136
127
|
it('should NOT change the audio input track if the provided id is the same', async () => {
|
|
137
|
-
// @ts-expect-error
|
|
138
128
|
client.setMediaConstraints(constraints);
|
|
139
129
|
expect(client.getAudioDeviceId()).toBe(defaultId);
|
|
140
|
-
// @ts-expect-error
|
|
141
130
|
const result = await client.changeAudioInputDevice(defaultId, session);
|
|
142
131
|
expect(result).toBeFalsy();
|
|
143
132
|
});
|
|
144
133
|
it('should change the audio input track if the provided id is the same and force param is TRUE', async () => {
|
|
145
|
-
// @ts-expect-error
|
|
146
134
|
client.setMediaConstraints(constraints);
|
|
147
135
|
expect(client.getAudioDeviceId()).toBe(defaultId);
|
|
148
|
-
// @ts-expect-error
|
|
149
136
|
const result = await client.changeAudioInputDevice(defaultId, session, true);
|
|
150
137
|
expect(result).toBeTruthy();
|
|
151
138
|
});
|
package/esm/api/amid.js
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
export default ((client, baseUrl) => ({
|
|
2
2
|
action: (action, args = {}) => client.post(`${baseUrl}/action/${action}`, args),
|
|
3
3
|
getAors: async (endpoint) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
try {
|
|
5
|
+
const rawEvents = await client.post(`${baseUrl}/action/PJSIPShowEndpoint`, {
|
|
6
|
+
Endpoint: endpoint,
|
|
7
|
+
}) || [];
|
|
8
|
+
if (!rawEvents) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
return rawEvents.filter((event) => event.Event === 'ContactStatusDetail');
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
8
16
|
},
|
|
9
17
|
}));
|
package/esm/api/chatd.js
CHANGED
|
@@ -24,7 +24,6 @@ export default ((client, baseUrl) => ({
|
|
|
24
24
|
if (uuids.length > MAX_PRESENCE_FETCHED) {
|
|
25
25
|
const requests = uuids.reduce((acc, _, i) => {
|
|
26
26
|
if (i % MAX_PRESENCE_FETCHED === 0) {
|
|
27
|
-
// @ts-ignore
|
|
28
27
|
acc.push(this.getMultipleLineState(uuids.slice(i, i + MAX_PRESENCE_FETCHED)));
|
|
29
28
|
}
|
|
30
29
|
return acc;
|
package/esm/api/dird.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { jsonToGraphQLQuery } from 'json-to-graphql-query/lib/jsonToGraphQLQuery';
|
|
2
2
|
import ApiRequester from '../utils/api-requester';
|
|
3
|
-
import Contact from '../
|
|
3
|
+
import { Contact } from '../index';
|
|
4
4
|
const getContactPayload = (contact) => ({
|
|
5
5
|
email: contact.email,
|
|
6
|
-
// @ts-ignore
|
|
7
6
|
firstname: contact.firstName ? contact.firstName : '',
|
|
8
|
-
// @ts-ignore
|
|
9
7
|
lastname: contact.lastName ? contact.lastName : '',
|
|
10
|
-
// @ts-ignore
|
|
11
8
|
number: contact.phoneNumber ? contact.phoneNumber : '',
|
|
12
9
|
entreprise: contact.entreprise ? contact.entreprise : '',
|
|
13
10
|
birthday: contact.birthday ? contact.birthday : '',
|
|
@@ -41,7 +38,7 @@ export default ((client, baseUrl) => ({
|
|
|
41
38
|
}),
|
|
42
39
|
fetchOffice365Contacts: (source, queryParams = null) => {
|
|
43
40
|
if (!source) {
|
|
44
|
-
return
|
|
41
|
+
return Promise.resolve([]);
|
|
45
42
|
}
|
|
46
43
|
return client.get(`${baseUrl}/backends/office365/sources/${source.uuid}/contacts`, queryParams).then((response) => Contact.parseManyOffice365(response.items, source));
|
|
47
44
|
},
|
|
@@ -51,7 +48,7 @@ export default ((client, baseUrl) => ({
|
|
|
51
48
|
// Can be used with `queryParams = { uuid: uuid1, uuid2 }` to fetch multiple contacts
|
|
52
49
|
fetchWazoContacts: (source, queryParams = null) => {
|
|
53
50
|
if (!source) {
|
|
54
|
-
return
|
|
51
|
+
return Promise.resolve([]);
|
|
55
52
|
}
|
|
56
53
|
return client.get(`${baseUrl}/backends/wazo/sources/${source.uuid}/contacts`, queryParams).then((response) => Contact.parseManyWazo(response.items, source));
|
|
57
54
|
},
|
|
@@ -60,7 +57,7 @@ export default ((client, baseUrl) => ({
|
|
|
60
57
|
}),
|
|
61
58
|
fetchGoogleContacts: (source, queryParams = null) => {
|
|
62
59
|
if (!source) {
|
|
63
|
-
return
|
|
60
|
+
return Promise.resolve([]);
|
|
64
61
|
}
|
|
65
62
|
return client.get(`${baseUrl}/backends/google/sources/${source.uuid}/contacts`, queryParams).then((response) => Contact.parseManyGoogle(response.items, source));
|
|
66
63
|
},
|
|
@@ -68,15 +65,15 @@ export default ((client, baseUrl) => ({
|
|
|
68
65
|
backend: 'conference',
|
|
69
66
|
}),
|
|
70
67
|
fetchSourcesFor: (context, backend) => client.get(`${baseUrl}/directories/${context}/sources`, { backend }),
|
|
71
|
-
fetchPhonebookContacts: (source, params
|
|
68
|
+
fetchPhonebookContacts: (source, params) => {
|
|
72
69
|
if (!source) {
|
|
73
|
-
return
|
|
70
|
+
return Promise.resolve({ items: [], total: 0 });
|
|
74
71
|
}
|
|
75
72
|
return client.get(`${baseUrl}/backends/phonebook/sources/${source.uuid}/contacts`, params);
|
|
76
73
|
},
|
|
77
74
|
fetchConferenceContacts: (source) => {
|
|
78
75
|
if (!source) {
|
|
79
|
-
return
|
|
76
|
+
return Promise.resolve([]);
|
|
80
77
|
}
|
|
81
78
|
return client.get(`${baseUrl}/backends/conference/sources/${source.uuid}/contacts`).then((response) => Contact.parseManyConference(response.items, source));
|
|
82
79
|
},
|
|
@@ -35,7 +35,7 @@ export default {
|
|
|
35
35
|
...config.iceServers, };
|
|
36
36
|
}
|
|
37
37
|
if (externalAppConfig && externalAppConfig.turn_servers) {
|
|
38
|
-
config.iceServers = [...JSON.parse(externalAppConfig.turn_servers), ...config.iceServers];
|
|
38
|
+
config.iceServers = [...JSON.parse(externalAppConfig.turn_servers), ...(config.iceServers || [])];
|
|
39
39
|
// Force to use TURN when defined in config
|
|
40
40
|
config.iceTransportPolicy = 'relay';
|
|
41
41
|
}
|
|
@@ -55,8 +55,7 @@ export default {
|
|
|
55
55
|
return reject(new Error('No `srflx` or `relay` found in candidate. Please consider using a TURN server.'));
|
|
56
56
|
}
|
|
57
57
|
if (ips.every(checkIsIPV4)) {
|
|
58
|
-
|
|
59
|
-
resolve();
|
|
58
|
+
resolve(null);
|
|
60
59
|
}
|
|
61
60
|
else {
|
|
62
61
|
const nonIPV4 = ips.find(ip => !checkIsIPV4(ip));
|
|
@@ -36,16 +36,19 @@ export default {
|
|
|
36
36
|
};
|
|
37
37
|
timeout = setTimeout(onEnded, timeoutDuration);
|
|
38
38
|
pc.createDataChannel('wazo-check-nat');
|
|
39
|
-
pc.onicecandidate = e => {
|
|
39
|
+
pc.onicecandidate = (e) => {
|
|
40
40
|
nbCandidates++;
|
|
41
41
|
if (e.candidate) {
|
|
42
42
|
rawCandidates.push(e.candidate.candidate);
|
|
43
43
|
}
|
|
44
44
|
if (e.candidate && e.candidate.candidate.indexOf('srflx') !== -1) {
|
|
45
45
|
const cand = parseCandidate(e.candidate.candidate);
|
|
46
|
-
if (
|
|
47
|
-
candidates[cand.relatedPort]
|
|
48
|
-
|
|
46
|
+
if (cand.relatedPort) {
|
|
47
|
+
if (!candidates[cand.relatedPort]) {
|
|
48
|
+
candidates[cand.relatedPort] = [];
|
|
49
|
+
}
|
|
50
|
+
candidates[cand.relatedPort].push(cand.port);
|
|
51
|
+
}
|
|
49
52
|
}
|
|
50
53
|
else if (!e.candidate) {
|
|
51
54
|
onEnded();
|
|
@@ -25,7 +25,7 @@ export default class AdHocAPIConference {
|
|
|
25
25
|
}
|
|
26
26
|
async start() {
|
|
27
27
|
this.started = true;
|
|
28
|
-
// @ts-ignore
|
|
28
|
+
// @ts-ignore: date / number
|
|
29
29
|
this.answerTime = Object.values(this.participants).length ? Object.values(this.participants)[0].answerTime : null;
|
|
30
30
|
const participantIds = Object.keys(this.participants);
|
|
31
31
|
const conference = await getApiClient().calld.createAdHocConference(this.host.callId, participantIds);
|
package/esm/domain/CallLog.js
CHANGED
|
@@ -54,7 +54,7 @@ export default class CallLog {
|
|
|
54
54
|
static parseNew(plain, session) {
|
|
55
55
|
const callLog = CallLog.parse(plain);
|
|
56
56
|
// @TODO: FIXME add verification declined vs missed call
|
|
57
|
-
callLog.newMissedCall = session && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
|
|
57
|
+
callLog.newMissedCall = session && session.hasExtension((plain.requested_extension || plain.destination_extension)) && !plain.answered;
|
|
58
58
|
return callLog;
|
|
59
59
|
}
|
|
60
60
|
static newFrom(profile) {
|
package/esm/domain/Contact.js
CHANGED
|
@@ -10,6 +10,7 @@ export const BACKEND = {
|
|
|
10
10
|
};
|
|
11
11
|
const SOURCE_MOBILE = 'mobile';
|
|
12
12
|
export default class Contact {
|
|
13
|
+
static BACKEND = BACKEND;
|
|
13
14
|
type;
|
|
14
15
|
id;
|
|
15
16
|
uuid;
|
|
@@ -404,7 +405,7 @@ export default class Contact {
|
|
|
404
405
|
}
|
|
405
406
|
merge(old) {
|
|
406
407
|
Object.keys(old).filter(key => key !== 'lineState').forEach(key => {
|
|
407
|
-
// @ts-ignore
|
|
408
|
+
// @ts-ignore: keys
|
|
408
409
|
this[key] = old[key] || this[key];
|
|
409
410
|
});
|
|
410
411
|
if (old.lineState) {
|
|
@@ -5,6 +5,12 @@ export const POST_PROCESSING = 'post_processing';
|
|
|
5
5
|
export const POST_PROCESSED_SUCCESS = 'post_processed_success';
|
|
6
6
|
export const POST_PROCESSED_ERROR = 'post_processed_error';
|
|
7
7
|
export default class MeetingAuthorization {
|
|
8
|
+
static PENDING = PENDING;
|
|
9
|
+
static ACCEPTED = ACCEPTED;
|
|
10
|
+
static REJECTED = REJECTED;
|
|
11
|
+
static POST_PROCESSING = POST_PROCESSING;
|
|
12
|
+
static POST_PROCESSED_SUCCESS = POST_PROCESSED_SUCCESS;
|
|
13
|
+
static POST_PROCESSED_ERROR = POST_PROCESSED_ERROR;
|
|
8
14
|
meetingUuid;
|
|
9
15
|
uuid;
|
|
10
16
|
userUuid;
|
|
@@ -11,6 +11,7 @@ export default class CTIPhone extends Emitter {
|
|
|
11
11
|
isMobile;
|
|
12
12
|
callbackAllLines;
|
|
13
13
|
currentCall;
|
|
14
|
+
client = null;
|
|
14
15
|
constructor(session, isMobile = false, callbackAllLines = false) {
|
|
15
16
|
super();
|
|
16
17
|
logger.info('CTI Phone created');
|
|
@@ -283,4 +284,5 @@ export default class CTIPhone extends Emitter {
|
|
|
283
284
|
}
|
|
284
285
|
useLocalVideoElement() { }
|
|
285
286
|
setMediaConstraints() { }
|
|
287
|
+
register() { return Promise.resolve(null); }
|
|
286
288
|
}
|
|
@@ -243,7 +243,6 @@ export default class WebRTCPhone extends Emitter {
|
|
|
243
243
|
const shouldScreenShare = constraints && !!constraints.screen;
|
|
244
244
|
const desktop = constraints && constraints.desktop;
|
|
245
245
|
const options = sipSession.sessionDescriptionHandlerOptionsReInvite;
|
|
246
|
-
// @ts-ignore
|
|
247
246
|
const wasAudioOnly = options?.audioOnly;
|
|
248
247
|
const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
|
|
249
248
|
if (callSession) {
|
|
@@ -340,9 +339,12 @@ export default class WebRTCPhone extends Emitter {
|
|
|
340
339
|
return;
|
|
341
340
|
}
|
|
342
341
|
// Video events
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
peerConnection
|
|
342
|
+
const sdh = sipSession.sessionDescriptionHandler;
|
|
343
|
+
const peerConnection = sdh.peerConnection;
|
|
344
|
+
if (!peerConnection) {
|
|
345
|
+
logger.info('null peer connection');
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
346
348
|
peerConnection.ontrack = (rawEvent) => {
|
|
347
349
|
const event = rawEvent;
|
|
348
350
|
const [stream] = event.streams;
|
|
@@ -477,6 +479,13 @@ export default class WebRTCPhone extends Emitter {
|
|
|
477
479
|
cameraEnabled,
|
|
478
480
|
});
|
|
479
481
|
const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
|
|
482
|
+
if (this.currentSipSession && !this.isCurrentCallSipSession(callSession)) {
|
|
483
|
+
logger.info('WebRTC phone - on call accepted with another ongoing call, holding it', {
|
|
484
|
+
sipId: sipSession.id,
|
|
485
|
+
cameraEnabled,
|
|
486
|
+
});
|
|
487
|
+
this.holdSipSession(this.currentSipSession, this.currentCallSession, true);
|
|
488
|
+
}
|
|
480
489
|
this.currentSipSession = sipSession;
|
|
481
490
|
this.currentCallSession = callSession;
|
|
482
491
|
this.eventEmitter.emit(ON_TERMINATE_SOUND, callSession, 'call accepted');
|
|
@@ -593,7 +602,7 @@ export default class WebRTCPhone extends Emitter {
|
|
|
593
602
|
if (callSession.getId() in this.ignoredSessions) {
|
|
594
603
|
return false;
|
|
595
604
|
}
|
|
596
|
-
// @ts-ignore
|
|
605
|
+
// @ts-ignore: does not exist
|
|
597
606
|
if (!sipSession.isCanceled) {
|
|
598
607
|
setTimeout(() => {
|
|
599
608
|
this.eventEmitter.emit(ON_PLAY_HANGUP_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, callSession);
|
|
@@ -619,9 +628,8 @@ export default class WebRTCPhone extends Emitter {
|
|
|
619
628
|
if (!sipSession) {
|
|
620
629
|
return false;
|
|
621
630
|
}
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
peerConnection, } = sipSession.sessionDescriptionHandler;
|
|
631
|
+
const sdh = sipSession.sessionDescriptionHandler;
|
|
632
|
+
const peerConnection = sdh.peerConnection;
|
|
625
633
|
const remoteStream = peerConnection.getRemoteStreams().find((stream) => !!stream.getVideoTracks().length);
|
|
626
634
|
return remoteStream && remoteStream.getVideoTracks().some(track => !track.muted);
|
|
627
635
|
}
|
|
@@ -981,9 +989,9 @@ export default class WebRTCPhone extends Emitter {
|
|
|
981
989
|
this.currentCallSession = callSession;
|
|
982
990
|
this.eventEmitter.emit(ON_CALL_OUTGOING, callSession);
|
|
983
991
|
// If an invite promise exists, catch exceptions on it to trigger error like OverConstraintsError.
|
|
984
|
-
// @ts-ignore
|
|
992
|
+
// @ts-ignore: does not exist
|
|
985
993
|
if (sipSession.invitePromise) {
|
|
986
|
-
// @ts-ignore
|
|
994
|
+
// @ts-ignore: does not exist
|
|
987
995
|
sipSession.invitePromise.catch(error => {
|
|
988
996
|
this.eventEmitter.emit(ON_CALL_ERROR, error, callSession);
|
|
989
997
|
});
|
|
@@ -1063,12 +1071,12 @@ export default class WebRTCPhone extends Emitter {
|
|
|
1063
1071
|
return sipSession ? this.client.stopNetworkMonitoring(sipSession) : null;
|
|
1064
1072
|
}
|
|
1065
1073
|
forceCancel(sipSession) {
|
|
1066
|
-
// @ts-ignore
|
|
1074
|
+
// @ts-ignore: private
|
|
1067
1075
|
if (!sipSession || !sipSession.outgoingInviteRequest) {
|
|
1068
1076
|
return;
|
|
1069
1077
|
}
|
|
1070
1078
|
try {
|
|
1071
|
-
// @ts-ignore
|
|
1079
|
+
// @ts-ignore: private
|
|
1072
1080
|
sipSession.outgoingInviteRequest.cancel();
|
|
1073
1081
|
}
|
|
1074
1082
|
catch (e) {
|
|
@@ -1282,7 +1290,6 @@ export default class WebRTCPhone extends Emitter {
|
|
|
1282
1290
|
// send a reinvite to renegociate ICE with new IP
|
|
1283
1291
|
if (this.shouldSendReinvite && this.currentSipSession && this.currentSipSession.state === SessionState.Established) {
|
|
1284
1292
|
this.shouldSendReinvite = false;
|
|
1285
|
-
// @ts-ignore
|
|
1286
1293
|
const pc = this.currentSipSession?.sessionDescriptionHandler?.peerConnection;
|
|
1287
1294
|
const isConference = pc ? pc.sfu : false;
|
|
1288
1295
|
const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
|
|
@@ -1365,14 +1372,12 @@ export default class WebRTCPhone extends Emitter {
|
|
|
1365
1372
|
}
|
|
1366
1373
|
}
|
|
1367
1374
|
_onMessage(message) {
|
|
1368
|
-
// @ts-ignore
|
|
1369
1375
|
if (!message || message.method !== 'MESSAGE') {
|
|
1370
1376
|
return;
|
|
1371
1377
|
}
|
|
1372
1378
|
let body;
|
|
1373
1379
|
try {
|
|
1374
|
-
|
|
1375
|
-
body = JSON.parse(message.body);
|
|
1380
|
+
body = JSON.parse(message.body || '');
|
|
1376
1381
|
}
|
|
1377
1382
|
catch (e) {
|
|
1378
1383
|
return;
|
|
@@ -1433,7 +1438,7 @@ export default class WebRTCPhone extends Emitter {
|
|
|
1433
1438
|
_createCallSession(sipSession, fromSession, extra = {}) {
|
|
1434
1439
|
// eslint-disable-next-line
|
|
1435
1440
|
const identity = sipSession ? sipSession.remoteIdentity || sipSession.assertedIdentity : null;
|
|
1436
|
-
// @ts-ignore
|
|
1441
|
+
// @ts-ignore: private
|
|
1437
1442
|
const number = identity ? identity.uri._normal.user : null;
|
|
1438
1443
|
const { state, } = sipSession || {};
|
|
1439
1444
|
const sessionId = this.getSipSessionId(sipSession);
|
|
@@ -1443,7 +1448,7 @@ export default class WebRTCPhone extends Emitter {
|
|
|
1443
1448
|
sipCallId: sessionId,
|
|
1444
1449
|
sipStatus: state,
|
|
1445
1450
|
displayName: identity ? identity.displayName || number : number,
|
|
1446
|
-
// @ts-ignore:
|
|
1451
|
+
// @ts-ignore: date / number
|
|
1447
1452
|
startTime: fromSession ? fromSession.startTime : new Date(),
|
|
1448
1453
|
creationTime: fromSession ? fromSession.creationTime : null,
|
|
1449
1454
|
answerTime: fromSession ? fromSession.answerTime : null,
|
package/esm/domain/Session.js
CHANGED
|
@@ -28,7 +28,7 @@ export default class Session {
|
|
|
28
28
|
if (token) {
|
|
29
29
|
const isValid = jws.JWS.verifyJWT(token, swarmKey, {
|
|
30
30
|
alg: ['RS256'],
|
|
31
|
-
// @ts-ignore
|
|
31
|
+
// @ts-ignore: date / number
|
|
32
32
|
verifyAt: new Date(),
|
|
33
33
|
});
|
|
34
34
|
if (isValid) {
|
|
@@ -133,7 +133,7 @@ export default class Session {
|
|
|
133
133
|
return line && Array.isArray(line.extensions) && line.extensions.length > 0 ? line.extensions[0].context : 'default';
|
|
134
134
|
}
|
|
135
135
|
hasEngineVersionGte(version) {
|
|
136
|
-
return this.engineVersion && compareVersions(String(this.engineVersion), String(version)) >= 0;
|
|
136
|
+
return !!this.engineVersion && compareVersions(String(this.engineVersion), String(version)) >= 0;
|
|
137
137
|
}
|
|
138
138
|
primaryNumber() {
|
|
139
139
|
const line = this.primaryLine();
|
|
@@ -26,14 +26,12 @@ Object.keys(fieldMap).forEach((field) => {
|
|
|
26
26
|
});
|
|
27
27
|
describe('Call Center Agent domain', () => {
|
|
28
28
|
it('should keep its values', () => {
|
|
29
|
-
// @ts-expect-error
|
|
30
29
|
const agent = new Agent(formatted);
|
|
31
30
|
expect(agent).toBeInstanceOf(Agent);
|
|
32
31
|
Object.keys(fieldMap).map(key => expect(agent[key]).toBe(formatted[key]));
|
|
33
32
|
});
|
|
34
33
|
it('can parse a plain call center agent to domain', () => {
|
|
35
34
|
const agent = Agent.parse(plain);
|
|
36
|
-
// @ts-expect-error
|
|
37
35
|
expect(agent).toEqual(new Agent(formatted));
|
|
38
36
|
});
|
|
39
37
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import CallSession from '../CallSession';
|
|
3
|
-
const stringify = cs => JSON.parse(JSON.stringify(cs));
|
|
2
|
+
const stringify = (cs) => JSON.parse(JSON.stringify(cs));
|
|
4
3
|
describe('CallSession domain', () => {
|
|
5
4
|
it('should update from another CallSession without data loss', () => {
|
|
6
5
|
const callSession = new CallSession({
|
|
@@ -303,13 +303,11 @@ describe('Contact domain', () => {
|
|
|
303
303
|
const noBirthdayContact = new Contact({
|
|
304
304
|
uuid: 'uuid-12345',
|
|
305
305
|
lastActivity: 'yesterday',
|
|
306
|
-
|
|
307
|
-
birthday: null,
|
|
306
|
+
birthday: undefined,
|
|
308
307
|
});
|
|
309
308
|
const noLastActivityContact = new Contact({
|
|
310
309
|
uuid: 'uuid-12345',
|
|
311
|
-
|
|
312
|
-
lastActivity: null,
|
|
310
|
+
lastActivity: undefined,
|
|
313
311
|
birthday: 'tomorrow',
|
|
314
312
|
});
|
|
315
313
|
const result = noBirthdayContact.merge(noLastActivityContact);
|