@byted-apaas/server-sdk-node 1.0.12 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1 +1,11 @@
1
- ## aPaaS Server SDK 版本说明:
1
+ ## aPaaS @byted-apaas/server-sdk-node 版本说明:
2
+
3
+ -------
4
+ ### 版本:1.0.13|兼容升级
5
+ 新功能:支持流式查询 findStream
6
+ ```js
7
+ await context.db.object("_user").findStream(async (records) => {
8
+ // doSomething ...
9
+ });
10
+ ```
11
+ 优化:findAll 标记为过时方法,用 findStream 替代
@@ -121,6 +121,8 @@ export interface _IKAsyncEndpoint<T> {
121
121
  }
122
122
  export interface _IKQuery<T> {
123
123
  /**
124
+ * @Deprecated Use FindStream instead.
125
+ *
124
126
  * 无需入参,返回全部符合条件的记录
125
127
  * @example
126
128
  * ```
@@ -130,6 +132,17 @@ export interface _IKQuery<T> {
130
132
  * ```
131
133
  */
132
134
  findAll(): Promise<_Record<T>[]>;
135
+ /**
136
+ * 遍历全部符合条件的记录
137
+ * @param handler 业务处理函数
138
+ * @example
139
+ * ```
140
+ * await context.db.object("_user").findStream(async (records) => {
141
+ * // doSomething ...
142
+ * });
143
+ * ```
144
+ */
145
+ findStream(handler: (records: object[]) => Promise<void>): Promise<void>;
133
146
  /**
134
147
  * 无需入参,返回符合条件的记录,单次返回 200 条
135
148
  * @example
@@ -56,6 +56,7 @@ declare class _KObjectQuery<T> implements _IKQuery<T> {
56
56
  find(): Promise<_Record<T>[]>;
57
57
  findOne(): Promise<_Record<T>>;
58
58
  findAll(): Promise<_Record<T>[]>;
59
+ findStream(handler: (records: object[]) => Promise<void>): Promise<void>;
59
60
  orderBy<K extends keyof T>(fieldApiNames: K[]): _KQuery<T>;
60
61
  orderBy<K extends keyof T>(...fieldApiNames: K[]): _KQuery<T>;
61
62
  orderByDesc<K extends keyof T>(fieldApiNames: K[]): _KQuery<T>;
@@ -75,7 +76,13 @@ declare class _KQuery<T> implements _IKQuery<T> {
75
76
  constructor(objectApiName: string, appCtx?: AppCtx);
76
77
  find(): Promise<_Record<T>[]>;
77
78
  findOne(): Promise<_Record<T>>;
79
+ /**
80
+ * @Deprecated Use FindStream instead.
81
+ */
78
82
  findAll(): Promise<_Record<T>[]>;
83
+ findStream(handler: (records: object[]) => Promise<void>): Promise<void>;
84
+ private walkRecordsByID;
85
+ private walkRecordsByLimitOffset;
79
86
  private getRecordsByPage;
80
87
  orderBy<K extends keyof T>(fieldApiNames: K[]): this;
81
88
  orderBy<K extends keyof T>(...fieldApiNames: K[]): this;
@@ -88,5 +95,6 @@ declare class _KQuery<T> implements _IKQuery<T> {
88
95
  limit(limit: number): this;
89
96
  offset(offset: number): this;
90
97
  count(): Promise<number>;
98
+ private findPreCheck;
91
99
  }
92
100
  export {};
@@ -301,6 +301,9 @@ class _KObjectQuery {
301
301
  return new _KQuery(this.apiName, this.appCtx).findAll();
302
302
  }
303
303
  ;
304
+ async findStream(handler) {
305
+ return new _KQuery(this.apiName, this.appCtx).findStream(handler);
306
+ }
304
307
  orderBy(fieldApiNames, ...restFieldApiNames) {
305
308
  fieldApiNames = !fieldApiNames ? [] : fieldApiNames;
306
309
  return new _KQuery(this.apiName, this.appCtx).orderBy(server_common_node_1.utils.argsToList(fieldApiNames, restFieldApiNames));
@@ -350,23 +353,8 @@ class _KQuery {
350
353
  });
351
354
  }
352
355
  async find() {
356
+ this.findPreCheck();
353
357
  const { apiName, appCtx, queryBuilder, queryV2 } = queryPropertiesStore.get(this);
354
- // 查询非 _id 字段或者关联对象下钻._id, limit 不允许超过 200
355
- let checkLimit;
356
- let checkFields;
357
- if (queryV2) {
358
- checkLimit = queryV2._limit;
359
- checkFields = queryV2.fields;
360
- }
361
- else {
362
- checkLimit = queryBuilder.getLimit();
363
- checkFields = queryBuilder.getSelect();
364
- }
365
- if (checkFields.length != 1 || !(checkFields[0] == "_id" || checkFields[0].endsWith("._id"))) {
366
- if (checkLimit > 200) {
367
- throw new Error(`limit(${checkLimit}) > ${queryBuilder_1.maxLimit}. Limit should be 1~${queryBuilder_1.maxLimitV2} when querying the id field, otherwise it should be 1~${queryBuilder_1.maxLimit}`);
368
- }
369
- }
370
358
  if (appCtx) {
371
359
  const param = {
372
360
  limit: queryV2._limit,
@@ -393,6 +381,9 @@ class _KQuery {
393
381
  return records instanceof Array ? (records.length > 0 ? records[0] : null) : null;
394
382
  }
395
383
  ;
384
+ /**
385
+ * @Deprecated Use FindStream instead.
386
+ */
396
387
  async findAll() {
397
388
  const { queryBuilder, queryV2 } = queryPropertiesStore.get(this);
398
389
  if (queryBuilder.getOrder().length > 0) {
@@ -404,6 +395,152 @@ class _KQuery {
404
395
  return await this.getRecordsByPage();
405
396
  }
406
397
  ;
398
+ async findStream(handler) {
399
+ const { queryBuilder, queryV2 } = queryPropertiesStore.get(this);
400
+ let offset = 0, orders = [];
401
+ if (queryV2) {
402
+ offset = queryV2._offset;
403
+ orders = queryV2._order;
404
+ }
405
+ else {
406
+ offset = queryBuilder.getOffset();
407
+ orders = queryBuilder.getOrder();
408
+ }
409
+ if (orders.length === 0 && offset === 0) {
410
+ // 走主键翻页
411
+ return await this.walkRecordsByID(handler);
412
+ }
413
+ // 走 limit offset 翻页
414
+ return await this.walkRecordsByLimitOffset(handler);
415
+ }
416
+ async walkRecordsByID(handler) {
417
+ const { apiName, appCtx, queryBuilder, queryV2 } = queryPropertiesStore.get(this);
418
+ let limit = 0, selectFields = [];
419
+ if (queryV2) {
420
+ if (queryV2.isSetLimit) {
421
+ limit = queryV2._limit;
422
+ }
423
+ selectFields = queryV2.fields;
424
+ }
425
+ else {
426
+ if (queryBuilder.isSetLimit) {
427
+ limit = queryBuilder.getLimit();
428
+ }
429
+ selectFields = queryBuilder.getSelect();
430
+ }
431
+ let maxId = 0, queryCount = 0;
432
+ while (true) {
433
+ let newLimit = queryBuilder_1.defaultLimit;
434
+ if (limit > 0 && limit - queryCount < queryBuilder_1.defaultLimit) {
435
+ newLimit = limit - queryCount;
436
+ }
437
+ if (newLimit <= 0) {
438
+ break;
439
+ }
440
+ let rs;
441
+ if (appCtx) {
442
+ let criterion = (0, logicV2_1.buildCriterionV2)(queryV2.filter);
443
+ criterion.push({ leftValue: '_id', operator: operator_1.operates.GT, rightValue: maxId });
444
+ const param = {
445
+ limit: newLimit,
446
+ offset: 0,
447
+ sort: [{ field: '_id', direction: 'asc', type: '' }],
448
+ fields: selectFields,
449
+ count: false,
450
+ filter: criterion,
451
+ };
452
+ rs = await (0, common_1.runCtxForOpenSDK)(appCtx, async () => {
453
+ return await Request.GetInstance().openSDKGetRecords(apiName, param);
454
+ });
455
+ }
456
+ else {
457
+ let criterion = (0, logic_1.buildCriterion)(queryBuilder.getLogic(), apiName, maxId);
458
+ rs = await Request.GetInstance().getRecordsOrCountByCriterion(apiName, await (0, logic_1.handleCriterion)(criterion), [new order_1.Order("_id", "asc")], false, queryBuilder.getSelect(), 0, newLimit, false);
459
+ }
460
+ queryCount += rs.length;
461
+ rs.forEach((r) => {
462
+ maxId = r._id > maxId ? r._id : maxId;
463
+ });
464
+ try {
465
+ if (rs.length > 0) {
466
+ await handler(rs);
467
+ }
468
+ }
469
+ catch (err) {
470
+ throw err;
471
+ }
472
+ if (rs.length < queryBuilder_1.defaultLimit) {
473
+ break;
474
+ }
475
+ }
476
+ }
477
+ async walkRecordsByLimitOffset(handler) {
478
+ const { apiName, appCtx, queryBuilder, queryV2 } = queryPropertiesStore.get(this);
479
+ let limit = 0, offset = 0, selectFields = [], orders = [];
480
+ if (queryV2) {
481
+ if (queryV2.isSetLimit) {
482
+ limit = queryV2._limit;
483
+ }
484
+ offset = queryV2._offset;
485
+ selectFields = queryV2.fields;
486
+ orders = queryV2._order;
487
+ }
488
+ else {
489
+ if (queryBuilder.isSetLimit) {
490
+ limit = queryBuilder.getLimit();
491
+ }
492
+ offset = queryBuilder.getOffset();
493
+ selectFields = queryBuilder.getSelect();
494
+ orders = queryBuilder.getOrder();
495
+ }
496
+ let maxId = 0, queryCount = 0;
497
+ for (let i = offset; !limit || i < offset + limit; i += queryBuilder_1.defaultLimit) {
498
+ let newLimit = function () {
499
+ if (limit == 0) {
500
+ return queryBuilder_1.defaultLimit;
501
+ }
502
+ if (offset + limit - i < queryBuilder_1.defaultLimit) {
503
+ return offset + limit - i;
504
+ }
505
+ return queryBuilder_1.defaultLimit;
506
+ }();
507
+ if (newLimit <= 0) {
508
+ break;
509
+ }
510
+ let rs;
511
+ if (appCtx) {
512
+ let criterion = (0, logicV2_1.buildCriterionV2)(queryV2.filter);
513
+ criterion.push({ leftValue: '_id', operator: operator_1.operates.GT, rightValue: maxId });
514
+ const param = {
515
+ limit: newLimit,
516
+ offset: i,
517
+ sort: orders,
518
+ fields: selectFields,
519
+ count: false,
520
+ filter: criterion,
521
+ };
522
+ rs = await (0, common_1.runCtxForOpenSDK)(appCtx, async () => {
523
+ return await Request.GetInstance().openSDKGetRecords(apiName, param);
524
+ });
525
+ }
526
+ else {
527
+ let criterion = (0, logic_1.buildCriterion)(queryBuilder.getLogic(), apiName, maxId);
528
+ rs = await Request.GetInstance().getRecordsOrCountByCriterion(apiName, await (0, logic_1.handleCriterion)(criterion), orders, false, selectFields, i, newLimit, false);
529
+ }
530
+ queryCount += rs.length;
531
+ try {
532
+ if (rs.length > 0) {
533
+ await handler(rs);
534
+ }
535
+ }
536
+ catch (err) {
537
+ throw err;
538
+ }
539
+ if (rs.length < queryBuilder_1.defaultLimit) {
540
+ break;
541
+ }
542
+ }
543
+ }
407
544
  async getRecordsByPage() {
408
545
  const { apiName, appCtx, queryBuilder, queryV2 } = queryPropertiesStore.get(this);
409
546
  let maxId = 0, records = [];
@@ -426,13 +563,13 @@ class _KQuery {
426
563
  }
427
564
  else {
428
565
  let criterion = (0, logic_1.buildCriterion)(queryBuilder.getLogic(), apiName, maxId);
429
- rs = await Request.GetInstance().getRecordsOrCountByCriterion(apiName, await (0, logic_1.handleCriterion)(criterion), [new order_1.Order("_id", "asc")], false, queryBuilder.getSelect(), 0, queryBuilder_1.maxLimit, false);
566
+ rs = await Request.GetInstance().getRecordsOrCountByCriterion(apiName, await (0, logic_1.handleCriterion)(criterion), [new order_1.Order("_id", "asc")], false, queryBuilder.getSelect(), 0, queryBuilder_1.defaultLimit, false);
430
567
  }
431
568
  rs.forEach((r) => {
432
569
  maxId = r._id > maxId ? r._id : maxId;
433
570
  });
434
571
  records.push(...rs);
435
- if (rs.length < queryBuilder_1.maxLimit) {
572
+ if (rs.length < queryBuilder_1.defaultLimit) {
436
573
  break;
437
574
  }
438
575
  }
@@ -542,6 +679,20 @@ class _KQuery {
542
679
  }
543
680
  }
544
681
  ;
682
+ findPreCheck() {
683
+ const { queryBuilder, queryV2 } = queryPropertiesStore.get(this);
684
+ let limit = queryBuilder_1.defaultLimit;
685
+ if (queryV2) {
686
+ limit = queryV2._limit;
687
+ }
688
+ else {
689
+ limit = queryBuilder.limit;
690
+ }
691
+ if (limit < 1) {
692
+ // need import exceptions
693
+ throw new server_common_node_1.exceptions.InvalidParamError(`limit(${limit}) < 1`);
694
+ }
695
+ }
545
696
  }
546
697
  function applyMixins(derivedCtor, constructors) {
547
698
  constructors.forEach((baseCtor) => {
@@ -1,7 +1,6 @@
1
1
  import { Order, OrderType } from './order';
2
2
  import { Logic } from '../../../kunlun/operator/impl/logic';
3
- export declare const maxLimit = 200;
4
- export declare const maxLimitV2 = 10000;
3
+ export declare const defaultLimit = 200;
5
4
  /**
6
5
  * 查询构造器,在 DB 中被初始化,用于构建一次查询
7
6
  */
@@ -11,6 +10,7 @@ export declare class QueryBuilder {
11
10
  select: string[];
12
11
  where: Logic[];
13
12
  limit: number;
13
+ isSetLimit: boolean;
14
14
  offset: number;
15
15
  order: Order[];
16
16
  logic: Logic;
@@ -2,13 +2,12 @@
2
2
  // Copyright 2022 ByteDance Ltd. and/or its affiliates
3
3
  // SPDX-License-Identifier: MIT
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.QueryBuilder = exports.maxLimitV2 = exports.maxLimit = void 0;
5
+ exports.QueryBuilder = exports.defaultLimit = void 0;
6
6
  const order_1 = require("./order");
7
7
  const logic_1 = require("../../../kunlun/operator/impl/logic");
8
8
  const server_common_node_1 = require("@byted-apaas/server-common-node");
9
- exports.maxLimit = 200;
10
- // 限制开放至 1w,当仅查询 _id 时,最大可返回 1w,其他查询字段时仅返回 200,由底层控制。
11
- exports.maxLimitV2 = 10000;
9
+ // SDK 仅作 limit 小于 0 校验,其他校验拦截由底层控制,如当查询结果不满足受控条件时,limit 仅支持最大 200
10
+ exports.defaultLimit = 200;
12
11
  /**
13
12
  * 查询构造器,在 DB 中被初始化,用于构建一次查询
14
13
  */
@@ -18,7 +17,7 @@ class QueryBuilder {
18
17
  this.dataSource = '';
19
18
  this.select = [];
20
19
  this.where = null;
21
- this.limit = exports.maxLimit;
20
+ this.limit = exports.defaultLimit;
22
21
  this.offset = 0;
23
22
  this.order = [];
24
23
  this.logic = new logic_1.Logic();
@@ -60,15 +59,8 @@ class QueryBuilder {
60
59
  this.offset = offset;
61
60
  }
62
61
  setLimit(limit) {
63
- if (limit < 1) {
64
- // need import exceptions
65
- throw new server_common_node_1.exceptions.InvalidParamError(`limit(${limit}) < 1`);
66
- }
67
- if (limit > exports.maxLimitV2) {
68
- // need import exceptions
69
- throw new server_common_node_1.exceptions.InvalidParamError(`limit(${limit}) > ${exports.maxLimitV2}. Limit should be 1~${exports.maxLimitV2} when querying the id field, otherwise it should be 1~${exports.maxLimit}`);
70
- }
71
62
  this.limit = limit;
63
+ this.isSetLimit = true;
72
64
  }
73
65
  getLimit() {
74
66
  return this.limit;
@@ -36,6 +36,7 @@ export declare class LogicalExpression {
36
36
  export declare class QueryV2 {
37
37
  objectApiName: string;
38
38
  _limit: number;
39
+ isSetLimit: boolean;
39
40
  _offset: number;
40
41
  fields: string[];
41
42
  _order: OrderV2[];
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildCriterionV2 = exports.logical = exports.QueryV2 = exports.LogicalExpression = exports.ArithmeticExpression = exports.NewConstantExpressionField = exports.NewMetadataExpressionField = void 0;
4
4
  const operator_1 = require("./operator");
5
- const queryBuilder_1 = require("../../../context/db/impl/queryBuilder");
6
5
  function NewMetadataExpressionField(objectApiName, fieldApiName) {
7
6
  return {
8
7
  type: "metadataVariable",
@@ -110,10 +109,8 @@ class QueryV2 {
110
109
  return this;
111
110
  }
112
111
  limit(limit) {
113
- if (limit <= 0 || limit > 10000) {
114
- throw new Error(`limit(${limit}) > ${queryBuilder_1.maxLimitV2}. Limit should be 1~${queryBuilder_1.maxLimitV2} when querying the id field, otherwise it should be 1~${queryBuilder_1.maxLimit}`);
115
- }
116
112
  this._limit = limit;
113
+ this.isSetLimit = true;
117
114
  return this;
118
115
  }
119
116
  orderBy(fieldApiNames) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byted-apaas/server-sdk-node",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "aPaaS Server SDK",
5
5
  "author": "zhouwexin <zhouwexin@bytedance.com>",
6
6
  "homepage": "",