-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathsrc_options.js.html
443 lines (383 loc) · 16.5 KB
/
src_options.js.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: src/options.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: src/options.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>'use strict';
const HTTP_PORT = 9000;
const TCP_PORT = 9009;
const HTTP = 'http';
const HTTPS = 'https';
const TCP = 'tcp';
const TCPS = 'tcps';
const ON = 'on';
const OFF = 'off';
const UNSAFE_OFF = 'unsafe_off';
/** @classdesc
* Sender configuration options. <br>
* <br>
* Properties of the object are initialized through a configuration string. <br>
* The configuration string has the following format: <i>&ltprotocol&gt::&ltkey&gt=&ltvalue&gt;&ltkey&gt=&ltvalue&gt;...;</i> <br>
* The keys are case-sensitive, the trailing semicolon is optional. <br>
* The values are validated, and an error is thrown if the format is invalid. <br>
* <br>
* Connection and protocol options
* <ul>
* <li> <b>protocol</b>: <i>enum, accepted values: http, https, tcp, tcps</i> - The protocol used to communicate with the server. <br>
* When <i>https</i> or <i>tcps</i> used, the connection is secured with TLS encryption.
* </li>
* <li> addr: <i>string</i> - Hostname and port, separated by colon. This key is mandatory, but the port part is optional. <br>
* If no port is specified, a default will be used. <br>
* When the protocol is HTTP/HTTPS, the port defaults to 9000. When the protocol is TCP/TCPS, the port defaults to 9009. <br>
* Examples: <i>http::addr=localhost:9000</i>, <i>https::addr=localhost:9000</i>, <i>http::addr=localhost</i>, <i>tcp::addr=localhost:9009</i>
* </li>
* </ul>
* <br>
* Authentication options
* <ul>
* <li> username: <i>string</i> - Used for authentication. <br>
* In case of HTTP Basic authentication should be accompanied by the <i>password</i> option. <br>
* If the TCP transport used with JWK token authentication, then should be accompanied by the <i>token</i> option.
* </li>
* <li> password: <i>string</i> - Password for HTTP Basic authentication, should be accompanied by the <i>username</i> option.
* </li>
* <li> token: <i>string</i> - In case of HTTP Bearer token authentication it contains the bearer token. <br>
* If the TCP transport used with JWK token authentication, then it contains the private key part of the JWK token,
* and it should be accompanied by the <i>username</i> option.
* </li>
* </ul>
* <br>
* TLS options
* <ul>
* <li> tls_verify: <i>enum, accepted values: on, unsafe_off</i> - When the HTTPS or TCPS protocols are selected, TLS encryption is used. <br>
* The Sender verifies the server's certificate, this check can be disabled by setting this option to <i>off</i>. Can be useful in
* non-production environments where self-signed certificates might be used, but generally not recommended to use.
* </li>
* <li> tls_ca: <i>string</i> - Path to a file containing the root CA's certificate in PEM format. <br>
* Can be useful when self-signed certificates are used, otherwise should not be set.
* </li>
* </ul>
* <br>
* Auto flush options
* <ul>
* <li> auto_flush: <i>enum, accepted values: on, off</i> - The Sender automatically flushes the buffer by default, this can be switched off
* by setting this option to <i>off</i>. <br>
* When disabled, the flush() method of the Sender has to be called explicitly to make sure data is sent to the server.
* </li>
* <li> auto_flush_rows: <i>integer</i> - The number of rows that will trigger a flush. When set to 0, row-based flushing is disabled. <br>
* The Sender will default this parameter to 75000 rows when HTTP protocol is used, and to 600 in case of TCP protocol.
* </li>
* <li> auto_flush_interval: <i>integer</i> - The number of milliseconds that will trigger a flush, default value is 1000.
* When set to 0, interval-based flushing is disabled. <br>
* Note that the setting is checked only when a new row is added to the buffer. There is no timer registered to flush the buffer automatically.
* </li>
* </ul>
* <br>
* Buffer sizing options
* <ul>
* <li> init_buf_size: <i>integer</i> - Initial buffer size, defaults to 64 KiB in the Sender.
* </li>
* <li> max_buf_size: <i>integer</i> - Maximum buffer size, defaults to 100 MiB in the Sender. <br>
* If the buffer would need to be extended beyond the maximum size, an error is thrown.
* </li>
* </ul>
* <br>
* HTTP request specific options
* <ul>
* <li> request_timeout: <i>integer</i> - The time in milliseconds to wait for a response from the server, set to 10 seconds by default. <br>
* This is in addition to the calculation derived from the <i>request_min_throughput</i> parameter.
* </li>
* <li> request_min_throughput: <i>integer</i> - Minimum expected throughput in bytes per second for HTTP requests, set to 100 KiB/s seconds by default. <br>
* If the throughput is lower than this value, the connection will time out. This is used to calculate an additional
* timeout on top of <i>request_timeout</i>. This is useful for large requests. You can set this value to 0 to disable this logic.
* </li>
* <li> retry_timeout: <i>integer</i> - The time in milliseconds to continue retrying after a failed HTTP request, set to 10 seconds by default. <br>
* The interval between retries is an exponential backoff starting at 10ms and doubling after each failed attempt up to a maximum of 1 second.
* </li>
* </ul>
* <br>
* Other options
* <ul>
* <li> max_name_len: <i>integer</i> - The maximum length of a table or column name, the Sender defaults this parameter to 127. <br>
* Recommended to use the same setting as the server, which also uses 127 by default.
* </li>
* <li> copy_buffer: <i>enum, accepted values: on, off</i> - By default the Sender creates a new buffer for every flush() call,
* and the data to be sent to the server is copied into this new buffer.
* Setting the flag to <i>off</i> results in reusing the same buffer instance for each flush() call. <br>
* Use this flag only if calls to the client are serialised.
* </li>
* </ul>
*/
class SenderOptions {
protocol;
addr;
host; // derived from addr
port; // derived from addr
// replaces `auth` and `jwk` options
username;
password;
token;
token_x; // allowed, but ignored
token_y; // allowed, but ignored
auto_flush;
auto_flush_rows;
auto_flush_interval;
// replaces `copyBuffer` option
copy_buffer;
request_min_throughput;
request_timeout;
retry_timeout;
// replaces `bufferSize` option
init_buf_size;
max_buf_size;
tls_verify;
tls_ca;
tls_roots; // not supported
tls_roots_password; // not supported
max_name_len;
log;
/**
* Creates a Sender options object by parsing the provided configuration string.
*
* @param {string} configurationString - Configuration string. <br>
* @param {function} log - Optional logging function used by the Sender. <br>
* Prototype: <i>(level: 'error'|'warn'|'info'|'debug', message: string) => void<i>.
*/
constructor(configurationString, log = undefined) {
parseConfigurationString(configurationString);
if (log && typeof log !== 'function') {
throw new Error('Invalid logging function');
}
this.log = log;
}
/**
* Creates a Sender options object by parsing the provided configuration string.
*
* @param {string} configurationString - Configuration string. <br>
* @param {function} log - Optional logging function used by the Sender. <br>
* Prototype: <i>(level: 'error'|'warn'|'info'|'debug', message: string) => void<i>. <br>
*
* @return {SenderOptions} An instance of the Sender configuration object initialized from the provided configuration string.
*/
static fromConfig(configurationString, log = undefined) {
return new SenderOptions(configurationString, log);
}
/**
* Creates a Sender options object by parsing the configuration string set in the QDB_CLIENT_CONF environment variable.
*
* @param {function} log - Optional logging function used by the Sender. <br>
* Prototype: <i>(level: 'error'|'warn'|'info'|'debug', message: string) => void<i>. <br>
*
* @return {SenderOptions} An instance of the Sender configuration object initialized from the QDB_CLIENT_CONF environment variable.
*/
static fromEnv(log = undefined) {
return SenderOptions.fromConfig(process.env.QDB_CLIENT_CONF, log);
}
}
function parseConfigurationString(options, configString) {
if (!configString) {
throw new Error('Configuration string is missing or empty');
}
const position = parseProtocol(options, configString);
parseSettings(options, configString, position);
parseAddress(options);
parseBufferSizes(options);
parseAutoFlushOptions(options);
parseTlsOptions(options);
parseRequestTimeoutOptions(options);
parseMaxNameLength(options);
parseCopyBuffer(options);
}
function parseSettings(options, configString, position) {
let index = configString.indexOf(';', position);
while (index > -1) {
if (index + 1 < configString.length && configString.charAt(index + 1) === ';') {
index = configString.indexOf(';', index + 2);
continue;
}
parseSetting(options, configString, position, index);
position = index + 1;
index = configString.indexOf(';', position);
}
if (position < configString.length) {
parseSetting(options, configString, position, configString.length);
}
}
function parseSetting(options, configString, position, index) {
const setting = configString.slice(position, index).replaceAll(';;', ';');
const equalsIndex = setting.indexOf('=');
if (equalsIndex < 0) {
throw new Error(`Missing \'=\' sign in \'${setting}\'`);
}
const key = setting.slice(0, equalsIndex);
const value = setting.slice(equalsIndex + 1);
validateConfigKey(key);
validateConfigValue(key, value);
options[key] = value;
}
const ValidConfigKeys = [
'addr',
'username', 'password', 'token', 'token_x', 'token_y',
'auto_flush', 'auto_flush_rows', 'auto_flush_interval',
'copy_buffer',
'request_min_throughput', 'request_timeout', 'retry_timeout',
'init_buf_size', 'max_buf_size',
'max_name_len',
'tls_verify', 'tls_ca', 'tls_roots', 'tls_roots_password'
];
function validateConfigKey(key) {
if (!ValidConfigKeys.includes(key)) {
throw new Error(`Unknown configuration key: \'${key}\'`);
}
}
function validateConfigValue(key, value) {
if (!value) {
throw new Error(`Invalid configuration, value is not set for \'${key}\'`);
}
for (let i = 0; i < value.length; i++) {
const unicode = value.codePointAt(i);
if (unicode < 0x20 || (unicode > 0x7E && unicode < 0xA0)) {
throw new Error(`Invalid configuration, control characters are not allowed: \'${value}\'`);
}
}
}
function parseProtocol(options, configString) {
let index = configString.indexOf('::');
if (index < 0) {
throw new Error('Missing protocol, configuration string format: \'protocol::key1=value1;key2=value2;key3=value3;\'');
}
options.protocol = configString.slice(0, index);
switch (options.protocol) {
case HTTP:
case HTTPS:
case TCP:
case TCPS:
break;
default:
throw new Error(`Invalid protocol: \'${options.protocol}\', accepted protocols: \'http\', \'https\', \'tcp\', \'tcps\'`);
}
return index + 2;
}
function parseAddress(options) {
if (!options.addr) {
throw new Error('Invalid configuration, \'addr\' is required');
}
const index = options.addr.indexOf(':');
if (index < 0) {
options.host = options.addr;
switch (options.protocol) {
case HTTP:
case HTTPS:
options.port = HTTP_PORT;
return;
case TCP:
case TCPS:
options.port = TCP_PORT;
return;
default:
throw new Error(`Invalid protocol: \'${options.protocol}\', accepted protocols: \'http\', \'https\', \'tcp\', \'tcps\'`);
}
}
options.host = options.addr.slice(0, index);
if (!options.host) {
throw new Error(`Host name is required`);
}
const portStr = options.addr.slice(index + 1);
if (!portStr) {
throw new Error(`Port is required`);
}
options.port = Number(portStr);
if (isNaN(options.port)) {
throw new Error(`Invalid port: \'${portStr}\'`);
}
if (!Number.isInteger(options.port) || options.port < 1) {
throw new Error(`Invalid port: ${options.port}`);
}
}
function parseBufferSizes(options) {
parseInteger(options, 'init_buf_size', 'initial buffer size', 1);
parseInteger(options, 'max_buf_size', 'max buffer size', 1);
}
function parseAutoFlushOptions(options) {
parseBoolean(options, 'auto_flush', 'auto flush');
parseInteger(options, 'auto_flush_rows', 'auto flush rows', 0);
parseInteger(options, 'auto_flush_interval', 'auto flush interval', 0);
}
function parseTlsOptions(options) {
parseBoolean(options, 'tls_verify', 'TLS verify', UNSAFE_OFF);
if (options.tls_roots || options.tls_roots_password) {
throw new Error('\'tls_roots\' and \'tls_roots_password\' options are not supported, please, ' +
'use the \'tls_ca\' option or the NODE_EXTRA_CA_CERTS environment variable instead');
}
}
function parseRequestTimeoutOptions(options) {
parseInteger(options, 'request_min_throughput', 'request min throughput', 1);
parseInteger(options, 'request_timeout', 'request timeout', 1);
parseInteger(options, 'retry_timeout', 'retry timeout', 0);
}
function parseMaxNameLength(options) {
parseInteger(options, 'max_name_len', 'max name length', 1);
}
function parseCopyBuffer(options) {
parseBoolean(options, 'copy_buffer', 'copy buffer');
}
function parseBoolean(options, property, description, offValue = OFF) {
if (options[property]) {
const property_str = options[property];
switch (property_str) {
case ON:
options[property] = true;
break;
case offValue:
options[property] = false;
break;
default:
throw new Error(`Invalid ${description} option: \'${property_str}\'`);
}
}
}
function parseInteger(options, property, description, lowerBound) {
if (options[property]) {
const property_str = options[property];
options[property] = Number(property_str);
if (isNaN(options[property])) {
throw new Error(`Invalid ${description} option, not a number: \'${property_str}\'`);
}
if (!Number.isInteger(options[property]) || options[property] < lowerBound) {
throw new Error(`Invalid ${description} option: ${options[property]}`);
}
}
}
exports.SenderOptions = SenderOptions;
exports.HTTP = HTTP;
exports.HTTPS = HTTPS;
exports.TCP = TCP;
exports.TCPS = TCPS;
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-@questdb_nodejs-client.html">@questdb/nodejs-client</a></li></ul><h3>Classes</h3><ul><li><a href="Sender.html">Sender</a></li><li><a href="SenderOptions.html">SenderOptions</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.2</a> on Wed Apr 17 2024 03:38:42 GMT+0100 (British Summer Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>