@aiqa/sdk 0.0.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/.vscode/launch.json +20 -0
- package/README.md +730 -0
- package/build/sdk.js +37 -0
- package/index.js +3 -0
- package/jest.config.js +7 -0
- package/package.json +24 -0
- package/src/README.md +729 -0
- package/src/config.ts +29 -0
- package/src/enum.ts +16 -0
- package/src/index.ts +428 -0
- package/src/logger.ts +37 -0
- package/src/service/index.ts +139 -0
- package/src/types.ts +164 -0
- package/tests/index.test.ts +534 -0
- package/tests/server.ts +22 -0
- package/tsconfig.json +11 -0
- package/win_create_ssh.sh +50 -0
package/src/config.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const MINIMAL_SUPPORT_VERSION = '1.0.0';
|
|
2
|
+
|
|
3
|
+
export interface SDKConfig {
|
|
4
|
+
url?: string;
|
|
5
|
+
jwtToken?: string;
|
|
6
|
+
path?: string;
|
|
7
|
+
enableLogging?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let config: SDKConfig = {
|
|
11
|
+
url: 'ws://localhost:3025',
|
|
12
|
+
path: '/ws',
|
|
13
|
+
enableLogging: true
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function setConfig(newConfig: SDKConfig) {
|
|
17
|
+
config = { ...config, ...newConfig };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getConfig(): SDKConfig {
|
|
21
|
+
return config;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function isLoggingEnabled(): boolean {
|
|
25
|
+
return config.enableLogging !== false; // Default to true if not explicitly set to false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default config;
|
|
29
|
+
|
package/src/enum.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export enum Methods {
|
|
2
|
+
INIT_AUDIO_RECORDER = "INIT_AUDIO_RECORDER",
|
|
3
|
+
IS_ALIVE = "IS_ALIVE",
|
|
4
|
+
|
|
5
|
+
CREATE_APPLICATION = "CREATE_APPLICATION",
|
|
6
|
+
GET_APPLICATION = "GET_APPLICATION",
|
|
7
|
+
UPDATE_APPLICATION = "UPDATE_APPLICATION",
|
|
8
|
+
SET_ACTIVE_APPLICATION = "SET_ACTIVE_APPLICATION",
|
|
9
|
+
GET_ACTIVE_APPLICATION = "GET_ACTIVE_APPLICATION",
|
|
10
|
+
|
|
11
|
+
START_RECORDING = "START_RECORDING",
|
|
12
|
+
STOP_RECORDING = "STOP_RECORDING",
|
|
13
|
+
IS_RECORDING = "IS_RECORDING",
|
|
14
|
+
|
|
15
|
+
ADD_FACT = "ADD_FACT"
|
|
16
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { Methods } from "./enum";
|
|
2
|
+
import service from "./service";
|
|
3
|
+
import { TApplication, TApplicationPayload, TApplicationFactPayload, TApplicationFact, TResponse, TFactIsMatched, TResult } from "./types";
|
|
4
|
+
import { setConfig, SDKConfig } from "./config";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const AiQaSdk = class {
|
|
8
|
+
events: {};
|
|
9
|
+
|
|
10
|
+
constructor(config?: SDKConfig) {
|
|
11
|
+
this.events = {};
|
|
12
|
+
|
|
13
|
+
if (config) {
|
|
14
|
+
setConfig(config);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Проверяем есть ли соединение с ПайтонАпп и если нет, то мы кидаем ошибку. Установите или запустите приложение
|
|
18
|
+
// Постоянно должно стучатся и постоянно пытаться подключится
|
|
19
|
+
// После подключения проверить версию и кинуть ошибку если не совпадает версия
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
configure(config: SDKConfig) {
|
|
23
|
+
setConfig(config);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
on(name: string, callback: (...args: any[]) => any) {
|
|
27
|
+
this.events[name] = callback;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
off(name: string) {
|
|
31
|
+
delete this.events[name];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
connect() {
|
|
35
|
+
service.connect(this.events);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
disconnect() {
|
|
39
|
+
service.disconnect()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// Is Alive
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
isAlive(cb: ({isAlive, error}: TResponse) => void) {
|
|
47
|
+
try {
|
|
48
|
+
const result = service.getStatus();
|
|
49
|
+
cb({isAlive: result})
|
|
50
|
+
}
|
|
51
|
+
catch(error) {
|
|
52
|
+
cb({error})
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
async isAliveAsync(): Promise<boolean> {
|
|
57
|
+
return new Promise(async (resolve, reject) => {
|
|
58
|
+
try {
|
|
59
|
+
const result = service.getStatus();
|
|
60
|
+
resolve(result);
|
|
61
|
+
}
|
|
62
|
+
catch(e) {
|
|
63
|
+
reject(e)
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/// Get Application ??????
|
|
69
|
+
|
|
70
|
+
getApplication(id: string, cb:({application, error}: TResponse) => void) {
|
|
71
|
+
service.sendMessage(Methods.GET_APPLICATION, {id})
|
|
72
|
+
.then((application: TApplication) => {
|
|
73
|
+
cb({application})
|
|
74
|
+
})
|
|
75
|
+
.catch(({error}) => {
|
|
76
|
+
cb({error})
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async getApplicationAsync(id: string): Promise<TApplication> {
|
|
81
|
+
return new Promise(async (resolve, reject) => {
|
|
82
|
+
try {
|
|
83
|
+
const application = await service.sendMessage(Methods.GET_APPLICATION, {id});
|
|
84
|
+
//@ts-ignore
|
|
85
|
+
resolve(application)
|
|
86
|
+
}
|
|
87
|
+
catch(e) {
|
|
88
|
+
reject(e)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// Update Application
|
|
94
|
+
|
|
95
|
+
updateApplication(id: string, referenceId: string, cb: ({application, error}: TResponse) => void) {
|
|
96
|
+
service.sendMessage(Methods.UPDATE_APPLICATION, {id, referenceId})
|
|
97
|
+
.then((application: TApplication) => {
|
|
98
|
+
cb({application})
|
|
99
|
+
})
|
|
100
|
+
.catch(({error}) => {
|
|
101
|
+
cb({error})
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async updateApplicationAsync(id: string, referenceId: string): Promise<TApplication> {
|
|
106
|
+
return new Promise(async (resolve, reject) => {
|
|
107
|
+
try {
|
|
108
|
+
const application = await service.sendMessage(Methods.UPDATE_APPLICATION, {id, referenceId});
|
|
109
|
+
//@ts-ignore
|
|
110
|
+
resolve(application)
|
|
111
|
+
}
|
|
112
|
+
catch(e) {
|
|
113
|
+
reject(e)
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/// Create Application
|
|
119
|
+
|
|
120
|
+
createApplication(data: TApplicationPayload, cb: ({application, error}: TResponse) => void) {
|
|
121
|
+
service.sendMessage(Methods.CREATE_APPLICATION, data)
|
|
122
|
+
.then((application: TApplication) => {
|
|
123
|
+
cb({application})
|
|
124
|
+
})
|
|
125
|
+
.catch(({error}) => {
|
|
126
|
+
cb({error})
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async createApplicationAsync(data: TApplicationPayload): Promise<TApplication> {
|
|
131
|
+
return new Promise(async (resolve, reject) => {
|
|
132
|
+
try {
|
|
133
|
+
const application = await service.sendMessage(Methods.CREATE_APPLICATION, data);
|
|
134
|
+
//@ts-ignore
|
|
135
|
+
resolve(application)
|
|
136
|
+
}
|
|
137
|
+
catch(e) {
|
|
138
|
+
reject(e)
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/// Set Active Application
|
|
144
|
+
|
|
145
|
+
setActiveApplication(applicationId: string, cb: ({applicationIsActive, error}: TResponse) => void) {
|
|
146
|
+
service.sendMessage(Methods.SET_ACTIVE_APPLICATION, {applicationId, active: true})
|
|
147
|
+
.then((result: TResult) => {
|
|
148
|
+
if (!!result.error) {
|
|
149
|
+
cb({error: result.error})
|
|
150
|
+
} else if (typeof result.data === 'boolean') {
|
|
151
|
+
cb({applicationIsActive: result.data})
|
|
152
|
+
} else {
|
|
153
|
+
cb({error: new Error(`Type of response data for ${Methods.SET_ACTIVE_APPLICATION} method is not equal Boolean`)});
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
.catch((error: Error) => {
|
|
157
|
+
cb({error});
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async setActiveApplicationAsync(applicationId: string): Promise<boolean> {
|
|
162
|
+
return new Promise(async (resolve, reject) => { //What return?
|
|
163
|
+
try {
|
|
164
|
+
const result = await service.sendMessage(Methods.SET_ACTIVE_APPLICATION, {applicationId, active: true});
|
|
165
|
+
//@ts-ignore
|
|
166
|
+
if (!!result.error) {
|
|
167
|
+
//@ts-ignore
|
|
168
|
+
reject(result.error)
|
|
169
|
+
//@ts-ignore
|
|
170
|
+
} else if (typeof result.data === 'boolean') {
|
|
171
|
+
//@ts-ignore
|
|
172
|
+
resolve(result.data)
|
|
173
|
+
} else {
|
|
174
|
+
reject(new Error(`Type of response data for ${Methods.SET_ACTIVE_APPLICATION} method is not equal Boolean`));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch(e) {
|
|
178
|
+
reject(e)
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// Get Active Application
|
|
184
|
+
|
|
185
|
+
getActiveApplication(cb: ({application, error}: TResponse) => void) {
|
|
186
|
+
service.sendMessage(Methods.GET_ACTIVE_APPLICATION)
|
|
187
|
+
.then((application: TApplication | null) => {
|
|
188
|
+
cb({application})
|
|
189
|
+
})
|
|
190
|
+
.catch((error: Error) => {
|
|
191
|
+
cb({error});
|
|
192
|
+
})
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async getActiveApplicationAsync(): Promise<TApplication | null> {
|
|
196
|
+
return new Promise(async (resolve, reject) => {
|
|
197
|
+
try {
|
|
198
|
+
const result = await service.sendMessage(Methods.GET_ACTIVE_APPLICATION);
|
|
199
|
+
//@ts-ignore
|
|
200
|
+
resolve(result)
|
|
201
|
+
}
|
|
202
|
+
catch(e) {
|
|
203
|
+
reject(e);
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// Reset Active Application
|
|
209
|
+
//ToDo Reset application is needed applicationId?
|
|
210
|
+
resetActiveApplication(cb: ({applicationIsActive, error}: TResponse) => void) {
|
|
211
|
+
service.sendMessage(Methods.SET_ACTIVE_APPLICATION, {active: false})
|
|
212
|
+
.then((result: TResult) => {
|
|
213
|
+
if (!!result.error) {
|
|
214
|
+
cb({error: result.error})
|
|
215
|
+
} else if (typeof result.data === 'boolean') {
|
|
216
|
+
cb({applicationIsActive: result.data})
|
|
217
|
+
} else {
|
|
218
|
+
cb({error: new Error(`Type of response data for ${Methods.SET_ACTIVE_APPLICATION} method is not equal Boolean`)});
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
.catch((error: Error) => {
|
|
222
|
+
cb({error});
|
|
223
|
+
})
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async resetActiveApplicationAsync(): Promise<boolean> {
|
|
227
|
+
return new Promise(async (resolve, reject) => {
|
|
228
|
+
try {
|
|
229
|
+
const result = await service.sendMessage(Methods.SET_ACTIVE_APPLICATION, {active: false});
|
|
230
|
+
//@ts-ignore
|
|
231
|
+
if (!!result.error) {
|
|
232
|
+
//@ts-ignore
|
|
233
|
+
reject(result.error)
|
|
234
|
+
//@ts-ignore
|
|
235
|
+
} else if (typeof result.data === 'boolean') {
|
|
236
|
+
//@ts-ignore
|
|
237
|
+
resolve(result.data)
|
|
238
|
+
} else {
|
|
239
|
+
reject(new Error(`Type of response data for ${Methods.SET_ACTIVE_APPLICATION} method is not equal Boolean`));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch(e) {
|
|
243
|
+
reject(e);
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/// Add Fact
|
|
249
|
+
|
|
250
|
+
addFact(fact: TApplicationFactPayload, cb: ({factIsMatched, error}: TResponse) => void){
|
|
251
|
+
service.sendMessage(Methods.ADD_FACT, fact)
|
|
252
|
+
.then((result: TFactIsMatched) => {
|
|
253
|
+
cb({factIsMatched: result})
|
|
254
|
+
})
|
|
255
|
+
.catch((error: Error) => {
|
|
256
|
+
cb({error});
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async addFactAsync (fact: TApplicationFactPayload): Promise<TFactIsMatched> {
|
|
261
|
+
return new Promise(async (resolve, reject) => {
|
|
262
|
+
try {
|
|
263
|
+
const result = await service.sendMessage(Methods.ADD_FACT, fact);
|
|
264
|
+
//@ts-ignore
|
|
265
|
+
resolve(result);
|
|
266
|
+
}
|
|
267
|
+
catch(e) {
|
|
268
|
+
reject(e);
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/// Start Recording
|
|
274
|
+
|
|
275
|
+
startRecording(cb: ({recordingIsStarted, error}: TResponse) => void) {
|
|
276
|
+
service.sendMessage(Methods.START_RECORDING)
|
|
277
|
+
.then((result: TResult) => {
|
|
278
|
+
if (typeof result.data === 'boolean') {
|
|
279
|
+
cb({recordingIsStarted: result.data})
|
|
280
|
+
} else {
|
|
281
|
+
cb({error: new Error(`Type of response data for ${Methods.START_RECORDING} method is not equal Boolean`)})
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
.catch((error: Error) => {
|
|
285
|
+
cb({error})
|
|
286
|
+
})
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
async startRecordingAsync(): Promise<boolean> {
|
|
290
|
+
return new Promise(async (resolve, reject) => {
|
|
291
|
+
try {
|
|
292
|
+
const result = await service.sendMessage(Methods.START_RECORDING);
|
|
293
|
+
//@ts-ignore
|
|
294
|
+
if (!!result.error) {
|
|
295
|
+
//@ts-ignore
|
|
296
|
+
reject(result.error)
|
|
297
|
+
//@ts-ignore
|
|
298
|
+
} else if (typeof result.data === 'boolean') {
|
|
299
|
+
//@ts-ignore
|
|
300
|
+
resolve(result.data)
|
|
301
|
+
} else {
|
|
302
|
+
reject(new Error(`Type of response data for ${Methods.START_RECORDING} method is not equal Boolean`))
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch(error) {
|
|
306
|
+
reject(error)
|
|
307
|
+
}
|
|
308
|
+
})
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/// Stop Recording
|
|
312
|
+
|
|
313
|
+
stopRecording(cb: ({recordingIsStopped, error}: TResponse) => void) {
|
|
314
|
+
service.sendMessage(Methods.STOP_RECORDING)
|
|
315
|
+
.then((result: TResult) => {
|
|
316
|
+
if (!!result.error) {
|
|
317
|
+
cb({error: result.error})
|
|
318
|
+
} else if (typeof result.data === 'boolean') {
|
|
319
|
+
cb({recordingIsStopped: result.data})
|
|
320
|
+
} else {
|
|
321
|
+
cb({error: new Error(`Type of response data for ${Methods.STOP_RECORDING} method is not equal Boolean`)})
|
|
322
|
+
}
|
|
323
|
+
})
|
|
324
|
+
.catch((error) => {
|
|
325
|
+
cb({error})
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async stopRecordingAsync(): Promise<boolean> {
|
|
330
|
+
return new Promise(async (resolve, reject) => {
|
|
331
|
+
try {
|
|
332
|
+
const result = await service.sendMessage(Methods.STOP_RECORDING);
|
|
333
|
+
//@ts-ignore
|
|
334
|
+
if (!!result.error) {
|
|
335
|
+
//@ts-ignore
|
|
336
|
+
reject(result.error)
|
|
337
|
+
//@ts-ignore
|
|
338
|
+
} else if (typeof result.data === 'boolean') {
|
|
339
|
+
//@ts-ignore
|
|
340
|
+
resolve(result.data)
|
|
341
|
+
} else {
|
|
342
|
+
reject(new Error(`Type of response data for ${Methods.STOP_RECORDING} method is not equal Boolean`))
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch(error) {
|
|
346
|
+
reject(error)
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/// Is Recording Now
|
|
352
|
+
|
|
353
|
+
isRecordingNow(cb: ({recordingIsActive, error}: TResponse) => void) {
|
|
354
|
+
service.sendMessage(Methods.IS_RECORDING)
|
|
355
|
+
.then((result: TResult) => {
|
|
356
|
+
if (!!result.error) {
|
|
357
|
+
cb({error: result.error})
|
|
358
|
+
} else if (typeof result.data === 'boolean') {
|
|
359
|
+
cb({recordingIsActive: result.data})
|
|
360
|
+
} else {
|
|
361
|
+
cb({error: new Error(`Type of response data for ${Methods.IS_RECORDING} method is not equal Boolean`)})
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
.catch((error: Error) => {
|
|
365
|
+
cb({error})
|
|
366
|
+
})
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
async isRecordingNowAsync(): Promise<boolean> {
|
|
370
|
+
return new Promise(async (resolve, reject) => {
|
|
371
|
+
try {
|
|
372
|
+
const result = await service.sendMessage(Methods.IS_RECORDING);
|
|
373
|
+
//@ts-ignore
|
|
374
|
+
if (!!result.error) {
|
|
375
|
+
//@ts-ignore
|
|
376
|
+
reject(result.error)
|
|
377
|
+
//@ts-ignore
|
|
378
|
+
} else if (typeof result.data === 'boolean') {
|
|
379
|
+
//@ts-ignore
|
|
380
|
+
resolve(result.data)
|
|
381
|
+
} else {
|
|
382
|
+
reject(new Error(`Type of response data for ${Methods.IS_RECORDING} method is not equal Boolean`))
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch(e) {
|
|
386
|
+
reject(e)
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
};
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
export default AiQaSdk;
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
Validation for
|
|
397
|
+
|
|
398
|
+
- createApplication
|
|
399
|
+
policyNumber: string;
|
|
400
|
+
product: string;
|
|
401
|
+
insuredPhone: string;
|
|
402
|
+
clientName: string;
|
|
403
|
+
|
|
404
|
+
- addFact
|
|
405
|
+
{
|
|
406
|
+
"conversationId": "",
|
|
407
|
+
"applicationAliasKey": "",
|
|
408
|
+
"factId": "",
|
|
409
|
+
"fact_status": true,
|
|
410
|
+
"value": "string"
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if user set wrong data we can make throw or call callback / reject function
|
|
414
|
+
|
|
415
|
+
and optional checking arg for
|
|
416
|
+
|
|
417
|
+
- getApplication
|
|
418
|
+
check string argument
|
|
419
|
+
|
|
420
|
+
- setApplication
|
|
421
|
+
check string argument
|
|
422
|
+
|
|
423
|
+
- onClick Play/Stop
|
|
424
|
+
check is the application active
|
|
425
|
+
|
|
426
|
+
- addFact
|
|
427
|
+
check is the application active
|
|
428
|
+
*/
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isLoggingEnabled } from "./config";
|
|
2
|
+
|
|
3
|
+
class Logger {
|
|
4
|
+
log(...args: any[]): void {
|
|
5
|
+
if (isLoggingEnabled()) {
|
|
6
|
+
console.log(...args);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
error(...args: any[]): void {
|
|
11
|
+
if (isLoggingEnabled()) {
|
|
12
|
+
console.error(...args);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
warn(...args: any[]): void {
|
|
17
|
+
if (isLoggingEnabled()) {
|
|
18
|
+
console.warn(...args);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
info(...args: any[]): void {
|
|
23
|
+
if (isLoggingEnabled()) {
|
|
24
|
+
console.info(...args);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
debug(...args: any[]): void {
|
|
29
|
+
if (isLoggingEnabled()) {
|
|
30
|
+
console.debug(...args);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const logger = new Logger();
|
|
36
|
+
export default logger;
|
|
37
|
+
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { MINIMAL_SUPPORT_VERSION, getConfig } from "../config";
|
|
2
|
+
import { Methods } from "../enum";
|
|
3
|
+
import { TApplication, TApplicationFact, TFactIsMatched, TResult } from "../types";
|
|
4
|
+
import logger from "../logger";
|
|
5
|
+
|
|
6
|
+
// Use global io from CDN (loaded in index.html)
|
|
7
|
+
// @ts-ignore - window.io is loaded via CDN before this script
|
|
8
|
+
const io = (typeof window !== 'undefined' ? (window as any).io : null);
|
|
9
|
+
|
|
10
|
+
const queue: any[] = [];
|
|
11
|
+
const listenersList: any[] = [];
|
|
12
|
+
const excludedMessages: string[] = ['app_version'];
|
|
13
|
+
|
|
14
|
+
const service = {
|
|
15
|
+
connect(events) {
|
|
16
|
+
const self = this;
|
|
17
|
+
const config = getConfig();
|
|
18
|
+
|
|
19
|
+
logger.log('INIT WEBSOCKET', config.url);
|
|
20
|
+
|
|
21
|
+
if (!config.url) {
|
|
22
|
+
logger.log("WebSocket address is required.");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const socketOptions: any = {
|
|
27
|
+
reconnectionDelayMax: 10000,
|
|
28
|
+
path: config.path || '/ws',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
if (config.jwtToken) {
|
|
32
|
+
socketOptions.extraHeaders = {
|
|
33
|
+
'Authorization': `Bearer ${config.jwtToken}`
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.websocketClient = io(config.url, socketOptions);
|
|
38
|
+
|
|
39
|
+
this.websocketClient.on('connect', () => {
|
|
40
|
+
logger.log("WebSocket connection established");
|
|
41
|
+
|
|
42
|
+
!!events['connect'] && events['connect']();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
this.websocketClient.on('app_version', (version: string = '1.0.0') => {
|
|
46
|
+
if(!(MINIMAL_SUPPORT_VERSION <= version)) {
|
|
47
|
+
self.websocketClient.disconnect();
|
|
48
|
+
throw new Error (`You version of AIQAapp is out of date. Your version is ${version}. Required >= ${MINIMAL_SUPPORT_VERSION}. Please update your app.`)
|
|
49
|
+
} else {
|
|
50
|
+
self.websocketClient.emit(Methods.INIT_AUDIO_RECORDER, JSON.stringify({init: true})); //TODO Try remove JSON.stringify
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
this.websocketClient.on('close', (event) => {
|
|
55
|
+
logger.log("WebSocket connection closed", event);
|
|
56
|
+
!!events['close'] && events['close']();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
this.websocketClient.on('disconnect', () => {
|
|
60
|
+
logger.log('Disconnected from WebSocket server');
|
|
61
|
+
!!events['disconnect'] && events['disconnect']();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
this.websocketClient.io.on("error", (error) => {
|
|
65
|
+
logger.log("error", error);
|
|
66
|
+
!!events['error'] && events['error']();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
this.websocketClient.io.on("reconnect_attempt", (attempt) => {
|
|
70
|
+
logger.log('reconnect_attempt', attempt);
|
|
71
|
+
!!events['reconnect_attempt'] && events['reconnect_attempt']();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
this.websocketClient.io.on("reconnect_error", (error) => {
|
|
75
|
+
logger.log("reconnect_error", error);
|
|
76
|
+
!!events['reconnect_error'] && events['reconnect_error']();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this.websocketClient.io.on("reconnect_failed", (error) => {
|
|
80
|
+
logger.log("reconnect_failed", error);
|
|
81
|
+
!!events['reconnect_failed'] && events['reconnect_failed']();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
this.websocketClient.onAny((eventName: string, eventData: any) => {
|
|
85
|
+
logger.log("Message from server:", eventName, eventData);
|
|
86
|
+
logger.log("excludedMessages", excludedMessages);
|
|
87
|
+
if(eventName && !excludedMessages.includes(eventName)) {
|
|
88
|
+
const response = eventData ? JSON.parse(eventData) : {};
|
|
89
|
+
const item = queue.find((item) => item.addressee === eventName);
|
|
90
|
+
const listener = listenersList.find((item) => item.addressee === eventName);
|
|
91
|
+
|
|
92
|
+
if (item && response.data) {
|
|
93
|
+
item.resolve({data: response.data});
|
|
94
|
+
self.removeFromQueue(item);
|
|
95
|
+
} else if (listener && response.data) {
|
|
96
|
+
listener.callback({data: response.data});
|
|
97
|
+
} else if (item && response.error) {
|
|
98
|
+
item.reject({error: response.error});
|
|
99
|
+
self.removeFromQueue(item);
|
|
100
|
+
} else if (listener && response.error) {
|
|
101
|
+
listener.callback({error: response.error});
|
|
102
|
+
} else {
|
|
103
|
+
logger.error('Problem with receiving message');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
disconnect() {
|
|
110
|
+
this.websocketClient.disconnect()
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
addListener(addressee: string, _checkAppVersion: () => void) {
|
|
114
|
+
listenersList.push({addressee, callback: _checkAppVersion});
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
sendMessage(addressee: string, data?: any): Promise<TApplication | TApplicationFact | TFactIsMatched | TResult> {
|
|
118
|
+
const self = this;
|
|
119
|
+
const promise: Promise<TApplication | TApplicationFact | TFactIsMatched | boolean> = new Promise((resolve, reject) => {
|
|
120
|
+
queue.push({addressee, resolve, reject});
|
|
121
|
+
self.websocketClient.emit(addressee, data ? JSON.stringify(data) : undefined); //TODO Try remove JSON.stringify
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
return promise
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
removeFromQueue(item) {
|
|
128
|
+
const index = queue.indexOf(item);
|
|
129
|
+
if (index > -1) { // only splice array when item is found
|
|
130
|
+
queue.splice(index, 1); // 2nd parameter means remove one item only
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
getStatus() {
|
|
135
|
+
return this.websocketClient.connected;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export default service;
|