dolphindb 0.0.1

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/browser.js ADDED
@@ -0,0 +1,1140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ddb = exports.DDB = exports.DdbFunction = exports.DdbPair = exports.DdbVectorAny = exports.DdbVectorDouble = exports.DdbVectorString = exports.DdbVectorInt = exports.DdbDouble = exports.DdbLong = exports.DdbString = exports.DdbInt = exports.DdbBool = exports.DdbObj = exports.nulls = exports.DdbFunctionType = exports.DdbType = exports.DdbForm = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const dayjs_1 = (0, tslib_1.__importDefault)(require("dayjs"));
6
+ require("xshell/prototype.browser");
7
+ const utils_browser_1 = require("xshell/utils.browser");
8
+ const chalk_browser_1 = require("xshell/chalk.browser");
9
+ var DdbForm;
10
+ (function (DdbForm) {
11
+ DdbForm[DdbForm["scalar"] = 0] = "scalar";
12
+ DdbForm[DdbForm["vector"] = 1] = "vector";
13
+ DdbForm[DdbForm["pair"] = 2] = "pair";
14
+ DdbForm[DdbForm["matrix"] = 3] = "matrix";
15
+ DdbForm[DdbForm["set"] = 4] = "set";
16
+ DdbForm[DdbForm["dict"] = 5] = "dict";
17
+ DdbForm[DdbForm["table"] = 6] = "table";
18
+ DdbForm[DdbForm["chart"] = 7] = "chart";
19
+ DdbForm[DdbForm["chunk"] = 8] = "chunk";
20
+ })(DdbForm = exports.DdbForm || (exports.DdbForm = {}));
21
+ var DdbType;
22
+ (function (DdbType) {
23
+ DdbType[DdbType["void"] = 0] = "void";
24
+ DdbType[DdbType["bool"] = 1] = "bool";
25
+ DdbType[DdbType["char"] = 2] = "char";
26
+ DdbType[DdbType["short"] = 3] = "short";
27
+ DdbType[DdbType["int"] = 4] = "int";
28
+ DdbType[DdbType["long"] = 5] = "long";
29
+ DdbType[DdbType["date"] = 6] = "date";
30
+ DdbType[DdbType["month"] = 7] = "month";
31
+ DdbType[DdbType["time"] = 8] = "time";
32
+ DdbType[DdbType["minute"] = 9] = "minute";
33
+ DdbType[DdbType["second"] = 10] = "second";
34
+ DdbType[DdbType["datetime"] = 11] = "datetime";
35
+ DdbType[DdbType["timestamp"] = 12] = "timestamp";
36
+ DdbType[DdbType["nanotime"] = 13] = "nanotime";
37
+ DdbType[DdbType["nanotimestamp"] = 14] = "nanotimestamp";
38
+ DdbType[DdbType["float"] = 15] = "float";
39
+ DdbType[DdbType["double"] = 16] = "double";
40
+ DdbType[DdbType["symbol"] = 17] = "symbol";
41
+ DdbType[DdbType["string"] = 18] = "string";
42
+ DdbType[DdbType["uuid"] = 19] = "uuid";
43
+ DdbType[DdbType["functiondef"] = 20] = "functiondef";
44
+ DdbType[DdbType["handle"] = 21] = "handle";
45
+ DdbType[DdbType["code"] = 22] = "code";
46
+ DdbType[DdbType["datasource"] = 23] = "datasource";
47
+ DdbType[DdbType["resource"] = 24] = "resource";
48
+ DdbType[DdbType["any"] = 25] = "any";
49
+ DdbType[DdbType["compress"] = 26] = "compress";
50
+ DdbType[DdbType["dict"] = 27] = "dict";
51
+ DdbType[DdbType["datehour"] = 28] = "datehour";
52
+ DdbType[DdbType["ipaddr"] = 30] = "ipaddr";
53
+ DdbType[DdbType["int128"] = 31] = "int128";
54
+ DdbType[DdbType["blob"] = 32] = "blob";
55
+ DdbType[DdbType["complex"] = 34] = "complex";
56
+ DdbType[DdbType["point"] = 35] = "point";
57
+ DdbType[DdbType["duration"] = 36] = "duration";
58
+ DdbType[DdbType["symbol_extended"] = 145] = "symbol_extended";
59
+ })(DdbType = exports.DdbType || (exports.DdbType = {}));
60
+ var DdbFunctionType;
61
+ (function (DdbFunctionType) {
62
+ DdbFunctionType[DdbFunctionType["SystemFunc"] = 0] = "SystemFunc";
63
+ DdbFunctionType[DdbFunctionType["SystemProc"] = 1] = "SystemProc";
64
+ DdbFunctionType[DdbFunctionType["OperatorFunc"] = 2] = "OperatorFunc";
65
+ DdbFunctionType[DdbFunctionType["UserDefinedFunc"] = 3] = "UserDefinedFunc";
66
+ DdbFunctionType[DdbFunctionType["PartialFunc"] = 4] = "PartialFunc";
67
+ DdbFunctionType[DdbFunctionType["DynamicFunc"] = 5] = "DynamicFunc";
68
+ DdbFunctionType[DdbFunctionType["PiecewiseFunc"] = 6] = "PiecewiseFunc";
69
+ DdbFunctionType[DdbFunctionType["JitFunc"] = 7] = "JitFunc";
70
+ DdbFunctionType[DdbFunctionType["JitPartialFunc"] = 8] = "JitPartialFunc";
71
+ })(DdbFunctionType = exports.DdbFunctionType || (exports.DdbFunctionType = {}));
72
+ exports.nulls = {
73
+ char: '\x80',
74
+ int16: -32768,
75
+ int32: -2147483648,
76
+ int64: -0x8000000000000000n, // -922_3372_0368_5477_5808
77
+ };
78
+ class DdbObj {
79
+ constructor(data) {
80
+ /** 是否为小端 (little endian) */
81
+ this.le = DdbObj.le_client;
82
+ Object.assign(this, data);
83
+ }
84
+ static parse(buf, le) {
85
+ if (!buf.length)
86
+ return new this({
87
+ le,
88
+ form: DdbForm.scalar,
89
+ type: DdbType.void,
90
+ length: 0,
91
+ value: undefined
92
+ });
93
+ const type = buf[0];
94
+ const form = buf[1];
95
+ if (buf.length <= 2) {
96
+ return new this({
97
+ le,
98
+ form,
99
+ type,
100
+ length: 2,
101
+ value: null,
102
+ });
103
+ }
104
+ // set 里面 data 嵌套了一个 vector, 跳过 vector 的 type 和 form
105
+ const i_data = form === DdbForm.set ? 4 : 2;
106
+ const buf_data = buf.subarray(i_data);
107
+ switch (form) {
108
+ case DdbForm.scalar: {
109
+ const [length, value] = this.parse_scalar(buf_data, le, type);
110
+ return new this({
111
+ le,
112
+ form,
113
+ type,
114
+ length: 2 + length,
115
+ value,
116
+ });
117
+ }
118
+ case DdbForm.vector:
119
+ case DdbForm.pair:
120
+ case DdbForm.set: {
121
+ let vector = this.parse_vector(buf_data, le, type);
122
+ vector.length += 2;
123
+ vector.form = form;
124
+ return vector;
125
+ }
126
+ case DdbForm.table: {
127
+ // table([
128
+ // [1, 2] as a,
129
+ // [1, 2] as b
130
+ // ])
131
+ // <Buffer
132
+ // 00 06 form = table
133
+ // 02 00 00 00 02 00 00 00 rows = 2, cols = 2
134
+ // 00 行名称
135
+ // 61 00 62 00 列名称 a, b
136
+ // 04 01 form = vector, type = int
137
+ // 02 00 00 00 01 00 00 00 cols = 2, rows = 1
138
+ // 01 00 00 00 02 00 00 00
139
+ // 04 01
140
+ // 02 00 00 00 01 00 00 00
141
+ // 01 00 00 00 02 00 00 00>
142
+ const dv = new DataView(buf.buffer, buf.byteOffset + i_data);
143
+ const rows = dv.getUint32(0, le);
144
+ const cols = dv.getUint32(4, le);
145
+ const i_name_tail = buf_data.indexOf(0, 8);
146
+ const name = this.dec.decode(buf_data.subarray(8, i_name_tail));
147
+ const i_items_start = i_name_tail + 1;
148
+ const [len_items, colnames] = this.parse_vector_items(buf_data.subarray(i_items_start), le, DdbType.string, cols);
149
+ let value = new Array(cols);
150
+ let i_start = i_items_start + len_items;
151
+ for (let i = 0; i < cols; i++) {
152
+ const type = buf_data[i_start];
153
+ const i_vector_head = i_start + 2;
154
+ let col = this.parse_vector(buf_data.subarray(i_vector_head), le, type);
155
+ col.name = colnames[i];
156
+ value[i] = col;
157
+ i_start = i_vector_head + col.length;
158
+ }
159
+ return new this({
160
+ le,
161
+ form,
162
+ type,
163
+ length: i_start,
164
+ name,
165
+ rows,
166
+ cols,
167
+ value,
168
+ });
169
+ }
170
+ case DdbForm.dict: {
171
+ // <Buffer 19 05 type = any, form = dict
172
+ // 12 01 keys.type = string, keys.form = vector
173
+ // 03 00 00 00 01 00 00 00 keys.cols = 3, keys.rows = 1
174
+ // 63 00 62 00 61 00
175
+ // 19 01 values.type = any, values.form = vector
176
+ // 03 00 00 00 01 00 00 00 values.cols = 3, values.rows = 1
177
+ // 04 00 03 00 00 00 04 00 02 00 00 00 04 00 01 00 00 00>
178
+ let keys = this.parse_vector(buf_data.subarray(2), le, buf_data[0]);
179
+ keys.length += 2;
180
+ let values = this.parse_vector(buf_data.subarray(keys.length + 2), le, buf_data[keys.length]);
181
+ values.length += 2;
182
+ return new this({
183
+ le,
184
+ form,
185
+ type,
186
+ length: 2 + keys.length + values.length,
187
+ rows: keys.rows,
188
+ cols: 2,
189
+ value: [
190
+ keys,
191
+ values
192
+ ],
193
+ });
194
+ }
195
+ case DdbForm.matrix: {
196
+ // matrix([
197
+ // [1, 2, 3],
198
+ // [3, 2, 1]
199
+ // ])
200
+ // <Buffer 00 has_row_label = , has_col_label =
201
+ // 04 03 type = int, form = matrix
202
+ // 03 00 00 00 02 00 00 00 rows = 3, cols = 2
203
+ // 01 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 02 00 00 00 01 00 00 00>
204
+ const dv = new DataView(buf.buffer, buf.byteOffset + i_data);
205
+ const label_flags = buf_data[0];
206
+ const has_row_labels = Boolean(label_flags & 0x01);
207
+ const has_col_labels = Boolean(label_flags & 0x02);
208
+ if (has_row_labels || has_col_labels)
209
+ throw new Error('matrix 暂不支持 row labels 和 col labels');
210
+ const datatype = buf_data[1];
211
+ const rows = dv.getUint32(3, le);
212
+ const cols = dv.getUint32(7, le);
213
+ const [len_items, value] = this.parse_vector_items(buf_data.subarray(11), le, datatype, rows * cols // 假设小于 2**32
214
+ );
215
+ return new this({
216
+ le,
217
+ form,
218
+ type,
219
+ length: 11 + len_items,
220
+ rows,
221
+ cols,
222
+ datatype,
223
+ value,
224
+ });
225
+ }
226
+ default:
227
+ return new this({
228
+ le,
229
+ form,
230
+ type,
231
+ length: buf_data.length,
232
+ value: buf_data
233
+ });
234
+ }
235
+ }
236
+ static parse_scalar(buf, le, type) {
237
+ switch (type) {
238
+ case DdbType.void:
239
+ return [1, null];
240
+ case DdbType.bool:
241
+ return [1, Boolean(buf[0])];
242
+ case DdbType.char:
243
+ return [1, String.fromCharCode(buf[0])];
244
+ case DdbType.short: {
245
+ const dv = new DataView(buf.buffer, buf.byteOffset);
246
+ return [2, dv.getInt16(0, le)];
247
+ }
248
+ case DdbType.int:
249
+ // datetime
250
+ case DdbType.date:
251
+ case DdbType.month:
252
+ case DdbType.time:
253
+ case DdbType.minute:
254
+ case DdbType.second:
255
+ case DdbType.datetime:
256
+ case DdbType.datehour: {
257
+ const dv = new DataView(buf.buffer, buf.byteOffset);
258
+ return [4, dv.getInt32(0, le)];
259
+ }
260
+ case DdbType.float: {
261
+ const dv = new DataView(buf.buffer, buf.byteOffset);
262
+ return [4, dv.getFloat32(0, le)];
263
+ }
264
+ case DdbType.double: {
265
+ const dv = new DataView(buf.buffer, buf.byteOffset);
266
+ return [8, dv.getFloat64(0, le)];
267
+ }
268
+ case DdbType.long:
269
+ // timestamp
270
+ case DdbType.timestamp:
271
+ case DdbType.nanotime:
272
+ case DdbType.nanotimestamp: {
273
+ const dv = new DataView(buf.buffer, buf.byteOffset);
274
+ return [8, dv.getBigInt64(0, le)];
275
+ }
276
+ case DdbType.string:
277
+ case DdbType.symbol:
278
+ case DdbType.code:
279
+ case DdbType.functiondef: {
280
+ const i_head = type === DdbType.functiondef ? 1 : 0;
281
+ let i_zero = buf.indexOf(0, i_head);
282
+ let i_end; // 整个字符串(包括 0)的末尾,excluding
283
+ if (i_zero === -1)
284
+ i_end = i_zero = buf.length;
285
+ else
286
+ i_end = i_zero + 1;
287
+ // 调整了 i_zero 到字符串(不包括 0)的末尾,excluding
288
+ const str = this.dec.decode(buf.subarray(i_head, i_zero));
289
+ return [
290
+ i_end,
291
+ type === DdbType.functiondef ?
292
+ {
293
+ type: buf[0],
294
+ name: str
295
+ }
296
+ :
297
+ str
298
+ ];
299
+ }
300
+ case DdbType.uuid:
301
+ case DdbType.ipaddr:
302
+ case DdbType.int128:
303
+ return [
304
+ 16,
305
+ buf.slice(0, 16)
306
+ ];
307
+ case DdbType.blob: {
308
+ const dv = new DataView(buf.buffer, buf.byteOffset);
309
+ const length = dv.getUint32(0, le);
310
+ return [
311
+ 4 + length,
312
+ buf.slice(4, 4 + length)
313
+ ];
314
+ }
315
+ case DdbType.complex:
316
+ case DdbType.point: {
317
+ const dv = new DataView(buf.buffer, buf.byteOffset);
318
+ return [
319
+ 16,
320
+ [
321
+ dv.getFloat64(0, le),
322
+ dv.getFloat64(8, le)
323
+ ]
324
+ ];
325
+ }
326
+ default:
327
+ return [0, buf];
328
+ }
329
+ }
330
+ /** parse: rows, cols, items
331
+ 返回的 ddbobj.length 不包括 vector 的 type 和 form
332
+ */
333
+ static parse_vector(buf, le, type) {
334
+ const dv = new DataView(buf.buffer, buf.byteOffset);
335
+ const rows = dv.getUint32(0, le);
336
+ const i_items_start = 8;
337
+ const [len_items, value] = this.parse_vector_items(buf.subarray(i_items_start), le, type, rows);
338
+ return new this({
339
+ le,
340
+ form: DdbForm.vector,
341
+ type,
342
+ length: i_items_start + len_items,
343
+ cols: 1,
344
+ rows,
345
+ value,
346
+ });
347
+ }
348
+ /** 有可能没有字节对齐,不能直接使用原有 message 的 arraybuffer, 统一复制出来,让原有 arraybuffer 被回收掉比较好 */
349
+ static parse_vector_items(buf, le, type, length) {
350
+ switch (type) {
351
+ case DdbType.bool:
352
+ return [length, buf.slice(0, length)];
353
+ case DdbType.char:
354
+ return [
355
+ length,
356
+ this.dec.decode(buf.subarray(0, length))
357
+ ];
358
+ case DdbType.short:
359
+ return [
360
+ 2 * length,
361
+ new Int16Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + 2 * length))
362
+ ];
363
+ case DdbType.int:
364
+ // datetime
365
+ case DdbType.date:
366
+ case DdbType.month:
367
+ case DdbType.time:
368
+ case DdbType.minute:
369
+ case DdbType.second:
370
+ case DdbType.datetime:
371
+ return [
372
+ 4 * length,
373
+ new Int32Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + 4 * length))
374
+ ];
375
+ case DdbType.float:
376
+ return [
377
+ 4 * length,
378
+ new Float32Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + 4 * length))
379
+ ];
380
+ case DdbType.double:
381
+ return [
382
+ 8 * length,
383
+ new Float64Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + 8 * length))
384
+ ];
385
+ case DdbType.long:
386
+ // timestamp
387
+ case DdbType.timestamp:
388
+ case DdbType.nanotime:
389
+ case DdbType.nanotimestamp:
390
+ return [
391
+ 8 * length,
392
+ new BigInt64Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + 8 * length))
393
+ ];
394
+ case DdbType.string:
395
+ case DdbType.symbol:
396
+ case DdbType.code: {
397
+ let value = new Array(length);
398
+ let i_head = 0, i_tail = i_head;
399
+ for (let i = 0; i < length; i++) {
400
+ i_tail = buf.indexOf(0, i_head);
401
+ value[i] = this.dec.decode(buf.subarray(i_head, i_tail));
402
+ i_head = i_tail + 1;
403
+ }
404
+ return [i_head, value];
405
+ }
406
+ case DdbType.symbol_extended: {
407
+ // <Buffer 91 01 type = symbol extended, form = vector
408
+ // 05 00 00 00 01 00 00 00 row = 5, col = 1
409
+ // buf:
410
+ // 00 00 00 00 symbol base id = 0 (uint32)
411
+ // 02 00 00 00 symbol base size = 2
412
+ // 00 61 61 00 以 \0 分割的字符串
413
+ // 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00>
414
+ const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
415
+ const base_id = dv.getUint32(0, le);
416
+ const base_size = dv.getUint32(4, le);
417
+ let base_length = 0;
418
+ let base = this.symbol_bases[base_id];
419
+ // base_size 为 0 时复用之前的 symbol base
420
+ if (base_size) {
421
+ [base_length, base] = this.parse_vector_items(buf.subarray(8), le, DdbType.string, base_size);
422
+ this.symbol_bases[base_id] = base;
423
+ }
424
+ const value_start = 8 + base_length;
425
+ const value_end = value_start + length * 4;
426
+ const value = new Uint32Array(buf.buffer.slice(buf.byteOffset + value_start, buf.byteOffset + value_end));
427
+ return [
428
+ value_end,
429
+ {
430
+ base_id,
431
+ base,
432
+ value
433
+ }
434
+ ];
435
+ }
436
+ case DdbType.uuid:
437
+ case DdbType.ipaddr:
438
+ case DdbType.int128:
439
+ return [
440
+ 16 * length,
441
+ new Uint8Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + 16 * length))
442
+ ];
443
+ case DdbType.blob: {
444
+ // <Buffer 20 01 type = blob, form = vector
445
+ // 02 00 00 00 01 00 00 00 cols = 2, rows = 1
446
+ // 04 00 00 00 61 62 63 64
447
+ // 04 00 00 00 61 62 63 64>
448
+ let value = new Array(length);
449
+ const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
450
+ let i_head = 0;
451
+ for (let i = 0; i < length; i++) {
452
+ const sublen = dv.getUint32(i_head, le);
453
+ const i_blob_head = i_head + 4;
454
+ const i_blob_tail = i_blob_head + sublen;
455
+ value[i] = buf.slice(i_blob_head, i_blob_tail);
456
+ i_head = i_blob_tail;
457
+ }
458
+ return [i_head, value];
459
+ }
460
+ case DdbType.complex:
461
+ case DdbType.point:
462
+ return [
463
+ 16 * length,
464
+ new Float64Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + 16 * length))
465
+ ];
466
+ case DdbType.any: {
467
+ // [1, 2, 'a', 'aaa']
468
+ // any[4](<Buffer
469
+ // 04 00 DdbType.int, DdbForm.scalar
470
+ // 01 00 00 00
471
+ // 04 00 DdbType.int, DdbForm.scalar
472
+ // 02 00 00 00
473
+ // 02 00 DdbType.char, DdbForm.scalar
474
+ // 61
475
+ // 12 00 DdbType.string, DdbForm.scalar
476
+ // 61 61 61 00>)
477
+ let values = new Array(length);
478
+ let i_head = 0;
479
+ for (let i = 0; i < length; i++) {
480
+ const obj = this.parse(buf.subarray(i_head), le);
481
+ values[i] = obj;
482
+ i_head += obj.length;
483
+ }
484
+ return [
485
+ i_head,
486
+ values
487
+ ];
488
+ }
489
+ default:
490
+ return [0, buf];
491
+ }
492
+ }
493
+ pack() {
494
+ const { form, type, value } = this;
495
+ let header = new Uint8Array(new ArrayBuffer(2));
496
+ header[0] = type;
497
+ header[1] = form;
498
+ const body = (() => {
499
+ switch (form) {
500
+ case DdbForm.scalar:
501
+ switch (type) {
502
+ case DdbType.void:
503
+ return [Uint8Array.of(1)];
504
+ case DdbType.bool:
505
+ return [Uint8Array.of(Number(value))];
506
+ case DdbType.char:
507
+ return [Uint8Array.of(value.charCodeAt(0))];
508
+ case DdbType.short:
509
+ return [Int16Array.of(value)];
510
+ case DdbType.int:
511
+ // datetime
512
+ case DdbType.date:
513
+ case DdbType.month:
514
+ case DdbType.time:
515
+ case DdbType.minute:
516
+ case DdbType.second:
517
+ case DdbType.datetime:
518
+ case DdbType.datehour:
519
+ return [Int32Array.of(value)];
520
+ case DdbType.float:
521
+ return [Float32Array.of(value)];
522
+ case DdbType.double:
523
+ return [Float64Array.of(value)];
524
+ case DdbType.long:
525
+ // timestamp
526
+ case DdbType.timestamp:
527
+ case DdbType.nanotime:
528
+ case DdbType.nanotimestamp:
529
+ return [BigInt64Array.of(this.value)];
530
+ case DdbType.string:
531
+ case DdbType.symbol:
532
+ case DdbType.code:
533
+ return [
534
+ DdbObj.enc.encode(value),
535
+ Uint8Array.of(0),
536
+ ];
537
+ case DdbType.functiondef:
538
+ return [
539
+ Uint8Array.of(value.type),
540
+ DdbObj.enc.encode(value.name),
541
+ Uint8Array.of(0)
542
+ ];
543
+ case DdbType.uuid:
544
+ case DdbType.ipaddr:
545
+ case DdbType.int128:
546
+ return [this.value];
547
+ case DdbType.blob:
548
+ return [
549
+ Uint32Array.of(this.value.byteLength),
550
+ this.value
551
+ ];
552
+ case DdbType.complex:
553
+ case DdbType.point:
554
+ return [Float64Array.from(this.value)];
555
+ case DdbType.duration:
556
+ return [value];
557
+ default:
558
+ throw new Error(`${DdbType[type]} 暂时不支持序列化`);
559
+ }
560
+ case DdbForm.vector:
561
+ case DdbForm.pair:
562
+ return [
563
+ Uint32Array.of(this.rows, 1),
564
+ ...DdbObj.pack_vector_body(value, type, this.rows)
565
+ ];
566
+ case DdbForm.set:
567
+ return [
568
+ new DdbObj({
569
+ ...this,
570
+ form: DdbForm.vector,
571
+ }).pack()
572
+ ];
573
+ case DdbForm.table:
574
+ return [
575
+ Uint32Array.of(this.rows, this.cols),
576
+ DdbObj.enc.encode(this.name),
577
+ Uint8Array.of(0),
578
+ ...DdbObj.pack_vector_body(this.value.map(col => col.name), DdbType.string, this.cols),
579
+ ...(() => {
580
+ let cols = new Array(this.cols);
581
+ for (let i = 0; i < cols.length; i++)
582
+ cols[i] = this.value[i].pack();
583
+ return cols;
584
+ })()
585
+ ];
586
+ case DdbForm.dict:
587
+ return [
588
+ value[0].pack(),
589
+ value[1].pack(),
590
+ ];
591
+ case DdbForm.matrix:
592
+ return [
593
+ Uint8Array.of(0, this.datatype, this.form),
594
+ Uint32Array.of(this.rows, this.cols),
595
+ ...DdbObj.pack_vector_body(value, this.datatype, this.rows * this.cols)
596
+ ];
597
+ default:
598
+ throw new Error(`${DdbForm[form]} 暂不支持序列化`);
599
+ }
600
+ })();
601
+ if (!body)
602
+ return new Uint8Array(0);
603
+ return (0, utils_browser_1.concat)([
604
+ header,
605
+ ...body
606
+ ]);
607
+ }
608
+ static pack_vector_body(value, type, length) {
609
+ switch (type) {
610
+ case DdbType.bool:
611
+ return [value];
612
+ case DdbType.char:
613
+ return [this.enc.encode(value)];
614
+ case DdbType.short:
615
+ return [value];
616
+ case DdbType.int:
617
+ // datetime
618
+ case DdbType.date:
619
+ case DdbType.month:
620
+ case DdbType.time:
621
+ case DdbType.minute:
622
+ case DdbType.second:
623
+ case DdbType.datetime:
624
+ return [value];
625
+ case DdbType.float:
626
+ return [value];
627
+ case DdbType.double:
628
+ return [value];
629
+ case DdbType.long:
630
+ // timestamp
631
+ case DdbType.timestamp:
632
+ case DdbType.nanotime:
633
+ case DdbType.nanotimestamp:
634
+ return [value];
635
+ case DdbType.string:
636
+ case DdbType.symbol:
637
+ case DdbType.code: {
638
+ let bufs = new Array(length * 2);
639
+ for (let i = 0; i < length; i++) {
640
+ bufs[2 * i] = this.enc.encode(value[i]);
641
+ bufs[2 * i + 1] = Uint8Array.of(0);
642
+ }
643
+ return bufs;
644
+ }
645
+ case DdbType.uuid:
646
+ case DdbType.ipaddr:
647
+ case DdbType.int128:
648
+ return [value];
649
+ case DdbType.blob: {
650
+ let bufs = new Array(length * 2);
651
+ for (let i = 0; i < length; i++) {
652
+ const blob_value = value[i];
653
+ bufs[2 * i] = Uint32Array.of(blob_value.length);
654
+ bufs[2 * i + 1] = blob_value;
655
+ }
656
+ return bufs;
657
+ }
658
+ case DdbType.complex:
659
+ case DdbType.point:
660
+ return [value];
661
+ case DdbType.any: {
662
+ // [1, 2, 'a', 'aaa']
663
+ // any[4](<Buffer
664
+ // 04 00 DdbType.int, DdbForm.scalar
665
+ // 01 00 00 00
666
+ // 04 00 DdbType.int, DdbForm.scalar
667
+ // 02 00 00 00
668
+ // 02 00 DdbType.char, DdbForm.scalar
669
+ // 61
670
+ // 12 00 DdbType.string, DdbForm.scalar
671
+ // 61 61 61 00>)
672
+ let bufs = new Array(length);
673
+ for (let i = 0; i < length; i++)
674
+ bufs[i] = value[i].pack();
675
+ return bufs;
676
+ }
677
+ default:
678
+ throw new Error(`vector ${DdbType[type]} 暂不支持序列化`);
679
+ }
680
+ }
681
+ toString() {
682
+ const type = (() => {
683
+ const tname = DdbType[this.type];
684
+ switch (this.form) {
685
+ case DdbForm.scalar:
686
+ if (this.type === DdbType.functiondef)
687
+ return `functiondef<${DdbFunctionType[this.value.type]}>`;
688
+ return tname;
689
+ case DdbForm.vector:
690
+ return `${tname}[${this.rows}]`;
691
+ case DdbForm.pair:
692
+ return `pair<${tname}>`;
693
+ case DdbForm.set:
694
+ return `set<${tname}>`;
695
+ case DdbForm.table:
696
+ return `table[${this.rows} rows][${this.cols} cols]`;
697
+ case DdbForm.dict:
698
+ return `dict<${DdbType[this.value[0].type]}, ${DdbType[this.value[1].type]}>`;
699
+ case DdbForm.matrix:
700
+ return `matrix<${DdbType[this.datatype]}>[${this.rows} rows][${this.cols} cols]`;
701
+ default:
702
+ return `${DdbForm[this.form]} ${tname}`;
703
+ }
704
+ })();
705
+ const data = (() => {
706
+ if (this.form === DdbForm.pair)
707
+ return `${this.value[0]}, ${this.value[1]}`;
708
+ if (this.form === DdbForm.scalar && this.type === DdbType.functiondef)
709
+ return `'${this.value.name}'`;
710
+ return this.value;
711
+ })();
712
+ return `${(0, chalk_browser_1.blue)(type)}(${this.name ? `'${(0, chalk_browser_1.yellow)(this.name)}', ` : ''}${data})\n`;
713
+ }
714
+ to_cols() {
715
+ return this.value.map(col => {
716
+ let col_ = {
717
+ title: col.name,
718
+ dataIndex: col.name,
719
+ };
720
+ switch (col.type) {
721
+ case DdbType.timestamp:
722
+ col_.render = (value) => {
723
+ if (value === exports.nulls.int64)
724
+ return '';
725
+ return (0, dayjs_1.default)(Number(value)).format('YYYY.MM.DD HH:mm:ss.SSS');
726
+ };
727
+ break;
728
+ case DdbType.date:
729
+ col_.render = (value) => {
730
+ if (value === exports.nulls.int32)
731
+ return '';
732
+ return (0, dayjs_1.default)(Number(1000 * 3600 * 24 * value)).format('YYYY.MM.DD');
733
+ };
734
+ break;
735
+ case DdbType.ipaddr:
736
+ col_.render = value => value.slice().reverse().join('.').replace(/^(0\.)+/, '');
737
+ break;
738
+ }
739
+ return col_;
740
+ });
741
+ }
742
+ to_rows() {
743
+ let rows = new Array(this.rows);
744
+ for (let i = 0; i < this.rows; i++) {
745
+ let row = {};
746
+ for (let j = 0; j < this.cols; j++) {
747
+ const c = this.value[j];
748
+ if (c.type === DdbType.ipaddr) {
749
+ row[c.name] = c.value.subarray(16 * i, 16 * (i + 1));
750
+ continue;
751
+ }
752
+ row[c.name] = c.value[i];
753
+ }
754
+ rows[i] = row;
755
+ }
756
+ return rows;
757
+ }
758
+ }
759
+ exports.DdbObj = DdbObj;
760
+ DdbObj.dec = new TextDecoder('utf-8');
761
+ DdbObj.enc = new TextEncoder();
762
+ /** 维护已解析的 symbol base,比如流数据中后续的 symbol 向量可能只发送一个 base.id, base.size == 0, 依赖之前发送的 symbol base */
763
+ DdbObj.symbol_bases = {};
764
+ /** little endian (client) */
765
+ DdbObj.le_client = Boolean(new Uint8Array(Uint32Array.of(1).buffer)[0]);
766
+ class DdbBool extends DdbObj {
767
+ constructor(value) {
768
+ super({
769
+ form: DdbForm.scalar,
770
+ type: DdbType.bool,
771
+ length: 1,
772
+ value,
773
+ });
774
+ }
775
+ }
776
+ exports.DdbBool = DdbBool;
777
+ class DdbInt extends DdbObj {
778
+ constructor(value) {
779
+ super({
780
+ form: DdbForm.scalar,
781
+ type: DdbType.int,
782
+ length: 4,
783
+ value
784
+ });
785
+ }
786
+ }
787
+ exports.DdbInt = DdbInt;
788
+ class DdbString extends DdbObj {
789
+ constructor(value) {
790
+ super({
791
+ form: DdbForm.scalar,
792
+ type: DdbType.string,
793
+ length: 0,
794
+ value
795
+ });
796
+ }
797
+ }
798
+ exports.DdbString = DdbString;
799
+ class DdbLong extends DdbObj {
800
+ constructor(value) {
801
+ super({
802
+ form: DdbForm.scalar,
803
+ type: DdbType.long,
804
+ length: 8,
805
+ value
806
+ });
807
+ }
808
+ }
809
+ exports.DdbLong = DdbLong;
810
+ class DdbDouble extends DdbObj {
811
+ constructor(value) {
812
+ super({
813
+ form: DdbForm.scalar,
814
+ type: DdbType.double,
815
+ length: 8,
816
+ value
817
+ });
818
+ }
819
+ }
820
+ exports.DdbDouble = DdbDouble;
821
+ class DdbVectorInt extends DdbObj {
822
+ constructor(value) {
823
+ super({
824
+ form: DdbForm.vector,
825
+ type: DdbType.int,
826
+ length: 0,
827
+ rows: value.length,
828
+ cols: 1,
829
+ value: Int32Array.from(value),
830
+ });
831
+ }
832
+ }
833
+ exports.DdbVectorInt = DdbVectorInt;
834
+ class DdbVectorString extends DdbObj {
835
+ constructor(value) {
836
+ super({
837
+ form: DdbForm.vector,
838
+ type: DdbType.string,
839
+ length: 0,
840
+ rows: value.length,
841
+ cols: 1,
842
+ value
843
+ });
844
+ }
845
+ }
846
+ exports.DdbVectorString = DdbVectorString;
847
+ class DdbVectorDouble extends DdbObj {
848
+ constructor(value) {
849
+ super({
850
+ form: DdbForm.vector,
851
+ type: DdbType.double,
852
+ length: 0,
853
+ rows: value.length,
854
+ cols: 1,
855
+ value: Float64Array.from(value)
856
+ });
857
+ }
858
+ }
859
+ exports.DdbVectorDouble = DdbVectorDouble;
860
+ class DdbVectorAny extends DdbObj {
861
+ constructor(value) {
862
+ super({
863
+ form: DdbForm.vector,
864
+ type: DdbType.any,
865
+ length: 0,
866
+ rows: value.length,
867
+ cols: 1,
868
+ value
869
+ });
870
+ }
871
+ }
872
+ exports.DdbVectorAny = DdbVectorAny;
873
+ class DdbPair extends DdbObj {
874
+ constructor(l, r = -2147483648) {
875
+ super({
876
+ form: DdbForm.pair,
877
+ type: DdbType.int,
878
+ length: 0,
879
+ rows: 2,
880
+ cols: 1,
881
+ value: Int32Array.of(l, r)
882
+ });
883
+ }
884
+ }
885
+ exports.DdbPair = DdbPair;
886
+ class DdbFunction extends DdbObj {
887
+ constructor(name, type) {
888
+ super({
889
+ form: DdbForm.scalar,
890
+ type: DdbType.functiondef,
891
+ length: 0,
892
+ value: { type, name }
893
+ });
894
+ }
895
+ }
896
+ exports.DdbFunction = DdbFunction;
897
+ class DDB {
898
+ constructor(ws_url) {
899
+ /** 当前的 session id (http 或 tcp) */
900
+ this.sid = '0';
901
+ /** utf-8 text decoder */
902
+ this.dec = new TextDecoder('utf-8');
903
+ this.enc = new TextEncoder();
904
+ this.ws = null;
905
+ /** little endian (server) */
906
+ this.le = true;
907
+ this.presult = Promise.resolve(null);
908
+ if (!ws_url) {
909
+ const url = new URL(location.href);
910
+ const hostname = url.searchParams.get('hostname') || location.hostname;
911
+ const port = url.searchParams.get('port') || location.port;
912
+ ws_url = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${hostname}${port ? `:${port}` : ''}/`;
913
+ }
914
+ this.ws_url = ws_url;
915
+ }
916
+ /** resolver, rejector, promise of last rpc */
917
+ presolver(buf) { }
918
+ prejector(error) { }
919
+ /** 连接到 DolphinDB Server */
920
+ async connect({ ws_url = this.ws_url, login = true, username = 'admin', password = '123456', } = {}) {
921
+ this.ws_url = ws_url;
922
+ if (this.ws?.readyState === WebSocket.OPEN)
923
+ this.disconnect();
924
+ let ws = new WebSocket(ws_url);
925
+ // https://stackoverflow.com/questions/11821096/what-is-the-difference-between-an-arraybuffer-and-a-blob/39951543
926
+ ws.binaryType = 'arraybuffer';
927
+ this.ws = ws;
928
+ ws.addEventListener('open', ev => {
929
+ console.log(`${this.ws_url} opened`);
930
+ ws.send(`API ${this.sid} 8\n` +
931
+ 'connect\n');
932
+ });
933
+ ws.addEventListener('close', ev => {
934
+ console.log(`${this.ws_url} closed with code = ${ev.code}, reason = '${ev.reason}'`);
935
+ });
936
+ ws.addEventListener('error', ev => {
937
+ console.log(`${this.ws_url} errored`, ev);
938
+ });
939
+ // 为首个 connect 响应报文初始化 presult 链表头结点
940
+ this.presult = new Promise((resolve, reject) => {
941
+ this.presolver = resolve;
942
+ this.prejector = reject;
943
+ });
944
+ ws.addEventListener('message', ({ data: buf }) => {
945
+ try {
946
+ this.presolver(this.parse_message(new Uint8Array(buf)));
947
+ }
948
+ catch (error) {
949
+ this.prejector(error);
950
+ }
951
+ });
952
+ await this.presult;
953
+ await this.eval('def pnode_run (nodes, func_name, args, add_node_alias = true) {\n' +
954
+ ' nargs = size(args)\n' +
955
+ ' func = funcByName(func_name)\n' +
956
+ ' \n' +
957
+ ' if (!nargs)\n' +
958
+ ' return pnodeRun(func, nodes, add_node_alias)\n' +
959
+ ' \n' +
960
+ ' args_partial = array(any, 1 + nargs, 1 + nargs)\n' +
961
+ ' args_partial[0] = func\n' +
962
+ ' args_partial[1:] = args\n' +
963
+ ' return pnodeRun(\n' +
964
+ ' unifiedCall(partial, args_partial),\n' +
965
+ ' nodes,\n' +
966
+ ' add_node_alias\n' +
967
+ ' )\n' +
968
+ '}\n', { urgent: true });
969
+ if (login)
970
+ await this.call('login', [username, password], { urgent: true });
971
+ }
972
+ disconnect() {
973
+ this.ws?.close(1000);
974
+ }
975
+ /** rpc through websocket (function command)
976
+ - type: API 类型: 'script' | 'function' | 'variable'
977
+ - options:
978
+ - urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
979
+ - vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
980
+ */
981
+ async rpc(type, { script, func, args = [], vars = [], urgent, }) {
982
+ if (!this.ws)
983
+ await this.connect();
984
+ if (this.ws.readyState !== WebSocket.OPEN)
985
+ throw new Error('ws 连接已断开');
986
+ // 临界区:保证多个 rpc 并发时形成 promise 链
987
+ // ddb 世界观:需要等待上一个 rpc 结果从 server 返回之后才能发起下一个调用
988
+ // 违反世界观可能造成:
989
+ // 1. 并发多个请求只返回第一个结果(阻塞,需后续请求疏通)
990
+ // 2. windows 下 ddb server 返回多个相同的结果
991
+ const ptail = this.presult;
992
+ let presolver;
993
+ let prejector;
994
+ const presult = this.presult = new Promise((resolve, reject) => {
995
+ presolver = resolve;
996
+ prejector = reject;
997
+ });
998
+ try {
999
+ await ptail;
1000
+ }
1001
+ catch { }
1002
+ this.presolver = presolver;
1003
+ this.prejector = prejector;
1004
+ // 临界区结束,只有一个 rpc 请求可以写 WebSocket
1005
+ if (urgent && type !== 'script' && type !== 'function')
1006
+ throw new Error('urgent 只适用于 script 和 funciton');
1007
+ this.to_ddbobjs(args);
1008
+ const command = this.enc.encode((() => {
1009
+ switch (type) {
1010
+ case 'function':
1011
+ return 'function\n' +
1012
+ `${func}\n` +
1013
+ `${args.length}\n` +
1014
+ `${Number(DDB.le_client)}\n`;
1015
+ case 'script':
1016
+ return 'script\n' +
1017
+ script;
1018
+ case 'variable':
1019
+ return 'variable\n' +
1020
+ `${vars.join(',')}\n` +
1021
+ `${vars.length}\n` +
1022
+ `${Number(DDB.le_client)}\n`;
1023
+ }
1024
+ })());
1025
+ const message = (0, utils_browser_1.concat)([
1026
+ this.enc.encode(`API ${this.sid} ${command.length}${urgent ? ` / 1_1_8_8` : ''}\n`),
1027
+ command,
1028
+ ...args.map((arg) => arg.pack())
1029
+ ]);
1030
+ this.ws.send(message);
1031
+ return DdbObj.parse(await presult, // data_buf
1032
+ this.le);
1033
+ }
1034
+ /** eval script through websocket (script command) */
1035
+ async eval(
1036
+ /** 执行的脚本 */
1037
+ script,
1038
+ /** 执行选项 */
1039
+ { urgent } = {}) {
1040
+ return this.rpc('script', { script, urgent });
1041
+ }
1042
+ /** call function through websocket (function command)
1043
+ - func: 函数名
1044
+ - args?: `[ ]` 调用参数 (传入的原生 string 和 boolean 会被自动转换为 DdbObj<string> 和 DdbObj<boolean>)
1045
+ - options?: 调用选项
1046
+ - urgent?: 紧急 flag,使用 urgent worker 处理,防止被其它作业阻塞
1047
+ - node?: 设置结点 alias 时发送到集群中对应的结点执行 (使用 DolphinDB 中的 rpc 方法)
1048
+ - nodes?: 设置多个结点 alias 时发送到集群中对应的多个结点执行 (使用 DolphinDB 中的 pnodeRun 方法)
1049
+ - func_type?: 设置 node 参数时必传,需指定函数类型,其它情况下不传
1050
+ - add_node_alias?: 设置 nodes 参数时选传,其它情况不传
1051
+ */
1052
+ async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias } = {}) {
1053
+ if (node) {
1054
+ if (typeof func_type === 'undefined')
1055
+ throw new Error('指定 node 时必须设置 func_type');
1056
+ args = [
1057
+ node,
1058
+ new DdbFunction(func, func_type),
1059
+ ...args
1060
+ ];
1061
+ func = 'rpc';
1062
+ }
1063
+ if (nodes) {
1064
+ args = [
1065
+ new DdbVectorString(nodes),
1066
+ func,
1067
+ new DdbVectorAny(this.to_ddbobjs(args)),
1068
+ ...typeof add_node_alias === 'undefined' ? [] : [add_node_alias]
1069
+ ];
1070
+ func = 'pnode_run';
1071
+ }
1072
+ return this.rpc('function', {
1073
+ func,
1074
+ args,
1075
+ urgent,
1076
+ });
1077
+ }
1078
+ /** upload variable through websocket (variable command) */
1079
+ async upload(
1080
+ /** 上传的变量名 */
1081
+ vars,
1082
+ /** 上传的变量值 */
1083
+ args) {
1084
+ if (!args.length || args.length !== vars.length)
1085
+ throw new Error('variable 指令参数为空或参数名为空,或数量不匹配');
1086
+ return this.rpc('variable', { vars, args });
1087
+ }
1088
+ /** 解析服务端响应报文,返回去掉 header 的 data buf */
1089
+ parse_message(buf) {
1090
+ // '1166953221 1 1\n'
1091
+ // 'OK\n'
1092
+ // '\x04\x00\x02\x00\x00\x00'
1093
+ /** index of line feed 0 */
1094
+ const i_lf_0 = buf.indexOf(0x0a); // '\n'
1095
+ const parts = this.dec.decode(buf.subarray(0, i_lf_0)).split(' ');
1096
+ /** session id */
1097
+ const sid = parts[0];
1098
+ if (sid !== this.sid) {
1099
+ console.log(`sid 从 ${this.sid} 变为 ${sid}`);
1100
+ this.sid = sid;
1101
+ }
1102
+ /** 返回对象的数量 */
1103
+ const n_obj = Number(parts[1]);
1104
+ /** 大小端: 协议中大端为 0, 小端为 1 */
1105
+ this.le = Number(parts[2]) !== 0;
1106
+ const i_ls_1 = i_lf_0 + 1;
1107
+ const i_lf_1 = buf.indexOf(0x0a, i_ls_1); // '\n'
1108
+ /** 'OK' 表示成功,其它文本表示失败 */
1109
+ const message = this.dec.decode(buf.subarray(i_ls_1, i_lf_1));
1110
+ if (message !== 'OK')
1111
+ throw new Error(message);
1112
+ return buf.subarray(i_lf_1 + 1);
1113
+ }
1114
+ /** 自动转换 js string, boolean 为 DdbObj */
1115
+ to_ddbobj(value) {
1116
+ if (value instanceof DdbObj)
1117
+ return value;
1118
+ const type = typeof value;
1119
+ switch (type) {
1120
+ case 'string':
1121
+ return new DdbString(value);
1122
+ case 'boolean':
1123
+ return new DdbBool(value);
1124
+ default:
1125
+ throw new Error(`不能自动转换 ${type} 至 DdbObj`);
1126
+ }
1127
+ }
1128
+ /** 转换 js 数组为 DdbObj[] (in place, 会修改原数组) */
1129
+ to_ddbobjs(values) {
1130
+ for (let i = 0; i < values.length; i++)
1131
+ values[i] = this.to_ddbobj(values[i]);
1132
+ return values;
1133
+ }
1134
+ }
1135
+ exports.DDB = DDB;
1136
+ /** little endian (client) */
1137
+ DDB.le_client = Boolean(new Uint8Array(Uint32Array.of(1).buffer)[0]);
1138
+ exports.ddb = window.ddb = new DDB();
1139
+ exports.default = exports.ddb;
1140
+ //# sourceMappingURL=browser.js.map