@team-internet/apiconnector 10.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/.devcontainer/Dockerfile +66 -0
- package/.devcontainer/devcontainer.json +30 -0
- package/.devcontainer/docker-compose.yml +11 -0
- package/.devcontainer/supporting_files/configuration/.czrc +1 -0
- package/.devcontainer/supporting_files/configuration/.p10k.zsh +1735 -0
- package/.devcontainer/supporting_files/configuration/.zshrc +23 -0
- package/.devcontainer/supporting_files/configuration/p10k-instant-prompt-vscode.zsh +323 -0
- package/.devcontainer/supporting_files/scripts/post-create.sh +11 -0
- package/.nycrc +6 -0
- package/CHANGELOG.md +582 -0
- package/CONTRIBUTING.md +132 -0
- package/LICENSE +21 -0
- package/README.md +56 -0
- package/dist/apiclient.d.ts +233 -0
- package/dist/apiclient.js +517 -0
- package/dist/column.d.ts +40 -0
- package/dist/column.js +52 -0
- package/dist/customlogger.d.ts +15 -0
- package/dist/customlogger.js +23 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +16 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.js +21 -0
- package/dist/record.d.ts +31 -0
- package/dist/record.js +42 -0
- package/dist/response.d.ts +264 -0
- package/dist/response.js +512 -0
- package/dist/responseparser.d.ts +1 -0
- package/dist/responseparser.js +36 -0
- package/dist/responsetemplatemanager.d.ts +65 -0
- package/dist/responsetemplatemanager.js +111 -0
- package/dist/responsetranslator.d.ts +32 -0
- package/dist/responsetranslator.js +144 -0
- package/dist/socketconfig.d.ts +62 -0
- package/dist/socketconfig.js +107 -0
- package/package.json +86 -0
- package/src/apiclient.ts +579 -0
- package/src/column.ts +57 -0
- package/src/customlogger.ts +29 -0
- package/src/index.ts +18 -0
- package/src/logger.ts +23 -0
- package/src/record.ts +46 -0
- package/src/response.ts +562 -0
- package/src/responseparser.ts +35 -0
- package/src/responsetemplatemanager.ts +136 -0
- package/src/responsetranslator.ts +191 -0
- package/src/socketconfig.ts +116 -0
- package/tests/apiclient.spec.ts +610 -0
- package/tests/app.js +47 -0
- package/tests/column.spec.ts +23 -0
- package/tests/index.spec.ts +22 -0
- package/tests/record.spec.ts +31 -0
- package/tests/response.spec.ts +341 -0
- package/tests/responseparser.spec.ts +13 -0
- package/tests/responsetemplatemanager.spec.ts +52 -0
- package/tests/socketconfig.spec.ts +14 -0
- package/tsconfig.json +7 -0
- package/typedoc.json +7 -0
package/src/apiclient.ts
ADDED
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
import fetch from "cross-fetch";
|
|
2
|
+
import { Logger } from "./logger.js";
|
|
3
|
+
import { Response } from "./response.js";
|
|
4
|
+
import { ResponseTemplateManager } from "./responsetemplatemanager.js";
|
|
5
|
+
import { fixedURLEnc, SocketConfig } from "./socketconfig.js";
|
|
6
|
+
import { toAscii } from "idna-uts46-hx";
|
|
7
|
+
|
|
8
|
+
export const CNR_CONNECTION_URL_PROXY = "http://10.0.0.1/api/call.cgi";
|
|
9
|
+
export const CNR_CONNECTION_URL_LIVE = "https://api.rrpproxy.net/api/call.cgi";
|
|
10
|
+
export const CNR_CONNECTION_URL_OTE =
|
|
11
|
+
"https://api-ote.rrpproxy.net/api/call.cgi";
|
|
12
|
+
|
|
13
|
+
const rtm = ResponseTemplateManager.getInstance();
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* APIClient class
|
|
17
|
+
*/
|
|
18
|
+
export class APIClient {
|
|
19
|
+
/**
|
|
20
|
+
* API connection timeout setting
|
|
21
|
+
*/
|
|
22
|
+
public static readonly socketTimeout: number = 300000;
|
|
23
|
+
/**
|
|
24
|
+
* User Agent string
|
|
25
|
+
*/
|
|
26
|
+
private ua: string;
|
|
27
|
+
/**
|
|
28
|
+
* API connection url
|
|
29
|
+
*/
|
|
30
|
+
private socketURL: string;
|
|
31
|
+
/**
|
|
32
|
+
* Object covering API connection data
|
|
33
|
+
*/
|
|
34
|
+
private socketConfig: SocketConfig;
|
|
35
|
+
/**
|
|
36
|
+
* activity flag for debug mode
|
|
37
|
+
*/
|
|
38
|
+
private debugMode: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* additional connection settings
|
|
41
|
+
*/
|
|
42
|
+
private curlopts: any;
|
|
43
|
+
/**
|
|
44
|
+
* logger function for debug mode
|
|
45
|
+
*/
|
|
46
|
+
private logger: Logger | null;
|
|
47
|
+
/**
|
|
48
|
+
* set sub user account
|
|
49
|
+
*/
|
|
50
|
+
private subUser: string;
|
|
51
|
+
/**
|
|
52
|
+
* set sub user account role seperater
|
|
53
|
+
*/
|
|
54
|
+
private readonly roleSeparator: string = ":";
|
|
55
|
+
|
|
56
|
+
public constructor() {
|
|
57
|
+
this.ua = "";
|
|
58
|
+
this.socketURL = "";
|
|
59
|
+
this.debugMode = false;
|
|
60
|
+
this.setURL(CNR_CONNECTION_URL_LIVE);
|
|
61
|
+
this.socketConfig = new SocketConfig();
|
|
62
|
+
this.useLIVESystem();
|
|
63
|
+
this.curlopts = {};
|
|
64
|
+
this.logger = null;
|
|
65
|
+
this.subUser = "";
|
|
66
|
+
this.roleSeparator = ":";
|
|
67
|
+
this.setDefaultLogger();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* set custom logger to use instead of default one
|
|
72
|
+
* @param customLogger
|
|
73
|
+
* @returns Current APIClient instance for method chaining
|
|
74
|
+
*/
|
|
75
|
+
public setCustomLogger(customLogger: Logger): APIClient {
|
|
76
|
+
this.logger = customLogger;
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* set default logger to use
|
|
81
|
+
* @returns Current APIClient instance for method chaining
|
|
82
|
+
*/
|
|
83
|
+
public setDefaultLogger(): APIClient {
|
|
84
|
+
this.logger = new Logger();
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Enable Debug Output to STDOUT
|
|
89
|
+
* @returns Current APIClient instance for method chaining
|
|
90
|
+
*/
|
|
91
|
+
public enableDebugMode(): APIClient {
|
|
92
|
+
this.debugMode = true;
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Disable Debug Output
|
|
98
|
+
* @returns Current APIClient instance for method chaining
|
|
99
|
+
*/
|
|
100
|
+
public disableDebugMode(): APIClient {
|
|
101
|
+
this.debugMode = false;
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get the API connection url that is currently set
|
|
107
|
+
* @returns API connection url currently in use
|
|
108
|
+
*/
|
|
109
|
+
public getURL(): string {
|
|
110
|
+
return this.socketURL;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Possibility to customize default user agent to fit your needs
|
|
115
|
+
* @param str user agent label
|
|
116
|
+
* @param rv revision of user agent
|
|
117
|
+
* @param modules further modules to add to user agent string, format: ["<mod1>/<rev>", "<mod2>/<rev>", ... ]
|
|
118
|
+
* @returns Current APIClient instance for method chaining
|
|
119
|
+
*/
|
|
120
|
+
public setUserAgent(str: string, rv: string, modules: any = []): APIClient {
|
|
121
|
+
const mods = modules.length ? " " + modules.join(" ") : "";
|
|
122
|
+
this.ua =
|
|
123
|
+
`${str} ` +
|
|
124
|
+
`(${process.platform}; ${process.arch}; rv:${rv})` +
|
|
125
|
+
mods +
|
|
126
|
+
` node-sdk/${this.getVersion()} ` +
|
|
127
|
+
`node/${process.version}`;
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Get the User Agent
|
|
133
|
+
* @returns User Agent string
|
|
134
|
+
*/
|
|
135
|
+
public getUserAgent(): string {
|
|
136
|
+
if (!this.ua.length) {
|
|
137
|
+
this.ua =
|
|
138
|
+
`NODE-SDK (${process.platform}; ${
|
|
139
|
+
process.arch
|
|
140
|
+
}; rv:${this.getVersion()}) ` + `node/${process.version}`;
|
|
141
|
+
}
|
|
142
|
+
return this.ua;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Set the proxy server to use for API communication
|
|
147
|
+
* @param proxy proxy server to use for communicatio
|
|
148
|
+
* @returns Current APIClient instance for method chaining
|
|
149
|
+
*/
|
|
150
|
+
public setProxy(proxy: string): APIClient {
|
|
151
|
+
this.curlopts.proxy = proxy;
|
|
152
|
+
return this;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Get the proxy server configuration
|
|
157
|
+
* @returns proxy server configuration value or null if not set
|
|
158
|
+
*/
|
|
159
|
+
public getProxy(): string | null {
|
|
160
|
+
if (Object.prototype.hasOwnProperty.call(this.curlopts, "proxy")) {
|
|
161
|
+
return this.curlopts.proxy;
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Set the referer to use for API communication
|
|
168
|
+
* @param referer Referer
|
|
169
|
+
* @returns Current APIClient instance for method chaining
|
|
170
|
+
*/
|
|
171
|
+
public setReferer(referer: string): APIClient {
|
|
172
|
+
this.curlopts.referer = referer;
|
|
173
|
+
return this;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get the referer configuration
|
|
178
|
+
* @returns referer configuration value or null if not set
|
|
179
|
+
*/
|
|
180
|
+
public getReferer(): string | null {
|
|
181
|
+
if (Object.prototype.hasOwnProperty.call(this.curlopts, "referer")) {
|
|
182
|
+
return this.curlopts.referer;
|
|
183
|
+
}
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Get the current module version
|
|
189
|
+
* @returns module version
|
|
190
|
+
*/
|
|
191
|
+
public getVersion(): string {
|
|
192
|
+
return "10.0.0";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Apply session data (session id and system entity) to given client request session
|
|
197
|
+
* @param session ClientRequest session instance
|
|
198
|
+
* @returns Current APIClient instance for method chaining
|
|
199
|
+
*/
|
|
200
|
+
public saveSession(session: any): APIClient {
|
|
201
|
+
session.socketcfg = {
|
|
202
|
+
login: this.socketConfig.getLogin(),
|
|
203
|
+
session: this.socketConfig.getSession(),
|
|
204
|
+
};
|
|
205
|
+
return this;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Use existing configuration out of ClientRequest session
|
|
210
|
+
* to rebuild and reuse connection settings
|
|
211
|
+
* @param session ClientRequest session instance
|
|
212
|
+
* @returns Current APIClient instance for method chaining
|
|
213
|
+
*/
|
|
214
|
+
public reuseSession(session: any): APIClient {
|
|
215
|
+
if (
|
|
216
|
+
!session ||
|
|
217
|
+
!session.socketcfg ||
|
|
218
|
+
!session.socketcfg.login ||
|
|
219
|
+
!session.socketcfg.session
|
|
220
|
+
) {
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
this.setCredentials(session.socketcfg.login);
|
|
224
|
+
this.socketConfig.setSession(session.socketcfg.session);
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Set another connection url to be used for API communication
|
|
230
|
+
* @param value API connection url to set
|
|
231
|
+
* @returns Current APIClient instance for method chaining
|
|
232
|
+
*/
|
|
233
|
+
public setURL(value: string): APIClient {
|
|
234
|
+
this.socketURL = value;
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Set Persistent to request session id for API communication
|
|
240
|
+
* @param value API session id
|
|
241
|
+
* @returns Current APIClient instance for method chaining
|
|
242
|
+
*/
|
|
243
|
+
public setPersistent(): APIClient {
|
|
244
|
+
this.socketConfig.setPersistent();
|
|
245
|
+
return this;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Set Credentials to be used for API communication
|
|
250
|
+
* @param uid account name
|
|
251
|
+
* @param pw account password
|
|
252
|
+
* @returns Current APIClient instance for method chaining
|
|
253
|
+
*/
|
|
254
|
+
public setCredentials(uid: string, pw: string = ""): APIClient {
|
|
255
|
+
this.socketConfig.setLogin(uid);
|
|
256
|
+
this.socketConfig.setPassword(pw);
|
|
257
|
+
return this;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Set Credentials to be used for API communication
|
|
262
|
+
* @param uid account name
|
|
263
|
+
* @param role role user id
|
|
264
|
+
* @param pw role user password
|
|
265
|
+
* @returns Current APIClient instance for method chaining
|
|
266
|
+
*/
|
|
267
|
+
public setRoleCredentials(
|
|
268
|
+
uid: string,
|
|
269
|
+
role: string,
|
|
270
|
+
pw: string = "",
|
|
271
|
+
): APIClient {
|
|
272
|
+
return this.setCredentials(
|
|
273
|
+
role ? `${uid}${this.roleSeparator}${role}` : uid,
|
|
274
|
+
pw,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Perform API login to start session-based communication
|
|
280
|
+
* @param otp optional one time password
|
|
281
|
+
* @returns Promise resolving with API Response
|
|
282
|
+
*/
|
|
283
|
+
public async login(): Promise<Response> {
|
|
284
|
+
this.setPersistent();
|
|
285
|
+
const rr = await this.request({}, false);
|
|
286
|
+
this.socketConfig.setSession("");
|
|
287
|
+
if (rr.isSuccess()) {
|
|
288
|
+
const col = rr.getColumn("SESSIONID");
|
|
289
|
+
this.socketConfig.setSession(col ? col.getData()[0] : "");
|
|
290
|
+
}
|
|
291
|
+
return rr;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Perform API logout to close API session in use
|
|
296
|
+
* @returns Promise resolving with API Response
|
|
297
|
+
*/
|
|
298
|
+
public async logout(): Promise<Response> {
|
|
299
|
+
const rr = await this.request(
|
|
300
|
+
{
|
|
301
|
+
COMMAND: "StopSession",
|
|
302
|
+
},
|
|
303
|
+
false,
|
|
304
|
+
);
|
|
305
|
+
if (rr.isSuccess()) {
|
|
306
|
+
this.socketConfig.setSession("");
|
|
307
|
+
}
|
|
308
|
+
return rr;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Perform API request using the given command
|
|
313
|
+
* @param cmd API command to request
|
|
314
|
+
* @returns Promise resolving with API Response
|
|
315
|
+
*/
|
|
316
|
+
public async request(cmd: any, setUserView = true): Promise<Response> {
|
|
317
|
+
// set sub user id if available
|
|
318
|
+
if (setUserView && this.subUser !== "") {
|
|
319
|
+
cmd.SUBUSER = this.subUser;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// flatten nested api command bulk parameters
|
|
323
|
+
let mycmd = this.flattenCommand(cmd);
|
|
324
|
+
|
|
325
|
+
// auto convert umlaut names to punycode
|
|
326
|
+
mycmd = await this.autoIDNConvert(mycmd);
|
|
327
|
+
|
|
328
|
+
// request command to API
|
|
329
|
+
const cfg: any = {
|
|
330
|
+
CONNECTION_URL: this.socketURL,
|
|
331
|
+
};
|
|
332
|
+
// TODO: 300s (to be sure to get an API response)
|
|
333
|
+
const reqCfg: any = {
|
|
334
|
+
// encoding: "utf8", //default for type string
|
|
335
|
+
// gzip: true,
|
|
336
|
+
body: this.getPOSTData(mycmd),
|
|
337
|
+
headers: {
|
|
338
|
+
"User-Agent": this.getUserAgent(),
|
|
339
|
+
},
|
|
340
|
+
method: "POST",
|
|
341
|
+
timeout: APIClient.socketTimeout,
|
|
342
|
+
url: cfg.CONNECTION_URL,
|
|
343
|
+
};
|
|
344
|
+
const proxy = this.getProxy();
|
|
345
|
+
if (proxy) {
|
|
346
|
+
reqCfg.proxy = proxy;
|
|
347
|
+
}
|
|
348
|
+
const referer = this.getReferer();
|
|
349
|
+
if (referer) {
|
|
350
|
+
reqCfg.headers.Referer = referer;
|
|
351
|
+
}
|
|
352
|
+
return fetch(cfg.CONNECTION_URL, reqCfg)
|
|
353
|
+
.then(async (res: any) => {
|
|
354
|
+
let error = null;
|
|
355
|
+
let body;
|
|
356
|
+
if (res.ok) {
|
|
357
|
+
// res.status >= 200 && res.status < 300
|
|
358
|
+
body = await res.text();
|
|
359
|
+
} else {
|
|
360
|
+
error = res.status + (res.statusText ? " " + res.statusText : "");
|
|
361
|
+
body = rtm.getTemplate("httperror").getPlain();
|
|
362
|
+
}
|
|
363
|
+
const rr = new Response(body, mycmd, cfg);
|
|
364
|
+
if (this.debugMode && this.logger) {
|
|
365
|
+
this.logger.log(this.getPOSTData(mycmd, true), rr, error);
|
|
366
|
+
}
|
|
367
|
+
return rr;
|
|
368
|
+
})
|
|
369
|
+
.catch((err) => {
|
|
370
|
+
const body = rtm.getTemplate("httperror").getPlain();
|
|
371
|
+
const rr = new Response(body, mycmd, cfg);
|
|
372
|
+
if (this.debugMode && this.logger) {
|
|
373
|
+
this.logger.log(this.getPOSTData(mycmd, true), rr, err.message);
|
|
374
|
+
}
|
|
375
|
+
return rr;
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Request the next page of list entries for the current list query
|
|
381
|
+
* Useful for tables
|
|
382
|
+
* @param rr API Response of current page
|
|
383
|
+
* @returns Promise resolving with API Response or null in case there are no further list entries
|
|
384
|
+
*/
|
|
385
|
+
public async requestNextResponsePage(rr: Response): Promise<Response | null> {
|
|
386
|
+
const mycmd = rr.getCommand();
|
|
387
|
+
if (Object.prototype.hasOwnProperty.call(mycmd, "LAST")) {
|
|
388
|
+
throw new Error(
|
|
389
|
+
"Parameter LAST in use. Please remove it to avoid issues in requestNextPage.",
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
let first = 0;
|
|
393
|
+
if (Object.prototype.hasOwnProperty.call(mycmd, "FIRST")) {
|
|
394
|
+
first = mycmd.FIRST;
|
|
395
|
+
}
|
|
396
|
+
const total = rr.getRecordsTotalCount();
|
|
397
|
+
const limit = rr.getRecordsLimitation();
|
|
398
|
+
first += limit;
|
|
399
|
+
if (first < total) {
|
|
400
|
+
mycmd.FIRST = first;
|
|
401
|
+
mycmd.LIMIT = limit;
|
|
402
|
+
return this.request(mycmd);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Request all pages/entries for the given query command
|
|
410
|
+
* @param cmd API list command to use
|
|
411
|
+
* @returns Promise resolving with array of API Responses
|
|
412
|
+
*/
|
|
413
|
+
public async requestAllResponsePages(cmd: any): Promise<Response[]> {
|
|
414
|
+
const responses: Response[] = [];
|
|
415
|
+
let rr: Response | null = await this.request({ ...cmd, FIRST: 0 });
|
|
416
|
+
|
|
417
|
+
while (rr !== null) {
|
|
418
|
+
responses.push(rr);
|
|
419
|
+
rr = await this.requestNextResponsePage(rr);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return responses;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Set a data view to a given subuser
|
|
427
|
+
* @param uid subuser account name
|
|
428
|
+
* @returns Current APIClient instance for method chaining
|
|
429
|
+
*/
|
|
430
|
+
public setUserView(uid: string): APIClient {
|
|
431
|
+
this.subUser = uid;
|
|
432
|
+
return this;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Reset data view back from subuser to user
|
|
437
|
+
* @returns Current APIClient instance for method chaining
|
|
438
|
+
*/
|
|
439
|
+
public resetUserView(): APIClient {
|
|
440
|
+
this.subUser = "";
|
|
441
|
+
return this;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Activate High Performance Connection Setup
|
|
446
|
+
* @see https://github.com/centralnicgroup-opensource/rtldev-middleware-node-sdk/blob/master/README.md
|
|
447
|
+
* @returns Current APIClient instance for method chaining
|
|
448
|
+
*/
|
|
449
|
+
public useHighPerformanceConnectionSetup(): APIClient {
|
|
450
|
+
this.setURL(CNR_CONNECTION_URL_PROXY);
|
|
451
|
+
return this;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Activate Default Connection Setup (the default)
|
|
456
|
+
* @returns Current APIClient instance for method chaining
|
|
457
|
+
*/
|
|
458
|
+
public useDefaultConnectionSetup(): APIClient {
|
|
459
|
+
this.setURL(CNR_CONNECTION_URL_LIVE);
|
|
460
|
+
return this;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Set OT&E System for API communication
|
|
465
|
+
* @returns Current APIClient instance for method chaining
|
|
466
|
+
*/
|
|
467
|
+
public useOTESystem(): APIClient {
|
|
468
|
+
this.setURL(CNR_CONNECTION_URL_OTE);
|
|
469
|
+
return this;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Set LIVE System for API communication (this is the default setting)
|
|
474
|
+
* @returns Current APIClient instance for method chaining
|
|
475
|
+
*/
|
|
476
|
+
public useLIVESystem(): APIClient {
|
|
477
|
+
this.setURL(CNR_CONNECTION_URL_LIVE);
|
|
478
|
+
return this;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Serialize given command for POST request including connection configuration data
|
|
483
|
+
* @param cmd API command to encode
|
|
484
|
+
* @returns encoded POST data string
|
|
485
|
+
*/
|
|
486
|
+
public getPOSTData(cmd: any, secured = false): string {
|
|
487
|
+
let data = this.socketConfig.getPOSTData();
|
|
488
|
+
if (secured) {
|
|
489
|
+
data = data.replace(/s_pw=[^&]+/, "s_pw=***");
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
let tmp = "";
|
|
493
|
+
if (!(typeof cmd === "string" || cmd instanceof String)) {
|
|
494
|
+
Object.keys(cmd).forEach((key: string) => {
|
|
495
|
+
if (cmd[key] !== null && cmd[key] !== undefined) {
|
|
496
|
+
tmp += `${key}=${cmd[key].toString().replace(/\r|\n/g, "")}\n`;
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
} else {
|
|
500
|
+
tmp = "" + cmd;
|
|
501
|
+
}
|
|
502
|
+
if (secured) {
|
|
503
|
+
tmp = tmp.replace(/PASSWORD=[^\n]+/, "PASSWORD=***");
|
|
504
|
+
}
|
|
505
|
+
tmp = tmp.replace(/\n$/, "");
|
|
506
|
+
if (Object.keys(cmd).length > 0) {
|
|
507
|
+
data += `${fixedURLEnc("s_command")}=${fixedURLEnc(tmp)}`;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
return data.endsWith("&") ? data.slice(0, -1) : data;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Flatten nested arrays in command
|
|
515
|
+
* @param cmd api command
|
|
516
|
+
* @returns api command with flattended parameters
|
|
517
|
+
*/
|
|
518
|
+
private flattenCommand(cmd: any): any {
|
|
519
|
+
const newcmd: any = {};
|
|
520
|
+
Object.keys(cmd).forEach((key: string) => {
|
|
521
|
+
const val = cmd[key];
|
|
522
|
+
const newKey = key.toUpperCase();
|
|
523
|
+
if (val !== null && val !== undefined) {
|
|
524
|
+
if (Array.isArray(val)) {
|
|
525
|
+
let index = 0;
|
|
526
|
+
for (const row of val) {
|
|
527
|
+
newcmd[`${newKey}${index}`] = (row + "").replace(/\r|\n/g, "");
|
|
528
|
+
index++;
|
|
529
|
+
}
|
|
530
|
+
} else {
|
|
531
|
+
if (typeof val === "string" || val instanceof String) {
|
|
532
|
+
newcmd[newKey] = val.replace(/\r|\n/g, "");
|
|
533
|
+
} else {
|
|
534
|
+
newcmd[newKey] = val;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
return newcmd;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Auto convert API command parameters to punycode, if necessary.
|
|
544
|
+
* @param cmd api command
|
|
545
|
+
* @returns Promise resolving with api command with IDN values replaced to punycode
|
|
546
|
+
*/
|
|
547
|
+
private async autoIDNConvert(cmd: any): Promise<any> {
|
|
548
|
+
const keyPattern = /^(NAMESERVER|NS|DNSZONE)([0-9]*)$/i;
|
|
549
|
+
const objClassPattern =
|
|
550
|
+
/^(DOMAIN(APPLICATION|BLOCKING)?|NAMESERVER|NS|DNSZONE)$/i;
|
|
551
|
+
const asciiPattern = /^[A-Za-z0-9.\-]+$/;
|
|
552
|
+
|
|
553
|
+
const toConvert: string[] = [];
|
|
554
|
+
const idxs: string[] = [];
|
|
555
|
+
|
|
556
|
+
Object.keys(cmd).forEach((key) => {
|
|
557
|
+
const val = cmd[key];
|
|
558
|
+
if (
|
|
559
|
+
(keyPattern.test(key) ||
|
|
560
|
+
(key.toUpperCase() === "OBJECTID" &&
|
|
561
|
+
cmd.OBJECTCLASS &&
|
|
562
|
+
objClassPattern.test(cmd.OBJECTCLASS))) &&
|
|
563
|
+
!asciiPattern.test(val)
|
|
564
|
+
) {
|
|
565
|
+
toConvert.push(val);
|
|
566
|
+
idxs.push(key);
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
if (toConvert.length > 0) {
|
|
571
|
+
const convertedValues = toConvert.map((value) => toAscii(value));
|
|
572
|
+
convertedValues.forEach((convertedValue, idx) => {
|
|
573
|
+
cmd[idxs[idx]] = convertedValue;
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
return cmd;
|
|
578
|
+
}
|
|
579
|
+
}
|
package/src/column.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Column class
|
|
3
|
+
*/
|
|
4
|
+
export class Column {
|
|
5
|
+
/**
|
|
6
|
+
* count of column data entries
|
|
7
|
+
*/
|
|
8
|
+
public length: number;
|
|
9
|
+
/**
|
|
10
|
+
* column key name
|
|
11
|
+
*/
|
|
12
|
+
private key: string;
|
|
13
|
+
/**
|
|
14
|
+
* column data container
|
|
15
|
+
*/
|
|
16
|
+
private data: string[];
|
|
17
|
+
|
|
18
|
+
public constructor(key: string, data: string[]) {
|
|
19
|
+
this.key = key;
|
|
20
|
+
this.data = data;
|
|
21
|
+
this.length = data.length;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get column name
|
|
26
|
+
* @returns column name
|
|
27
|
+
*/
|
|
28
|
+
public getKey(): string {
|
|
29
|
+
return this.key;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get column data
|
|
34
|
+
* @returns column data
|
|
35
|
+
*/
|
|
36
|
+
public getData(): string[] {
|
|
37
|
+
return this.data;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get column data at given index
|
|
42
|
+
* @param idx data index
|
|
43
|
+
* @returns data at given index
|
|
44
|
+
*/
|
|
45
|
+
public getDataByIndex(idx: number): string | null {
|
|
46
|
+
return this.hasDataIndex(idx) ? this.data[idx] : null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Check if column has a given data index
|
|
51
|
+
* @param idx data index
|
|
52
|
+
* @returns boolean result
|
|
53
|
+
*/
|
|
54
|
+
private hasDataIndex(idx: number): boolean {
|
|
55
|
+
return idx >= 0 && idx < this.length;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Logger } from "./logger.js";
|
|
2
|
+
import { Response } from "./response.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Logger class
|
|
6
|
+
*/
|
|
7
|
+
export class CustomLogger extends Logger {
|
|
8
|
+
/**
|
|
9
|
+
* output/log given data
|
|
10
|
+
* @param post request string used
|
|
11
|
+
* @param r Response object
|
|
12
|
+
* @param error error message or null
|
|
13
|
+
* @return current Logger instance for method chaining
|
|
14
|
+
*/
|
|
15
|
+
public log(
|
|
16
|
+
post: string,
|
|
17
|
+
r: Response,
|
|
18
|
+
error: string | null = null,
|
|
19
|
+
): CustomLogger {
|
|
20
|
+
// apply here whatever you need e.g.
|
|
21
|
+
console.log(post);
|
|
22
|
+
console.dir(r.getCommand());
|
|
23
|
+
if (error) {
|
|
24
|
+
console.error(error);
|
|
25
|
+
}
|
|
26
|
+
console.log(r.getPlain());
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { APIClient } from "./apiclient.js";
|
|
2
|
+
import { Response } from "./response.js";
|
|
3
|
+
import { ResponseTemplateManager } from "./responsetemplatemanager.js";
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
/**
|
|
7
|
+
* APIClient class
|
|
8
|
+
*/
|
|
9
|
+
APIClient,
|
|
10
|
+
/**
|
|
11
|
+
* Response class
|
|
12
|
+
*/
|
|
13
|
+
Response, // need this to replace 'applyCustomChanges'
|
|
14
|
+
/**
|
|
15
|
+
* ResponseTemplateManager class
|
|
16
|
+
*/
|
|
17
|
+
ResponseTemplateManager,
|
|
18
|
+
};
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Response } from "./response.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Logger class
|
|
5
|
+
*/
|
|
6
|
+
export class Logger {
|
|
7
|
+
/**
|
|
8
|
+
* output/log given data
|
|
9
|
+
* @param post request string used
|
|
10
|
+
* @param r Response object
|
|
11
|
+
* @param error error message or null
|
|
12
|
+
* @return current Logger instance for method chaining
|
|
13
|
+
*/
|
|
14
|
+
public log(post: string, r: Response, error: string | null = null): Logger {
|
|
15
|
+
console.dir(r.getCommand());
|
|
16
|
+
console.log(post);
|
|
17
|
+
if (error) {
|
|
18
|
+
console.error(`HTTP communication failed: ${error}`);
|
|
19
|
+
}
|
|
20
|
+
console.log(r.getPlain());
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
}
|