cdsclient-lib 0.0.2 → 0.0.4
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 +19 -20
- package/dist/lib/cjs/client.d.ts +304 -0
- package/dist/lib/cjs/client.js +916 -0
- package/dist/lib/cjs/client.js.map +1 -0
- package/dist/lib/cjs/enums.d.ts +23 -0
- package/dist/lib/cjs/enums.js +28 -0
- package/dist/lib/cjs/enums.js.map +1 -0
- package/dist/lib/cjs/errors.d.ts +20 -0
- package/dist/lib/cjs/errors.js +25 -0
- package/dist/lib/cjs/errors.js.map +1 -0
- package/dist/lib/cjs/event/channelstates.d.ts +24 -0
- package/dist/lib/cjs/event/channelstates.js +28 -0
- package/dist/lib/cjs/event/channelstates.js.map +1 -0
- package/dist/lib/cjs/event/eventprovider.d.ts +40 -0
- package/dist/lib/cjs/event/eventprovider.js +62 -0
- package/dist/lib/cjs/event/eventprovider.js.map +1 -0
- package/dist/lib/cjs/event/events.d.ts +32 -0
- package/dist/lib/cjs/event/events.js +38 -0
- package/dist/lib/cjs/event/events.js.map +1 -0
- package/dist/lib/cjs/index.d.ts +23 -0
- package/dist/lib/cjs/index.js +68 -0
- package/dist/lib/cjs/index.js.map +1 -0
- package/dist/lib/cjs/interfaces.d.ts +162 -0
- package/dist/lib/cjs/interfaces.js +20 -0
- package/dist/lib/cjs/interfaces.js.map +1 -0
- package/dist/lib/cjs/models.d.ts +198 -0
- package/dist/lib/cjs/models.js +234 -0
- package/dist/lib/cjs/models.js.map +1 -0
- package/dist/lib/cjs/wsclient.d.ts +99 -0
- package/dist/lib/cjs/wsclient.js +330 -0
- package/dist/lib/cjs/wsclient.js.map +1 -0
- package/dist/lib/es6/client.d.ts +304 -0
- package/dist/lib/es6/client.js +876 -0
- package/dist/lib/es6/client.js.map +1 -0
- package/dist/lib/es6/enums.d.ts +23 -0
- package/dist/lib/es6/enums.js +25 -0
- package/dist/lib/es6/enums.js.map +1 -0
- package/dist/lib/es6/errors.d.ts +20 -0
- package/dist/lib/es6/errors.js +25 -0
- package/dist/lib/es6/errors.js.map +1 -0
- package/dist/lib/es6/event/channelstates.d.ts +24 -0
- package/dist/lib/es6/event/channelstates.js +25 -0
- package/dist/lib/es6/event/channelstates.js.map +1 -0
- package/dist/lib/es6/event/eventprovider.d.ts +40 -0
- package/dist/lib/es6/event/eventprovider.js +57 -0
- package/dist/lib/es6/event/eventprovider.js.map +1 -0
- package/dist/lib/es6/event/events.d.ts +32 -0
- package/dist/lib/es6/event/events.js +35 -0
- package/dist/lib/es6/event/events.js.map +1 -0
- package/dist/lib/es6/index.d.ts +23 -0
- package/dist/lib/es6/index.js +23 -0
- package/dist/lib/es6/index.js.map +1 -0
- package/dist/lib/es6/interfaces.d.ts +162 -0
- package/dist/lib/es6/interfaces.js +19 -0
- package/dist/lib/es6/interfaces.js.map +1 -0
- package/dist/lib/es6/models.d.ts +198 -0
- package/dist/lib/es6/models.js +201 -0
- package/dist/lib/es6/models.js.map +1 -0
- package/dist/lib/es6/wsclient.d.ts +99 -0
- package/dist/lib/es6/wsclient.js +292 -0
- package/dist/lib/es6/wsclient.js.map +1 -0
- package/package.json +28 -14
|
@@ -0,0 +1,876 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright © 2024 Rajdeep Rath. All Rights Reserved.
|
|
3
|
+
*
|
|
4
|
+
* This codebase is open-source and provided for use exclusively with the Cloudisense platform,
|
|
5
|
+
* as governed by its End-User License Agreement (EULA). Unauthorized use, reproduction,
|
|
6
|
+
* or distribution of this code outside of the Cloudisense ecosystem is strictly prohibited.
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
* You may not use this file except in compliance with the License.
|
|
10
|
+
* A copy of the License is available at:
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* This code may include third-party open-source libraries subject to their respective licenses.
|
|
14
|
+
* Such licenses are referenced in the source files or accompanying documentation.
|
|
15
|
+
*
|
|
16
|
+
* For questions or permissions beyond the scope of this notice, please contact Rajdeep Rath.
|
|
17
|
+
*/
|
|
18
|
+
import 'reflect-metadata';
|
|
19
|
+
import { WSClient } from "./wsclient";
|
|
20
|
+
import { sha256 } from 'js-sha256';
|
|
21
|
+
import { EventList } from "strongly-typed-events";
|
|
22
|
+
import { ClientEventProvider } from "./event/eventprovider";
|
|
23
|
+
import { Base64 } from 'js-base64';
|
|
24
|
+
import { ClientStateType, ClientState, CloudisenseClientStatsDataEvent, CloudisenseClientLogDataEvent, CloudisenseClientSimpleNotificationEvent, CloudisenseClientErrorEvent, AuthData, CloudisenseClientUIDataEvent, CloudisenseClientScriptDataEvent } from "./models";
|
|
25
|
+
import { TOPIC_SCRIPT_MONITORING, TOPIC_LOG_MONITORING, TOPIC_STATS_MONITORING, TOPIC_UI_UPDATES } from "./event/events";
|
|
26
|
+
import * as CHANNEL_STATES from './event/channelstates';
|
|
27
|
+
import * as EVENTS from './event/events';
|
|
28
|
+
import axios from 'axios';
|
|
29
|
+
import { plainToInstance } from 'class-transformer';
|
|
30
|
+
export class CloudisenseApiClient extends ClientEventProvider {
|
|
31
|
+
constructor(config) {
|
|
32
|
+
super();
|
|
33
|
+
this._topicevents = new EventList();
|
|
34
|
+
this._errorCount = 0;
|
|
35
|
+
this.host = config.host;
|
|
36
|
+
this.port = config.port;
|
|
37
|
+
this.authdata = config.authdata;
|
|
38
|
+
this.autoconnect = (typeof config.autoconnect === 'undefined' || config.autoconnect === null) ? false : config.autoconnect;
|
|
39
|
+
this.reconnectOnFailure = (typeof config.reconnectOnFailure === 'undefined' || config.reconnectOnFailure === null) ? false : config.reconnectOnFailure;
|
|
40
|
+
this._restEndPoint = "http" + "://" + this.host + ":" + this.port; // fix this later
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Subscribes to a specific DataEvent topic
|
|
45
|
+
*
|
|
46
|
+
* @param topicname topic name to subscribe to
|
|
47
|
+
* @param fn subscriber handler function
|
|
48
|
+
*/
|
|
49
|
+
subscribeTopic(topicname, fn) {
|
|
50
|
+
return this._topicevents.get(topicname).subscribe(fn);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Unsubscribes from a specific DataEvent topic. The handler is executed at most once
|
|
54
|
+
*
|
|
55
|
+
* @param topicname topic name to unsubscribe from
|
|
56
|
+
* @param fn subscriber handler function
|
|
57
|
+
*/
|
|
58
|
+
unsubscribeTopic(topicname, fn) {
|
|
59
|
+
this._topicevents.get(topicname).unsubscribe(fn);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Checks to see if a given DataEvent topic has a handler registered against it or not
|
|
63
|
+
*
|
|
64
|
+
* @param topicname
|
|
65
|
+
* @param fn
|
|
66
|
+
*/
|
|
67
|
+
hasTopicHandler(topicname, fn) {
|
|
68
|
+
return this._topicevents.get(topicname).has(fn);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Gets the root path of the filesystem (constrained by sandbox)
|
|
72
|
+
*
|
|
73
|
+
* @returns Promise that resolved to root path data of the filesystem
|
|
74
|
+
*/
|
|
75
|
+
get_accessible_file_system_paths() {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
let promise = this._socketservice.doRPC("get_accessible_paths", {});
|
|
78
|
+
promise.then((data) => {
|
|
79
|
+
resolve(data);
|
|
80
|
+
}).catch((err) => {
|
|
81
|
+
reject(err);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Requests deletion of a file from the file system
|
|
87
|
+
*
|
|
88
|
+
* @param path The path of the file to delete
|
|
89
|
+
* @returns Promise that resolves to nothing if operation is successful and error if unsuccessful
|
|
90
|
+
*/
|
|
91
|
+
delete_file(path) {
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
let promise = this._socketservice.doRPC("delete_file", {
|
|
94
|
+
"path": path
|
|
95
|
+
});
|
|
96
|
+
promise.then((data) => {
|
|
97
|
+
resolve(data);
|
|
98
|
+
}).catch((err) => {
|
|
99
|
+
reject(err);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Requests deletion of a directory from the file system
|
|
105
|
+
*
|
|
106
|
+
* @param path The path of the directory to delete
|
|
107
|
+
* @returns Promise that resolves to nothing if operation is successful and error if unsuccessful
|
|
108
|
+
*/
|
|
109
|
+
delete_folder(root, dirname, deleteNonEmpty = false) {
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
let promise = this._socketservice.doRPC("delete_folder", {
|
|
112
|
+
"root": root,
|
|
113
|
+
"dirname": dirname,
|
|
114
|
+
"delete_non_empty": deleteNonEmpty
|
|
115
|
+
});
|
|
116
|
+
promise.then((data) => {
|
|
117
|
+
resolve(data);
|
|
118
|
+
}).catch((err) => {
|
|
119
|
+
reject(err);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Requests the download file from the file system (within allowed scope)
|
|
125
|
+
*
|
|
126
|
+
* @param path The path of the file to download
|
|
127
|
+
* @returns Promise that resolves to a download link if operation is successful and error if unsuccessful
|
|
128
|
+
*/
|
|
129
|
+
download_file(path, mode = "static") {
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
let promise = this._socketservice.doRPC("download_file", {
|
|
132
|
+
"path": path,
|
|
133
|
+
"mode": mode
|
|
134
|
+
});
|
|
135
|
+
promise.then((data) => {
|
|
136
|
+
resolve(data);
|
|
137
|
+
}).catch((err) => {
|
|
138
|
+
reject(err);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Gets content listing of the file system path specified
|
|
144
|
+
*
|
|
145
|
+
* @returns Promise that resolved to path content (if any)
|
|
146
|
+
*/
|
|
147
|
+
list_path_content(root, path = "") {
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
let promise = this._socketservice.doRPC("list_content", {
|
|
150
|
+
"root": root,
|
|
151
|
+
"path": path
|
|
152
|
+
});
|
|
153
|
+
promise.then((data) => {
|
|
154
|
+
resolve(data);
|
|
155
|
+
}).catch((err) => {
|
|
156
|
+
reject(err);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Fetched the content of a simple text file from server
|
|
162
|
+
*
|
|
163
|
+
* @returns
|
|
164
|
+
*/
|
|
165
|
+
read_file(path) {
|
|
166
|
+
const promise = new Promise((resolve, reject) => {
|
|
167
|
+
const url = this.getBaseAPIendPoint() + "/file/read";
|
|
168
|
+
const params = new URLSearchParams();
|
|
169
|
+
params.append('path', path);
|
|
170
|
+
const config = {
|
|
171
|
+
headers: {
|
|
172
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
const promise = axios.post(url, params, config);
|
|
176
|
+
promise.then((result) => {
|
|
177
|
+
if (result.status == 200) {
|
|
178
|
+
const content = Base64.decode(result.data.data);
|
|
179
|
+
console.debug(content);
|
|
180
|
+
resolve(content);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
throw new Error("Invalid or unexpected response");
|
|
184
|
+
}
|
|
185
|
+
})
|
|
186
|
+
.catch((err) => {
|
|
187
|
+
console.error(err.toString());
|
|
188
|
+
reject(err);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
return promise;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Saves the content of a simple text file on server
|
|
195
|
+
*
|
|
196
|
+
* @returns
|
|
197
|
+
*/
|
|
198
|
+
write_file(path, content) {
|
|
199
|
+
const promise = new Promise((resolve, reject) => {
|
|
200
|
+
const url = this.getBaseAPIendPoint() + "/file/write";
|
|
201
|
+
const params = new URLSearchParams();
|
|
202
|
+
params.append('path', path);
|
|
203
|
+
params.append('content', Base64.encode(content));
|
|
204
|
+
const config = {
|
|
205
|
+
headers: {
|
|
206
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const promise = axios.post(url, params, config);
|
|
210
|
+
promise.then((result) => {
|
|
211
|
+
if (result.status == 200) {
|
|
212
|
+
const content = Base64.decode(result.data.data);
|
|
213
|
+
console.debug(content);
|
|
214
|
+
resolve(content);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
throw new Error("Invalid or unexpected response");
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
.catch((err) => {
|
|
221
|
+
console.error(err.toString());
|
|
222
|
+
reject(err);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
return promise;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Gets list of accessible logs
|
|
229
|
+
*
|
|
230
|
+
* @returns Promise that resolved to List of logs
|
|
231
|
+
*/
|
|
232
|
+
get_logs() {
|
|
233
|
+
return new Promise((resolve, reject) => {
|
|
234
|
+
let promise = this._socketservice.doRPC("list_logs");
|
|
235
|
+
promise.then((data) => {
|
|
236
|
+
resolve(data);
|
|
237
|
+
}).catch((err) => {
|
|
238
|
+
reject(err);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Gets list of reaction engine rules
|
|
244
|
+
*
|
|
245
|
+
* @returns Promise that resolved to List of ReactionRules
|
|
246
|
+
*/
|
|
247
|
+
list_rules(head = true) {
|
|
248
|
+
return new Promise((resolve, reject) => {
|
|
249
|
+
let promise = this._socketservice.doRPC("list_rules", { "head": head });
|
|
250
|
+
promise.then((data) => {
|
|
251
|
+
resolve(data);
|
|
252
|
+
}).catch((err) => {
|
|
253
|
+
reject(err);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Attempts to reloads all reaction rules in the system
|
|
259
|
+
*
|
|
260
|
+
* @returns Promise that resolved to nothing
|
|
261
|
+
*/
|
|
262
|
+
reload_rules() {
|
|
263
|
+
return new Promise((resolve, reject) => {
|
|
264
|
+
let promise = this._socketservice.doRPC("reload_rules", {});
|
|
265
|
+
promise.then((data) => {
|
|
266
|
+
resolve(data);
|
|
267
|
+
}).catch((err) => {
|
|
268
|
+
reject(err);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Attempts to reloads a reaction rules by specified id
|
|
274
|
+
* in the system
|
|
275
|
+
*
|
|
276
|
+
* @returns Promise that resolved to id of the reaction rule
|
|
277
|
+
*/
|
|
278
|
+
reload_rule(id) {
|
|
279
|
+
return new Promise((resolve, reject) => {
|
|
280
|
+
let promise = this._socketservice.doRPC("reload_rule", { "rule_id": id });
|
|
281
|
+
promise.then((data) => {
|
|
282
|
+
resolve(id);
|
|
283
|
+
}).catch((err) => {
|
|
284
|
+
reject(err);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Gets rule data of a reaction engine rule by specified id
|
|
290
|
+
*
|
|
291
|
+
* @returns Promise that resolved to Rule data
|
|
292
|
+
*/
|
|
293
|
+
get_rule(id) {
|
|
294
|
+
return new Promise((resolve, reject) => {
|
|
295
|
+
let promise = this._socketservice.doRPC("read_rule", { "rule_id": id });
|
|
296
|
+
promise.then((data) => {
|
|
297
|
+
resolve(data);
|
|
298
|
+
}).catch((err) => {
|
|
299
|
+
reject(err);
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Requests service to initiate restart via systemctl.
|
|
305
|
+
* Server should have sufficient permissions to execute the command
|
|
306
|
+
*
|
|
307
|
+
* @returns Promise that resolved to nothing (no return value)
|
|
308
|
+
*/
|
|
309
|
+
request_restart(id) {
|
|
310
|
+
return new Promise((resolve, reject) => {
|
|
311
|
+
let promise = this._socketservice.doRPC("restart_self", {});
|
|
312
|
+
promise.then((data = null) => {
|
|
313
|
+
resolve(data);
|
|
314
|
+
}).catch((err) => {
|
|
315
|
+
reject(err);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Requests to load settings / configuration information from the server
|
|
321
|
+
*
|
|
322
|
+
* @returns Promise that resolved to settings data
|
|
323
|
+
*/
|
|
324
|
+
loadSettings() {
|
|
325
|
+
return new Promise((resolve, reject) => {
|
|
326
|
+
let promise = this._socketservice.doRPC("get_configuration", {});
|
|
327
|
+
promise.then((data) => {
|
|
328
|
+
resolve(data);
|
|
329
|
+
}).catch((err) => {
|
|
330
|
+
reject(err);
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Gets sample reaction rule data from server
|
|
336
|
+
*
|
|
337
|
+
* @returns Promise that resolved to Rule data
|
|
338
|
+
*/
|
|
339
|
+
generate_sample_rule() {
|
|
340
|
+
return new Promise((resolve, reject) => {
|
|
341
|
+
let promise = this._socketservice.doRPC("generate_sample", {});
|
|
342
|
+
promise.then((data) => {
|
|
343
|
+
resolve(data);
|
|
344
|
+
}).catch((err) => {
|
|
345
|
+
reject(err);
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Saves rule data of a reaction engine rule on server
|
|
351
|
+
*
|
|
352
|
+
* @returns Promise that resolved to Rule Id on successful write
|
|
353
|
+
*/
|
|
354
|
+
write_rule(data, update = true) {
|
|
355
|
+
return new Promise((resolve, reject) => {
|
|
356
|
+
let promise = this._socketservice.doRPC("write_rule", { "rule_data": data, "update": update });
|
|
357
|
+
promise.then((response) => {
|
|
358
|
+
resolve(response);
|
|
359
|
+
}).catch((err) => {
|
|
360
|
+
reject(err);
|
|
361
|
+
});
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Deletes a rule by specified id
|
|
366
|
+
*
|
|
367
|
+
* @returns Promise that resolves to the id of the deleted rule
|
|
368
|
+
*/
|
|
369
|
+
delete_rule(id) {
|
|
370
|
+
return new Promise((resolve, reject) => {
|
|
371
|
+
let promise = this._socketservice.doRPC("delete_rule", { "rule_id": id });
|
|
372
|
+
promise.then(() => {
|
|
373
|
+
resolve(id);
|
|
374
|
+
}).catch((err) => {
|
|
375
|
+
reject(err);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Subscribes to arbitrary data channel (topic path) to get realtime data
|
|
381
|
+
*
|
|
382
|
+
* @returns Promise that resolved to subscribable topic path for the data channel for stats
|
|
383
|
+
*/
|
|
384
|
+
subscribe_datachannel(topic) {
|
|
385
|
+
return new Promise((resolve, reject) => {
|
|
386
|
+
let payload = {
|
|
387
|
+
"topic": topic
|
|
388
|
+
};
|
|
389
|
+
let promise = this._socketservice.doRPC("subscribe_channel", payload);
|
|
390
|
+
promise.then((data) => {
|
|
391
|
+
resolve(data);
|
|
392
|
+
}).catch((err) => {
|
|
393
|
+
reject(err);
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Subscribes to stats channel (topic path) to get realtime data
|
|
399
|
+
*
|
|
400
|
+
* @returns Promise that resolved to subscribable topic path for the data channel for stats
|
|
401
|
+
*/
|
|
402
|
+
subscribe_stats() {
|
|
403
|
+
return new Promise((resolve, reject) => {
|
|
404
|
+
let payload = {
|
|
405
|
+
"topic": TOPIC_STATS_MONITORING
|
|
406
|
+
};
|
|
407
|
+
let promise = this._socketservice.doRPC("subscribe_channel", payload);
|
|
408
|
+
promise.then((data) => {
|
|
409
|
+
resolve(data);
|
|
410
|
+
}).catch((err) => {
|
|
411
|
+
reject(err);
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Subscribes to ui updates channel (topic path) to get data updates for dashboard widgets
|
|
417
|
+
*
|
|
418
|
+
* @returns Promise that resolved to subscribable topic path for the data channel for stats
|
|
419
|
+
*/
|
|
420
|
+
subscribe_ui_updates() {
|
|
421
|
+
return new Promise((resolve, reject) => {
|
|
422
|
+
let payload = {
|
|
423
|
+
"topic": TOPIC_UI_UPDATES
|
|
424
|
+
};
|
|
425
|
+
let promise = this._socketservice.doRPC("subscribe_channel", payload);
|
|
426
|
+
promise.then((data) => {
|
|
427
|
+
resolve(data);
|
|
428
|
+
}).catch((err) => {
|
|
429
|
+
reject(err);
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Unsubscribes from stats channel (topic path) to get realtime data
|
|
435
|
+
*
|
|
436
|
+
* @returns Promise that resolved to boolean true on unsubscribe success
|
|
437
|
+
*/
|
|
438
|
+
unsubscribe_stats() {
|
|
439
|
+
return new Promise((resolve, reject) => {
|
|
440
|
+
let payload = {
|
|
441
|
+
"topic": TOPIC_STATS_MONITORING
|
|
442
|
+
};
|
|
443
|
+
let promise = this._socketservice.doRPC("unsubscribe_channel", payload);
|
|
444
|
+
promise.then((data) => {
|
|
445
|
+
resolve(true);
|
|
446
|
+
}).catch((err) => {
|
|
447
|
+
reject(err);
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Subscribes to log channel (topic path) to get realtime data
|
|
453
|
+
*
|
|
454
|
+
* @param topic
|
|
455
|
+
* @returns Promise that resolved to subscribable topic path for the data channel of thsi log
|
|
456
|
+
*/
|
|
457
|
+
subscribe_log(topic) {
|
|
458
|
+
return new Promise((resolve, reject) => {
|
|
459
|
+
let payload = {
|
|
460
|
+
"topic": topic
|
|
461
|
+
};
|
|
462
|
+
let promise = this._socketservice.doRPC("subscribe_channel", payload);
|
|
463
|
+
promise.then((data) => {
|
|
464
|
+
resolve(data);
|
|
465
|
+
}).catch((err) => {
|
|
466
|
+
reject(err);
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
*
|
|
472
|
+
* Unsubscribes from a log channel
|
|
473
|
+
*
|
|
474
|
+
* @param logkey
|
|
475
|
+
* @returns
|
|
476
|
+
*/
|
|
477
|
+
unsubscribe_log(topic) {
|
|
478
|
+
return new Promise((resolve, reject) => {
|
|
479
|
+
let payload = {
|
|
480
|
+
"topic": topic
|
|
481
|
+
};
|
|
482
|
+
let promise = this._socketservice.doRPC("unsubscribe_channel", payload);
|
|
483
|
+
promise.then((data) => {
|
|
484
|
+
resolve(data);
|
|
485
|
+
}).catch((err) => {
|
|
486
|
+
reject(err);
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Requests to download a log file from server
|
|
492
|
+
*
|
|
493
|
+
* @param logkey
|
|
494
|
+
* @returns
|
|
495
|
+
*/
|
|
496
|
+
download_log(logkey, mode = "static") {
|
|
497
|
+
const promise = new Promise((resolve, reject) => {
|
|
498
|
+
const url = this.getBaseAPIendPoint() + "/log/download/" + mode;
|
|
499
|
+
const params = new URLSearchParams();
|
|
500
|
+
params.append('logname', logkey);
|
|
501
|
+
const config = {
|
|
502
|
+
headers: {
|
|
503
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
const promise = axios.post(url, params, config);
|
|
507
|
+
promise.then((result) => {
|
|
508
|
+
if (result.data.status == "success") {
|
|
509
|
+
const download_url = this.getBaseAPIendPoint() + "/" + result.data.data;
|
|
510
|
+
resolve(download_url);
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
throw new Error('Exception response received ' + JSON.stringify(result));
|
|
514
|
+
}
|
|
515
|
+
})
|
|
516
|
+
.catch((err) => {
|
|
517
|
+
reject(err);
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
return promise;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Gets list of system services that can be started/stopped through the service
|
|
524
|
+
*
|
|
525
|
+
* @returns
|
|
526
|
+
*/
|
|
527
|
+
get_system_services() {
|
|
528
|
+
return new Promise((resolve, reject) => {
|
|
529
|
+
let promise = this._socketservice.doRPC("list_targets");
|
|
530
|
+
promise.then((data) => {
|
|
531
|
+
resolve(data);
|
|
532
|
+
}).catch((err) => {
|
|
533
|
+
reject(err);
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Starts a system service using its name
|
|
539
|
+
*
|
|
540
|
+
* @param name
|
|
541
|
+
* @returns
|
|
542
|
+
*/
|
|
543
|
+
start_service(name) {
|
|
544
|
+
return new Promise((resolve, reject) => {
|
|
545
|
+
let payload = {
|
|
546
|
+
"module": name
|
|
547
|
+
};
|
|
548
|
+
let promise = this._socketservice.doRPC("start_target", payload);
|
|
549
|
+
promise.then((data) => {
|
|
550
|
+
resolve(data);
|
|
551
|
+
}).catch((err) => {
|
|
552
|
+
reject(err);
|
|
553
|
+
});
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Stops a system service using its name
|
|
558
|
+
*
|
|
559
|
+
* @param name
|
|
560
|
+
* @returns
|
|
561
|
+
*/
|
|
562
|
+
stop_service(name) {
|
|
563
|
+
return new Promise((resolve, reject) => {
|
|
564
|
+
let payload = {
|
|
565
|
+
"module": name
|
|
566
|
+
};
|
|
567
|
+
let promise = this._socketservice.doRPC("stop_target", payload);
|
|
568
|
+
promise.then((data) => {
|
|
569
|
+
resolve(data);
|
|
570
|
+
}).catch((err) => {
|
|
571
|
+
reject(err);
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Restarts a system service using its name
|
|
577
|
+
*
|
|
578
|
+
* @param name
|
|
579
|
+
* @returns
|
|
580
|
+
*/
|
|
581
|
+
restart_service(name) {
|
|
582
|
+
return new Promise((resolve, reject) => {
|
|
583
|
+
let payload = {
|
|
584
|
+
"module": name
|
|
585
|
+
};
|
|
586
|
+
let promise = this._socketservice.doRPC("restart_target", payload);
|
|
587
|
+
promise.then((data) => {
|
|
588
|
+
resolve(data);
|
|
589
|
+
}).catch((err) => {
|
|
590
|
+
reject(err);
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
*
|
|
596
|
+
* Execute arbitrary intent request
|
|
597
|
+
*
|
|
598
|
+
* @param intent
|
|
599
|
+
* @param params
|
|
600
|
+
* @returns
|
|
601
|
+
*/
|
|
602
|
+
execute_arbitrary_action(intent, params) {
|
|
603
|
+
return new Promise((resolve, reject) => {
|
|
604
|
+
let promise = this._socketservice.doRPC(intent, params);
|
|
605
|
+
promise.then((data) => {
|
|
606
|
+
resolve(data);
|
|
607
|
+
}).catch((err) => {
|
|
608
|
+
reject(err);
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Connects to backend service using auth data from previous authentication
|
|
614
|
+
*
|
|
615
|
+
* @param authData
|
|
616
|
+
* @returns Promise
|
|
617
|
+
*/
|
|
618
|
+
connectWithAuthData(authData) {
|
|
619
|
+
return new Promise((resolve, reject) => {
|
|
620
|
+
this.__wsconnect(authData).then((wsclient) => {
|
|
621
|
+
resolve(wsclient);
|
|
622
|
+
})
|
|
623
|
+
.catch((err) => {
|
|
624
|
+
reject(err);
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Connects to backend service using a set of valid credentials
|
|
630
|
+
*
|
|
631
|
+
* @param username
|
|
632
|
+
* @param password
|
|
633
|
+
* @returns
|
|
634
|
+
*/
|
|
635
|
+
connectWithCredentials(username, password) {
|
|
636
|
+
return new Promise((resolve, reject) => {
|
|
637
|
+
var hashed_password = sha256.create().update(password).hex();
|
|
638
|
+
this.authenticate(username, hashed_password).then((res) => {
|
|
639
|
+
if (res.status == 200) {
|
|
640
|
+
const authData = plainToInstance(AuthData, res.data.data);
|
|
641
|
+
this._authtime = new Date().getUTCMilliseconds();
|
|
642
|
+
this.__wsconnect(authData).then((wsclient) => {
|
|
643
|
+
resolve(wsclient);
|
|
644
|
+
})
|
|
645
|
+
.catch((err) => {
|
|
646
|
+
reject(err);
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
reject("Authentication failed with code " + res.status);
|
|
651
|
+
}
|
|
652
|
+
}).catch((err) => {
|
|
653
|
+
this._errorCount++;
|
|
654
|
+
const message = err.toString();
|
|
655
|
+
if (message.indexOf("ECONNREFUSED") > 0) {
|
|
656
|
+
if (this.reconnectOnFailure) {
|
|
657
|
+
this.attemptReconnect();
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
661
|
+
reject(err);
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
__wsconnect(tokenData) {
|
|
667
|
+
return new Promise((resolve, reject) => {
|
|
668
|
+
const socket_client = new WSClient({
|
|
669
|
+
host: this.host,
|
|
670
|
+
port: this.port,
|
|
671
|
+
authtoken: this.authdata.access.token
|
|
672
|
+
})
|
|
673
|
+
.connectService()
|
|
674
|
+
.then((client) => {
|
|
675
|
+
this._errorCount = 0;
|
|
676
|
+
this._socketservice = client;
|
|
677
|
+
this._onClientStateUpdate.dispatch(new ClientState(ClientStateType.CONNECTED));
|
|
678
|
+
this._socketservice.onChannelData.subscribe((data) => {
|
|
679
|
+
this.processChannelData(data);
|
|
680
|
+
});
|
|
681
|
+
this._socketservice.onChannelState.subscribe((state) => {
|
|
682
|
+
switch (state) {
|
|
683
|
+
case CHANNEL_STATES.STATE_CHANNEL_ERROR:
|
|
684
|
+
this._onClientStateUpdate.dispatch(new ClientState(ClientStateType.CONNECTION_ERROR));
|
|
685
|
+
this._errorCount++;
|
|
686
|
+
if (this.reconnectOnFailure) {
|
|
687
|
+
// try to connect again
|
|
688
|
+
this.attemptReconnect();
|
|
689
|
+
}
|
|
690
|
+
break;
|
|
691
|
+
case CHANNEL_STATES.STATE_CHANNEL_DISCONNECTED:
|
|
692
|
+
this._onClientStateUpdate.dispatch(new ClientState(ClientStateType.CONNECTION_TERMINATED));
|
|
693
|
+
break;
|
|
694
|
+
case CHANNEL_STATES.STATE_CHANNEL_CONNECTION_LOST:
|
|
695
|
+
this._onClientStateUpdate.dispatch(new ClientState(ClientStateType.CONNECTION_LOST));
|
|
696
|
+
if (this.reconnectOnFailure) {
|
|
697
|
+
// try to connect again
|
|
698
|
+
this.attemptReconnect();
|
|
699
|
+
}
|
|
700
|
+
break;
|
|
701
|
+
case CHANNEL_STATES.STATE_CHANNEL_CONNECTIING:
|
|
702
|
+
this._onClientStateUpdate.dispatch(new ClientState(ClientStateType.CONNECTING));
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
resolve(socket_client);
|
|
707
|
+
})
|
|
708
|
+
.catch((err) => {
|
|
709
|
+
reject(err);
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Returns a boolean promise to help determine if socket si conencted or not
|
|
715
|
+
* @returns
|
|
716
|
+
*/
|
|
717
|
+
connected() {
|
|
718
|
+
return new Promise((resolve, reject) => {
|
|
719
|
+
if (this._socketservice && this._socketservice.is_connected()) {
|
|
720
|
+
resolve(true);
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
reject(false);
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Disconnects the client if connected to the server, otherwise
|
|
729
|
+
* throws error.
|
|
730
|
+
*/
|
|
731
|
+
disconnect() {
|
|
732
|
+
return new Promise((resolve, reject) => {
|
|
733
|
+
if (this._socketservice && this._socketservice.is_connected()) {
|
|
734
|
+
this._socketservice.disconnectService();
|
|
735
|
+
resolve(this._socketservice);
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
reject("Unable to disconnect service");
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Attempts to reconenct back to service using last successful credentials
|
|
744
|
+
*/
|
|
745
|
+
attemptReconnect() {
|
|
746
|
+
console.log("Attempting to reconnect");
|
|
747
|
+
if (this.authdata != undefined && this.authdata != null) {
|
|
748
|
+
if (this._errorCount < CloudisenseApiClient.MAX_ERROR_TOLERANCE) {
|
|
749
|
+
setTimeout(() => {
|
|
750
|
+
this.connectWithAuthData(this.authdata);
|
|
751
|
+
}, 5000);
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
throw new Error("too many connection failures");
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Process push data from server and dispatch events for client
|
|
760
|
+
*
|
|
761
|
+
* @param data
|
|
762
|
+
*/
|
|
763
|
+
processChannelData(data) {
|
|
764
|
+
if (data["type"] == "event") {
|
|
765
|
+
let notificationData = undefined;
|
|
766
|
+
let event = data;
|
|
767
|
+
this._onClientStateUpdate.dispatch(new ClientState(ClientStateType.EVENT_RECEIVED));
|
|
768
|
+
switch (event.name) {
|
|
769
|
+
case EVENTS.SERVER_PING_EVENT:
|
|
770
|
+
console.debug("Server ping message");
|
|
771
|
+
break;
|
|
772
|
+
case EVENTS.TEXT_NOTIFICATION_EVENT:
|
|
773
|
+
this._onTextNotificationEvent.dispatchAsync(new CloudisenseClientSimpleNotificationEvent(event.topic, event.data, event.meta, event.timestamp));
|
|
774
|
+
break;
|
|
775
|
+
case EVENTS.EVENT_UI_UPDATE:
|
|
776
|
+
this._onUIEvent.dispatchAsync(new CloudisenseClientUIDataEvent(event.topic, event.data, event.meta, event.timestamp));
|
|
777
|
+
this._dispatchTopicOrientedDataEvent(event);
|
|
778
|
+
break;
|
|
779
|
+
case EVENTS.TEXT_DATA_NOTIFICATION_EVENT:
|
|
780
|
+
this._onTextNotificationEvent.dispatchAsync(new CloudisenseClientSimpleNotificationEvent(event.topic, event.data, event.meta, event.timestamp));
|
|
781
|
+
this._dispatchTopicOrientedDataEvent(event);
|
|
782
|
+
break;
|
|
783
|
+
case EVENTS.ERROR_EVENT:
|
|
784
|
+
this._dispatchTopicOrientedErrorEvent(event);
|
|
785
|
+
break;
|
|
786
|
+
case EVENTS.DATA_EVENT:
|
|
787
|
+
this._dispatchTopicOrientedDataEvent(event);
|
|
788
|
+
break;
|
|
789
|
+
default:
|
|
790
|
+
console.error("Unrecognized event type");
|
|
791
|
+
break;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Dispatches topic specific error event with topic specific data
|
|
797
|
+
* @param event
|
|
798
|
+
*/
|
|
799
|
+
_dispatchTopicOrientedErrorEvent(event) {
|
|
800
|
+
const topic = event.topic;
|
|
801
|
+
switch (topic) {
|
|
802
|
+
case (topic.startsWith(TOPIC_LOG_MONITORING)) ? topic : null:
|
|
803
|
+
case (topic.startsWith(TOPIC_SCRIPT_MONITORING)) ? topic : null:
|
|
804
|
+
case (topic.startsWith(TOPIC_STATS_MONITORING)) ? topic : null:
|
|
805
|
+
case (topic.startsWith(TOPIC_UI_UPDATES)) ? topic : null:
|
|
806
|
+
case (topic.startsWith(EVENTS.TOPIC_UI_INITIALIZATION)) ? topic : null:
|
|
807
|
+
this._topicevents.get(topic).dispatchAsync(this, new CloudisenseClientErrorEvent(event.topic, event.data, event.meta, event.timestamp));
|
|
808
|
+
break;
|
|
809
|
+
default:
|
|
810
|
+
console.error("Error for unexpected topic:" + topic);
|
|
811
|
+
break;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Dispatches topic specific event with topic specific data - (generic)
|
|
816
|
+
*
|
|
817
|
+
* @param event
|
|
818
|
+
*/
|
|
819
|
+
_dispatchTopicOrientedDataEvent(event) {
|
|
820
|
+
const topic = event.topic;
|
|
821
|
+
switch (topic) {
|
|
822
|
+
case (topic.startsWith(TOPIC_LOG_MONITORING)) ? topic : null:
|
|
823
|
+
this._topicevents.get(topic).dispatchAsync(this, new CloudisenseClientLogDataEvent(event.topic, event.data, event.meta, event.timestamp));
|
|
824
|
+
break;
|
|
825
|
+
case (topic.startsWith(TOPIC_SCRIPT_MONITORING)) ? topic : null:
|
|
826
|
+
this._topicevents.get(topic).dispatchAsync(this, new CloudisenseClientScriptDataEvent(event.topic, event.data, event.meta, event.timestamp));
|
|
827
|
+
break;
|
|
828
|
+
case (topic.startsWith(TOPIC_STATS_MONITORING)) ? topic : null:
|
|
829
|
+
this._topicevents.get(topic).dispatchAsync(this, new CloudisenseClientStatsDataEvent(event.topic, event.data, event.meta, event.timestamp));
|
|
830
|
+
break;
|
|
831
|
+
case (topic.startsWith(TOPIC_UI_UPDATES)) ? topic : null:
|
|
832
|
+
this._topicevents.get(topic).dispatchAsync(this, new CloudisenseClientUIDataEvent(event.topic, event.data, event.meta, event.timestamp));
|
|
833
|
+
break;
|
|
834
|
+
default:
|
|
835
|
+
console.debug("Event for topic:" + topic);
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
getBaseAPIendPoint() {
|
|
840
|
+
return this._restEndPoint;
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Authenticates a user based on username and password
|
|
844
|
+
*
|
|
845
|
+
* @param username
|
|
846
|
+
* @param password
|
|
847
|
+
* @returns
|
|
848
|
+
*/
|
|
849
|
+
authenticate(username, password) {
|
|
850
|
+
return new Promise((resolve, reject) => {
|
|
851
|
+
const url = this.getBaseAPIendPoint() + "/" + "authorize";
|
|
852
|
+
const params = new URLSearchParams();
|
|
853
|
+
params.append('username', username);
|
|
854
|
+
params.append('password', password);
|
|
855
|
+
const config = {
|
|
856
|
+
headers: {
|
|
857
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
const promise = axios.post(url, params, config);
|
|
861
|
+
promise.then((result) => {
|
|
862
|
+
console.debug(result);
|
|
863
|
+
resolve(result);
|
|
864
|
+
})
|
|
865
|
+
.catch((err) => {
|
|
866
|
+
console.error(err.toString());
|
|
867
|
+
reject(err);
|
|
868
|
+
});
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
dispose() {
|
|
872
|
+
// TO DO cleanup
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
CloudisenseApiClient.MAX_ERROR_TOLERANCE = 5;
|
|
876
|
+
//# sourceMappingURL=client.js.map
|