dolphindb 2.0.504 → 2.0.505

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/index.d.ts CHANGED
@@ -78,11 +78,10 @@ export interface DdbArrayVectorBlock {
78
78
  lengths: Uint8Array | Uint16Array | Uint32Array;
79
79
  data: DdbVectorValue;
80
80
  }
81
- export declare type DdbValue = null | boolean | number | [number, number] | bigint | string | string[] | Uint8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array | Uint8Array[] | DdbObj[] | DdbFunctionDefValue | DdbSymbolExtendedValue | DdbArrayVectorBlock[];
82
- export declare type DdbVectorValue = string | string[] | Uint8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array | Uint8Array[] | DdbObj[] | DdbSymbolExtendedValue | DdbArrayVectorBlock[];
81
+ export declare type DdbValue = null | boolean | number | [number, number] | bigint | string | string[] | Uint8Array | Int8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array | Uint8Array[] | DdbObj[] | DdbFunctionDefValue | DdbSymbolExtendedValue | DdbArrayVectorBlock[];
82
+ export declare type DdbVectorValue = string | string[] | Uint8Array | Int8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array | Uint8Array[] | DdbObj[] | DdbSymbolExtendedValue | DdbArrayVectorBlock[];
83
83
  export declare const nulls: {
84
- readonly bool: 128;
85
- readonly char: "€";
84
+ readonly int8: -128;
86
85
  readonly int16: -32768;
87
86
  readonly int32: -2147483648;
88
87
  readonly int64: -9223372036854775808n;
@@ -128,6 +127,8 @@ export declare class DdbObj<T extends DdbValue = DdbValue> {
128
127
  datatype?: DdbType;
129
128
  /** 实际数据。不同的 DdbForm, DdbType 使用 DdbValue 中不同的类型来表示实际数据 */
130
129
  value: T;
130
+ /** 原始二进制数据 */
131
+ buffer?: Uint8Array;
131
132
  constructor(data: Partial<DdbObj> & {
132
133
  form: DdbForm;
133
134
  type: DdbType;
@@ -157,7 +158,7 @@ export declare class DdbBool extends DdbObj<boolean> {
157
158
  constructor(value: boolean | null);
158
159
  }
159
160
  export declare class DdbChar extends DdbObj<string> {
160
- constructor(value: string | null);
161
+ constructor(value: string | number | null);
161
162
  }
162
163
  export declare class DdbInt extends DdbObj<number> {
163
164
  constructor(value: number | null);
@@ -269,13 +270,13 @@ export declare class DDB {
269
270
  password: string;
270
271
  /** python session flag (2048) */
271
272
  python: boolean;
272
- message_hook: (message: Uint8Array) => any;
273
- /** print message handler */
274
- printer(message: string): void;
273
+ parse_object: boolean;
274
+ /** message handler */
275
+ on_message({ type, data }: DdbMessage, _this: DDB): void;
275
276
  /** resolver, rejector, promise of last rpc */
276
- presolver(buf: Uint8Array): void;
277
+ presolver(message: DdbMessage): void;
277
278
  prejector(error: Error): void;
278
- presult: Promise<Uint8Array>;
279
+ presult: Promise<DdbMessage>;
279
280
  get connected(): boolean;
280
281
  /**
281
282
  Initialize an instance of DolphinDB Client using the WebSocket URL
@@ -348,22 +349,31 @@ export declare class DDB {
348
349
  - options:
349
350
  - urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
350
351
  - vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
352
+ - on_message?: 在该次 rpc 期间设置 message handler, 结束后恢复原有
353
+ - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
354
+ 不做解析,以便后续转发、序列化
351
355
  */
352
- rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent, }: {
356
+ rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent, on_message, parse_object, }: {
353
357
  script?: string;
354
358
  func?: string;
355
359
  args?: (DdbObj | string | boolean)[];
356
360
  vars?: string[];
357
361
  urgent?: boolean;
362
+ on_message?: DDB['on_message'];
363
+ parse_object?: boolean;
358
364
  }): Promise<T>;
359
- /** eval script through websocket (script command) */
360
- eval<T extends DdbObj>(
361
- /** 执行的脚本 */
362
- script: string,
363
- /** 执行选项 */
364
- { urgent }?: {
365
- /** 紧急 flag,确保提交的脚本使用 urgent worker 处理,防止被其它作业阻塞 */
365
+ /** eval script through websocket (script command)
366
+ - script?: 执行的脚本
367
+ - options?: 执行选项
368
+ - urgent?: 紧急 flag,确保提交的脚本使用 urgent worker 处理,防止被其它作业阻塞
369
+ - on_message?: 在该次 rpc 期间设置 message handler, 结束后恢复原有
370
+ - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
371
+ 不做解析,以便后续转发、序列化
372
+ */
373
+ eval<T extends DdbObj>(script: string, { urgent, on_message, parse_object, }?: {
366
374
  urgent?: boolean;
375
+ on_message?: DDB['on_message'];
376
+ parse_object?: boolean;
367
377
  }): Promise<T>;
368
378
  /** call function through websocket (function command)
369
379
  - func: 函数名
@@ -374,31 +384,42 @@ export declare class DDB {
374
384
  - nodes?: 设置多个结点 alias 时发送到集群中对应的多个结点执行 (使用 DolphinDB 中的 pnodeRun 方法)
375
385
  - func_type?: 设置 node 参数时必传,需指定函数类型,其它情况下不传
376
386
  - add_node_alias?: 设置 nodes 参数时选传,其它情况不传
387
+ - on_message?: 在该次 rpc 期间设置 message handler, 结束后恢复原有
388
+ - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
389
+ 不做解析,以便后续转发、序列化
377
390
  */
378
- call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias }?: {
391
+ call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias, on_message, parse_object, }?: {
379
392
  urgent?: boolean;
380
393
  node?: string;
381
394
  nodes?: string[];
382
395
  func_type?: DdbFunctionType;
383
396
  add_node_alias?: boolean;
397
+ on_message?: DDB['on_message'];
398
+ parse_object?: boolean;
384
399
  }): Promise<T>;
385
400
  /** upload variable through websocket (variable command) */
386
401
  upload(
387
402
  /** Uploaded variables' name */
388
403
  vars: string[],
389
404
  /** Uploaded variables' value */
390
- args: (DdbObj | string | boolean)[]): Promise<DdbObj<DdbValue>>;
405
+ args: (DdbObj | string | boolean)[], { on_message, parse_object, }?: {
406
+ on_message?: DDB['on_message'];
407
+ parse_object?: boolean;
408
+ }): Promise<DdbObj<DdbValue>>;
391
409
  /** 解析服务端响应报文,返回去掉 header 的 data buf */
392
- parse_message(buf: Uint8Array): {
393
- type: "message";
394
- data: string;
395
- } | {
396
- type: "object";
397
- data: Uint8Array;
398
- };
410
+ parse_message(buf: Uint8Array, parse_object?: boolean): DdbMessage;
399
411
  /** 自动转换 js string, boolean 为 DdbObj */
400
412
  to_ddbobj(value: DdbObj | string | boolean): DdbObj;
401
413
  /** 转换 js 数组为 DdbObj[] */
402
414
  to_ddbobjs(values: any[]): DdbObj<DdbValue>[];
403
415
  }
416
+ export interface DdbPrintMessage {
417
+ type: 'print';
418
+ data: string;
419
+ }
420
+ export interface DdbObjectMessage {
421
+ type: 'object';
422
+ data: DdbObj;
423
+ }
424
+ export declare type DdbMessage = DdbPrintMessage | DdbObjectMessage;
404
425
  export default DDB;
package/index.js CHANGED
@@ -6,6 +6,7 @@ const ws_1 = require("ws");
6
6
  const dayjs_1 = tslib_1.__importDefault(require("dayjs"));
7
7
  const customParseFormat_js_1 = tslib_1.__importDefault(require("dayjs/plugin/customParseFormat.js"));
8
8
  dayjs_1.default.extend(customParseFormat_js_1.default);
9
+ const net_js_1 = require("xshell/net.js");
9
10
  const utils_js_1 = require("xshell/utils.js");
10
11
  var DdbForm;
11
12
  (function (DdbForm) {
@@ -109,8 +110,7 @@ var DdbFunctionType;
109
110
  DdbFunctionType[DdbFunctionType["JitPartialFunc"] = 8] = "JitPartialFunc";
110
111
  })(DdbFunctionType = exports.DdbFunctionType || (exports.DdbFunctionType = {}));
111
112
  exports.nulls = {
112
- bool: 0x80,
113
- char: '\x80',
113
+ int8: -0x80,
114
114
  int16: -32768,
115
115
  int32: -2147483648,
116
116
  int64: -0x8000000000000000n,
@@ -284,12 +284,14 @@ class DdbObj {
284
284
  case DdbType.void:
285
285
  return [1, null];
286
286
  case DdbType.bool: {
287
- const value = buf[0];
288
- return [1, value === exports.nulls.bool ? null : Boolean(value)];
287
+ const dv = new DataView(buf.buffer, buf.byteOffset);
288
+ const value = dv.getInt8(0);
289
+ return [1, value === exports.nulls.int8 ? null : Boolean(value)];
289
290
  }
290
291
  case DdbType.char: {
291
- const value = String.fromCharCode(buf[0]);
292
- return [1, value === exports.nulls.char ? null : value];
292
+ const dv = new DataView(buf.buffer, buf.byteOffset);
293
+ const value = dv.getInt8(0);
294
+ return [1, value === exports.nulls.int8 ? null : value];
293
295
  }
294
296
  case DdbType.short: {
295
297
  const dv = new DataView(buf.buffer, buf.byteOffset);
@@ -474,11 +476,10 @@ class DdbObj {
474
476
  static parse_vector_items(buf, le, type, length) {
475
477
  switch (type) {
476
478
  case DdbType.bool:
477
- return [length, buf.slice(0, length)];
478
479
  case DdbType.char:
479
480
  return [
480
481
  length,
481
- this.dec.decode(buf.subarray(0, length))
482
+ new Int8Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + length))
482
483
  ];
483
484
  case DdbType.short:
484
485
  return [
@@ -628,17 +629,17 @@ class DdbObj {
628
629
  return [Uint8Array.of(1)];
629
630
  case DdbType.bool:
630
631
  return [
631
- Uint8Array.of(value === null ?
632
- exports.nulls.bool
632
+ Int8Array.of(value === null ?
633
+ exports.nulls.int8
633
634
  :
634
635
  Number(value))
635
636
  ];
636
637
  case DdbType.char:
637
638
  return [
638
- Uint8Array.of((value === null ?
639
- exports.nulls.char
639
+ Int8Array.of((value === null ?
640
+ exports.nulls.int8
640
641
  :
641
- value).charCodeAt(0))
642
+ value))
642
643
  ];
643
644
  case DdbType.short:
644
645
  return [
@@ -780,7 +781,7 @@ class DdbObj {
780
781
  case DdbType.bool:
781
782
  return [value];
782
783
  case DdbType.char:
783
- return [this.enc.encode(value)];
784
+ return [value];
784
785
  case DdbType.short:
785
786
  return [value];
786
787
  case DdbType.int:
@@ -968,7 +969,10 @@ class DdbChar extends DdbObj {
968
969
  form: DdbForm.scalar,
969
970
  type: DdbType.char,
970
971
  length: 1,
971
- value,
972
+ value: typeof value === 'string' ?
973
+ value.charCodeAt(0)
974
+ :
975
+ value
972
976
  });
973
977
  }
974
978
  }
@@ -1375,7 +1379,7 @@ class DDB {
1375
1379
  this.password = '123456';
1376
1380
  /** python session flag (2048) */
1377
1381
  this.python = false;
1378
- this.message_hook = null;
1382
+ this.parse_object = true;
1379
1383
  this.presult = Promise.resolve(null);
1380
1384
  this.url = url;
1381
1385
  if (options.autologin !== undefined)
@@ -1387,12 +1391,20 @@ class DDB {
1387
1391
  if (options.python !== undefined)
1388
1392
  this.python = options.python;
1389
1393
  }
1390
- /** print message handler */
1391
- printer(message) {
1392
- console.log(message);
1394
+ /** message handler */
1395
+ on_message({ type, data }, _this) {
1396
+ switch (type) {
1397
+ case 'print':
1398
+ console.log(data);
1399
+ return;
1400
+ case 'object':
1401
+ if (this.print_buffer)
1402
+ console.log((0, utils_js_1.typed_array_to_buffer)(data.buffer));
1403
+ return;
1404
+ }
1393
1405
  }
1394
1406
  /** resolver, rejector, promise of last rpc */
1395
- presolver(buf) { }
1407
+ presolver(message) { }
1396
1408
  prejector(error) { }
1397
1409
  get connected() {
1398
1410
  return this.websocket?.readyState === ws_1.WebSocket.OPEN;
@@ -1417,42 +1429,25 @@ class DDB {
1417
1429
  if (options.python !== undefined)
1418
1430
  this.python = options.python;
1419
1431
  this.disconnect();
1420
- let websocket = new ws_1.WebSocket(this.url, this.python ? ['python'] : [], {
1421
- maxPayload: 2 ** 33 // 8 GB
1422
- });
1423
- // https://stackoverflow.com/questions/11821096/what-is-the-difference-between-an-arraybuffer-and-a-blob/39951543
1424
- websocket.binaryType = 'arraybuffer';
1425
- this.websocket = websocket;
1426
- await new Promise((resolve, reject) => {
1427
- websocket.addEventListener('open', async (event) => {
1428
- console.log(`${websocket.url} opened`);
1432
+ await (0, net_js_1.connect_websocket)(this.url, {
1433
+ protocols: this.python ? ['python'] : [],
1434
+ on_open: async (event, websocket) => {
1435
+ this.websocket = websocket;
1429
1436
  await this.rpc('connect', {});
1430
- resolve();
1431
- });
1432
- websocket.addEventListener('close', event => {
1433
- console.log(`${websocket.url} closed with code = ${event.code}, reason = '${event.reason}'`);
1434
- });
1435
- websocket.addEventListener('error', event => {
1436
- const message = `${websocket.url} errored`;
1437
- console.error(message, event);
1438
- reject(Object.assign(new Error(message), { event }));
1439
- });
1440
- websocket.addEventListener('message', event => {
1437
+ },
1438
+ on_message: event => {
1441
1439
  const buf = new Uint8Array(event.data);
1442
- if (this.message_hook)
1443
- this.message_hook(buf);
1444
1440
  try {
1445
- const { type, data } = this.parse_message(buf);
1446
- if (type === 'message') {
1447
- this.printer(data);
1441
+ const message = this.parse_message(buf);
1442
+ this.on_message(message, this);
1443
+ if (message.type === 'print')
1448
1444
  return;
1449
- }
1450
- this.presolver(data);
1445
+ this.presolver(message);
1451
1446
  }
1452
1447
  catch (error) {
1453
1448
  this.prejector(error);
1454
1449
  }
1455
- });
1450
+ }
1456
1451
  });
1457
1452
  if (!this.python)
1458
1453
  await this.eval('def pnode_run (nodes, func_name, args, add_node_alias = true) {\n' +
@@ -1506,7 +1501,7 @@ class DDB {
1506
1501
  limit,
1507
1502
  ] : [],
1508
1503
  ];
1509
- return `/ ${options.join('_')}`;
1504
+ return options.join('_');
1510
1505
  }
1511
1506
  disconnect() {
1512
1507
  if (this.connected)
@@ -1520,8 +1515,11 @@ class DDB {
1520
1515
  - options:
1521
1516
  - urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
1522
1517
  - vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
1518
+ - on_message?: 在该次 rpc 期间设置 message handler, 结束后恢复原有
1519
+ - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
1520
+ 不做解析,以便后续转发、序列化
1523
1521
  */
1524
- async rpc(type, { script, func, args = [], vars = [], urgent, }) {
1522
+ async rpc(type, { script, func, args = [], vars = [], urgent, on_message, parse_object, }) {
1525
1523
  if (!this.websocket)
1526
1524
  await this.connect();
1527
1525
  if (!this.connected)
@@ -1568,25 +1566,36 @@ class DDB {
1568
1566
  }
1569
1567
  })());
1570
1568
  const message = (0, utils_js_1.concat)([
1571
- this.enc.encode(`API2 ${this.sid} ${command.length}${this.get_rpc_options({ urgent })}\n`),
1569
+ this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
1572
1570
  command,
1573
1571
  ...args.map((arg) => arg.pack())
1574
1572
  ]);
1575
- this.websocket.send(message);
1576
- const buf_data = await presult;
1577
- if (this.print_buffer)
1578
- console.log((0, utils_js_1.typed_array_to_buffer)(buf_data));
1579
- // LOCAL: 便于 repl
1580
- // return global.DdbObj.parse(data_buf) as DdbObj
1581
- return DdbObj.parse(buf_data, this.le);
1573
+ const _on_message = this.on_message;
1574
+ const _parse_object = this.parse_object;
1575
+ if (on_message)
1576
+ this.on_message = on_message;
1577
+ if (parse_object !== undefined)
1578
+ this.parse_object = parse_object;
1579
+ try {
1580
+ this.websocket.send(message);
1581
+ const { data } = (await presult);
1582
+ return data;
1583
+ }
1584
+ finally {
1585
+ this.on_message = _on_message;
1586
+ this.parse_object = _parse_object;
1587
+ }
1582
1588
  }
1583
- /** eval script through websocket (script command) */
1584
- async eval(
1585
- /** 执行的脚本 */
1586
- script,
1587
- /** 执行选项 */
1588
- { urgent } = {}) {
1589
- return this.rpc('script', { script, urgent });
1589
+ /** eval script through websocket (script command)
1590
+ - script?: 执行的脚本
1591
+ - options?: 执行选项
1592
+ - urgent?: 紧急 flag,确保提交的脚本使用 urgent worker 处理,防止被其它作业阻塞
1593
+ - on_message?: 在该次 rpc 期间设置 message handler, 结束后恢复原有
1594
+ - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
1595
+ 不做解析,以便后续转发、序列化
1596
+ */
1597
+ async eval(script, { urgent, on_message, parse_object, } = {}) {
1598
+ return this.rpc('script', { script, urgent, on_message, parse_object });
1590
1599
  }
1591
1600
  /** call function through websocket (function command)
1592
1601
  - func: 函数名
@@ -1597,8 +1606,11 @@ class DDB {
1597
1606
  - nodes?: 设置多个结点 alias 时发送到集群中对应的多个结点执行 (使用 DolphinDB 中的 pnodeRun 方法)
1598
1607
  - func_type?: 设置 node 参数时必传,需指定函数类型,其它情况下不传
1599
1608
  - add_node_alias?: 设置 nodes 参数时选传,其它情况不传
1609
+ - on_message?: 在该次 rpc 期间设置 message handler, 结束后恢复原有
1610
+ - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
1611
+ 不做解析,以便后续转发、序列化
1600
1612
  */
1601
- async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias } = {}) {
1613
+ async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, on_message, parse_object, } = {}) {
1602
1614
  if (this.python)
1603
1615
  throw new Error('call doesn\'t support python session yet');
1604
1616
  if (node) {
@@ -1630,6 +1642,8 @@ class DDB {
1630
1642
  func,
1631
1643
  args,
1632
1644
  urgent,
1645
+ on_message,
1646
+ parse_object
1633
1647
  });
1634
1648
  }
1635
1649
  /** upload variable through websocket (variable command) */
@@ -1637,19 +1651,19 @@ class DDB {
1637
1651
  /** Uploaded variables' name */
1638
1652
  vars,
1639
1653
  /** Uploaded variables' value */
1640
- args) {
1654
+ args, { on_message, parse_object, } = {}) {
1641
1655
  if (!args.length || args.length !== vars.length)
1642
1656
  throw new Error('variable 指令参数为空或参数名为空,或数量不匹配');
1643
- return this.rpc('variable', { vars, args });
1657
+ return this.rpc('variable', { vars, args, on_message, parse_object });
1644
1658
  }
1645
1659
  /** 解析服务端响应报文,返回去掉 header 的 data buf */
1646
- parse_message(buf) {
1660
+ parse_message(buf, parse_object = this.parse_object) {
1647
1661
  // MSG\n
1648
1662
  // <message>\0
1649
1663
  // 'M'.codePointAt(0).to_hex_str()
1650
1664
  if (buf[0] === 0x4d && buf[1] === 0x53 && buf[2] === 0x47 && buf[3] === 0x0a)
1651
1665
  return {
1652
- type: 'message',
1666
+ type: 'print',
1653
1667
  data: this.dec.decode(buf.subarray(4))
1654
1668
  };
1655
1669
  // '1166953221 1 1\n'
@@ -1674,9 +1688,19 @@ class DDB {
1674
1688
  const message = this.dec.decode(buf.subarray(i_ls_1, i_lf_1));
1675
1689
  if (message !== 'OK')
1676
1690
  throw new Error(message);
1691
+ const buf_obj = buf.subarray(i_lf_1 + 1);
1677
1692
  return {
1678
1693
  type: 'object',
1679
- data: buf.subarray(i_lf_1 + 1)
1694
+ data: parse_object ?
1695
+ Object.assign(DdbObj.parse(buf_obj, this.le), { buffer: buf_obj })
1696
+ :
1697
+ new DdbObj({
1698
+ form: DdbForm.scalar,
1699
+ type: DdbType.void,
1700
+ length: 0,
1701
+ le: this.le,
1702
+ buffer: buf_obj,
1703
+ })
1680
1704
  };
1681
1705
  }
1682
1706
  /** 自动转换 js string, boolean 为 DdbObj */