oak-domain 4.0.0 → 4.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.
Files changed (37) hide show
  1. package/lib/store/AsyncRowStore.d.ts +9 -4
  2. package/lib/store/AsyncRowStore.js +68 -10
  3. package/lib/store/CascadeStore.d.ts +6 -4
  4. package/lib/store/CascadeStore.js +94 -42
  5. package/lib/store/TriggerExecutor.d.ts +6 -3
  6. package/lib/store/TriggerExecutor.js +132 -123
  7. package/lib/store/filter.js +9 -8
  8. package/lib/types/Demand.d.ts +1 -0
  9. package/lib/types/Entity.d.ts +8 -2
  10. package/lib/types/Environment.d.ts +2 -0
  11. package/lib/types/RowStore.d.ts +5 -4
  12. package/lib/types/Timer.d.ts +11 -5
  13. package/lib/types/Trigger.d.ts +8 -14
  14. package/lib/types/Trigger.js +0 -23
  15. package/lib/types/Watcher.d.ts +1 -1
  16. package/lib/utils/SimpleConnector.js +1 -1
  17. package/lib/utils/url/index.mp.d.ts +2 -3
  18. package/lib/utils/url/index.mp.js +1 -1
  19. package/lib/utils/url/whatwg-url/index.d.ts +3 -0
  20. package/lib/utils/url/whatwg-url/index.js +16 -0
  21. package/lib/utils/url/whatwg-url/lib/URL-impl.d.ts +20 -0
  22. package/lib/utils/url/whatwg-url/lib/URL-impl.js +175 -0
  23. package/lib/utils/url/whatwg-url/lib/URL.d.ts +1 -0
  24. package/lib/utils/url/whatwg-url/lib/URL.js +298 -0
  25. package/lib/utils/url/whatwg-url/lib/URLSearchParams-impl.d.ts +19 -0
  26. package/lib/utils/url/whatwg-url/lib/URLSearchParams-impl.js +126 -0
  27. package/lib/utils/url/whatwg-url/lib/URLSearchParams.d.ts +1 -0
  28. package/lib/utils/url/whatwg-url/lib/URLSearchParams.js +426 -0
  29. package/lib/utils/url/whatwg-url/lib/infra.d.ts +12 -0
  30. package/lib/utils/url/whatwg-url/lib/infra.js +25 -0
  31. package/lib/utils/url/whatwg-url/lib/url-state-machine.d.ts +24 -0
  32. package/lib/utils/url/whatwg-url/lib/url-state-machine.js +1238 -0
  33. package/lib/utils/url/whatwg-url/lib/urlencoded.d.ts +15 -0
  34. package/lib/utils/url/whatwg-url/lib/urlencoded.js +162 -0
  35. package/lib/utils/url/whatwg-url/lib/utils.d.ts +37 -0
  36. package/lib/utils/url/whatwg-url/lib/utils.js +101 -0
  37. package/package.json +2 -3
@@ -1,13 +1,17 @@
1
1
  /// <reference types="node" />
2
2
  import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, Context, TxnOption, OpRecord, AggregationResult, ClusterInfo } from "../types";
3
3
  import { IncomingHttpHeaders } from "http";
4
+ /**
5
+ * 服务器端执行的异步环境的底层抽象
6
+ */
4
7
  export declare abstract class AsyncContext<ED extends EntityDict> implements Context {
5
8
  rowStore: AsyncRowStore<ED, this>;
6
- clusterInfo?: ClusterInfo;
7
9
  private uuid?;
8
10
  opRecords: OpRecord<ED>[];
9
11
  private scene?;
10
- private headers?;
12
+ headers?: IncomingHttpHeaders;
13
+ clusterInfo?: ClusterInfo;
14
+ opResult: OperationResult<ED>;
11
15
  private message?;
12
16
  events: {
13
17
  commit: Array<() => Promise<void>>;
@@ -17,13 +21,14 @@ export declare abstract class AsyncContext<ED extends EntityDict> implements Con
17
21
  * 在返回结果前调用,对数据行进行一些预处理,比如将一些敏感的列隐藏
18
22
  */
19
23
  abstract refineOpRecords(): Promise<void>;
20
- constructor(store: AsyncRowStore<ED, AsyncContext<ED>>, headers?: IncomingHttpHeaders, clusterInfo?: ClusterInfo);
21
- setHeaders(headers: IncomingHttpHeaders): void;
24
+ constructor(store: AsyncRowStore<ED, AsyncContext<ED>>);
25
+ restartToExecute(routine: (context: this) => Promise<any>): Promise<void>;
22
26
  getHeader(key: string): string | string[] | undefined;
23
27
  getScene(): string | undefined;
24
28
  setScene(scene?: string): void;
25
29
  private resetEvents;
26
30
  on(event: 'commit' | 'rollback', callback: () => Promise<void>): void;
31
+ saveOpRecord<T extends keyof ED>(entity: T, operation: ED[T]['Operation']): void;
27
32
  /**
28
33
  * 一个context中不应该有并发的事务,这里将事务串行化,使用的时候千万要注意不要自己等自己
29
34
  * @param options
@@ -2,30 +2,53 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AsyncContext = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const action_1 = require("../actions/action");
5
6
  const assert_1 = tslib_1.__importDefault(require("assert"));
7
+ /**
8
+ * 服务器端执行的异步环境的底层抽象
9
+ */
6
10
  class AsyncContext {
7
11
  rowStore;
8
- clusterInfo;
9
12
  uuid;
10
13
  opRecords;
11
14
  scene;
12
15
  headers;
16
+ clusterInfo;
17
+ opResult;
13
18
  message;
14
19
  events;
15
- constructor(store, headers, clusterInfo) {
20
+ constructor(store) {
16
21
  this.rowStore = store;
17
- this.clusterInfo = clusterInfo;
18
22
  this.opRecords = [];
19
23
  this.events = {
20
24
  commit: [],
21
25
  rollback: [],
22
26
  };
23
- if (headers) {
24
- this.headers = headers;
27
+ this.opResult = {};
28
+ }
29
+ // 使一个上下文重新开始事务执行,清除历史数据(定时器中使用)
30
+ async restartToExecute(routine) {
31
+ const newContext = !this.uuid ? this : {
32
+ ...this,
33
+ }; // 这里可能有问题,继承的context对象中如果有对象属性会变成指针公用,但是估计目前是跑不到的。by Xc 20231215
34
+ if (newContext !== this) {
35
+ console.warn('restartToExecute跑出了非重用当前context的情况,请仔细调试');
36
+ }
37
+ newContext.opRecords = [];
38
+ newContext.events = {
39
+ commit: [],
40
+ rollback: [],
41
+ };
42
+ newContext.opResult = {};
43
+ await newContext.begin();
44
+ try {
45
+ await routine(newContext);
46
+ await newContext.commit();
47
+ }
48
+ catch (err) {
49
+ await newContext.rollback();
50
+ throw err;
25
51
  }
26
- }
27
- setHeaders(headers) {
28
- this.headers = headers;
29
52
  }
30
53
  getHeader(key) {
31
54
  if (this.headers) {
@@ -47,6 +70,39 @@ class AsyncContext {
47
70
  on(event, callback) {
48
71
  this.uuid && this.events[event].push(callback);
49
72
  }
73
+ saveOpRecord(entity, operation) {
74
+ const { action, data, filter, id } = operation;
75
+ switch (action) {
76
+ case 'create': {
77
+ this.opRecords.push({
78
+ id,
79
+ a: 'c',
80
+ e: entity,
81
+ d: data
82
+ });
83
+ break;
84
+ }
85
+ case 'remove': {
86
+ this.opRecords.push({
87
+ id,
88
+ a: 'r',
89
+ e: entity,
90
+ f: filter,
91
+ });
92
+ break;
93
+ }
94
+ default: {
95
+ (0, assert_1.default)(!action_1.readOnlyActions.includes(action));
96
+ this.opRecords.push({
97
+ id,
98
+ a: 'u',
99
+ e: entity,
100
+ d: data,
101
+ f: filter,
102
+ });
103
+ }
104
+ }
105
+ }
50
106
  /**
51
107
  * 一个context中不应该有并发的事务,这里将事务串行化,使用的时候千万要注意不要自己等自己
52
108
  * @param options
@@ -82,8 +138,10 @@ class AsyncContext {
82
138
  }
83
139
  }
84
140
  }
85
- operate(entity, operation, option) {
86
- return this.rowStore.operate(entity, operation, this, option);
141
+ async operate(entity, operation, option) {
142
+ const result = await this.rowStore.operate(entity, operation, this, option);
143
+ this.opResult = this.mergeMultipleResults([this.opResult, result]);
144
+ return result;
87
145
  }
88
146
  select(entity, selection, option) {
89
147
  return this.rowStore.select(entity, selection, this, option);
@@ -15,15 +15,15 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
15
15
  private reinforceSelectionSync;
16
16
  private reinforceSelectionInner;
17
17
  private reinforceOperation;
18
- registerOperationRewriter(rewriter: OperationRewriter<ED, AsyncContext<ED> | SyncContext<ED>>): void;
19
- registerSelectionRewriter(rewriter: SelectionRewriter<ED, AsyncContext<ED> | SyncContext<ED>>): void;
18
+ registerOperationRewriter(rewriter: OperationRewriter<ED, AsyncContext<ED> | SyncContext<ED>, OperateOption>): void;
19
+ registerSelectionRewriter(rewriter: SelectionRewriter<ED, AsyncContext<ED> | SyncContext<ED>, SelectOption>): void;
20
20
  protected abstract selectAbjointRow<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]['Schema']>[];
21
21
  protected abstract updateAbjointRow<T extends keyof ED, OP extends OperateOption, Cxt extends SyncContext<ED>>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): number;
22
22
  protected abstract selectAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Promise<Partial<ED[T]['Schema']>[]>;
23
23
  protected abstract countAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: Cxt, option: OP): Promise<number>;
24
24
  protected abstract updateAbjointRowAsync<T extends keyof ED, OP extends OperateOption, Cxt extends AsyncContext<ED>>(entity: T, operation: ED[T]['Create'] | ED[T]['Update'] | ED[T]['Remove'], context: Cxt, option: OP): Promise<number>;
25
- protected abstract aggregateSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): AggregationResult<ED[T]['Schema']>;
26
- protected abstract aggregateAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): Promise<AggregationResult<ED[T]['Schema']>>;
25
+ protected abstract aggregateAbjointRowSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): AggregationResult<ED[T]['Schema']>;
26
+ protected abstract aggregateAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): Promise<AggregationResult<ED[T]['Schema']>>;
27
27
  protected destructCascadeSelect<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED> | AsyncContext<ED>>(entity: T, projection2: ED[T]['Selection']['data'], context: Cxt, cascadeSelectFn: <T2 extends keyof ED>(entity2: T2, selection: ED[T2]['Selection'], context: Cxt, op: OP) => Partial<ED[T2]['Schema']>[] | Promise<Partial<ED[T2]['Schema']>[]>, aggregateFn: <T2 extends keyof ED>(entity2: T2, aggregation: ED[T2]['Aggregation'], context: Cxt, op: OP) => AggregationResult<ED[T2]['Schema']> | Promise<AggregationResult<ED[T2]['Schema']>>, option: OP): {
28
28
  projection: ED[T]["Selection"]["data"];
29
29
  cascadeSelectionFns: ((result: Partial<ED[T]['Schema']>[]) => Promise<void> | void)[];
@@ -97,6 +97,8 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
97
97
  private addToResultSelections;
98
98
  private addSingleRowToResultSelections;
99
99
  protected cascadeSelectAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Promise<Partial<ED[T]['Schema']>[]>;
100
+ protected aggregateAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): Promise<AggregationResult<ED[T]['Schema']>>;
101
+ protected aggregateSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): AggregationResult<ED[T]['Schema']>;
100
102
  protected selectAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Promise<Partial<ED[T]['Schema']>[]>;
101
103
  protected selectSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]['Schema']>[];
102
104
  protected operateSync<T extends keyof ED, Cxt extends SyncContext<ED>, OP extends OperateOption>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): OperationResult<ED>;
@@ -20,17 +20,21 @@ class CascadeStore extends RowStore_1.RowStore {
20
20
  }
21
21
  selectionRewriters = [];
22
22
  operationRewriters = [];
23
- async reinforceSelectionAsync(entity, selection, context, option) {
24
- this.reinforceSelectionInner(entity, selection, context);
25
- const rewriterPromises = this.selectionRewriters.map(ele => ele(this.getSchema(), entity, selection, context));
23
+ async reinforceSelectionAsync(entity, selection, context, option, isAggr) {
24
+ if (!isAggr && !selection.distinct) {
25
+ this.reinforceSelectionInner(entity, selection, context);
26
+ }
27
+ const rewriterPromises = this.selectionRewriters.map(ele => ele(this.getSchema(), entity, selection, context, option, isAggr));
26
28
  if (rewriterPromises.length > 0) {
27
29
  await Promise.all(rewriterPromises);
28
30
  }
29
31
  }
30
- reinforceSelectionSync(entity, selection, context, option) {
31
- this.reinforceSelectionInner(entity, selection, context);
32
+ reinforceSelectionSync(entity, selection, context, option, isAggr) {
33
+ if (!isAggr && !selection.distinct) {
34
+ this.reinforceSelectionInner(entity, selection, context);
35
+ }
32
36
  this.selectionRewriters.forEach(ele => {
33
- const result = ele(this.getSchema(), entity, selection, context);
37
+ const result = ele(this.getSchema(), entity, selection, context, option);
34
38
  (0, assert_1.default)(!(result instanceof Promise));
35
39
  });
36
40
  }
@@ -312,8 +316,8 @@ class CascadeStore extends RowStore_1.RowStore {
312
316
  });
313
317
  }
314
318
  }
315
- async reinforceOperation(entity, operation, context) {
316
- await Promise.all(this.operationRewriters.map(ele => ele(this.getSchema(), entity, operation, context)));
319
+ async reinforceOperation(entity, operation, context, option) {
320
+ await Promise.all(this.operationRewriters.map(ele => ele(this.getSchema(), entity, operation, context, option)));
317
321
  }
318
322
  registerOperationRewriter(rewriter) {
319
323
  this.operationRewriters.push(rewriter);
@@ -682,12 +686,14 @@ class CascadeStore extends RowStore_1.RowStore {
682
686
  (0, assert_1.default)(!option2.modiParentId && !option2.modiParentEntity);
683
687
  if (action === 'create') {
684
688
  option2.modiParentId = data.id;
689
+ option2.modiParentEntity = entity;
685
690
  }
686
- else {
687
- (0, assert_1.default)(filter?.id && typeof filter.id === 'string');
691
+ else if (filter?.id && typeof filter.id === 'string') {
692
+ // 如果是对toModi对象进行cascadeUpdate操作,必然带有id,如果没有则认为不是modi相关的操作
693
+ // 批量通过或者拒绝applyment应该就会出现
688
694
  option2.modiParentId = filter.id;
695
+ option2.modiParentEntity = entity;
689
696
  }
690
- option2.modiParentEntity = entity;
691
697
  }
692
698
  for (const attr in data) {
693
699
  const relation = (0, relation_1.judgeRelation)(this.storageSchema, entity, attr);
@@ -1037,14 +1043,18 @@ class CascadeStore extends RowStore_1.RowStore {
1037
1043
  const closeRootMode = context.openRootMode();
1038
1044
  await this.cascadeUpdateAsync('modi', modiCreate, context, option);
1039
1045
  closeRootMode();
1040
- return 1;
1046
+ return {
1047
+ 'modi': {
1048
+ create: 1,
1049
+ }
1050
+ };
1041
1051
  }
1042
1052
  else {
1043
1053
  this.preProcessDataCreated(entity, data);
1044
1054
  let result = 0;
1045
1055
  const createInner = async (operation2) => {
1046
1056
  try {
1047
- result += await this.updateAbjointRowAsync(entity, operation2, context, option);
1057
+ await this.updateAbjointRowAsync(entity, operation2, context, option);
1048
1058
  }
1049
1059
  catch (e) {
1050
1060
  /* 这段代码是处理插入时有重复的行,现在看有问题,等实际需求出现再写
@@ -1114,6 +1124,7 @@ class CascadeStore extends RowStore_1.RowStore {
1114
1124
  }
1115
1125
  };
1116
1126
  if (data instanceof Array) {
1127
+ result = data.length;
1117
1128
  const multipleCreate = this.supportMultipleCreate();
1118
1129
  if (multipleCreate) {
1119
1130
  await createInner(operation);
@@ -1130,14 +1141,16 @@ class CascadeStore extends RowStore_1.RowStore {
1130
1141
  }
1131
1142
  }
1132
1143
  else {
1144
+ result = 1;
1133
1145
  await createInner(operation);
1134
1146
  }
1135
1147
  if (!option.dontCollect) {
1136
- context.opRecords.push({
1148
+ context.saveOpRecord(entity, operation);
1149
+ /* context.opRecords.push({
1137
1150
  a: 'c',
1138
1151
  e: entity,
1139
- d: data,
1140
- });
1152
+ d: data as ED[T]['OpSchema'] | ED[T]['OpSchema'][],
1153
+ }); */
1141
1154
  }
1142
1155
  if (!option.dontCreateOper && !['oper', 'operEntity', 'modiEntity', 'modi'].includes(entity)) {
1143
1156
  // 按照框架要求生成Oper和OperEntity这两个内置的对象
@@ -1180,7 +1193,11 @@ class CascadeStore extends RowStore_1.RowStore {
1180
1193
  closeRootMode();
1181
1194
  }
1182
1195
  }
1183
- return result;
1196
+ return {
1197
+ [entity]: {
1198
+ ['create']: result,
1199
+ }
1200
+ };
1184
1201
  }
1185
1202
  }
1186
1203
  default: {
@@ -1283,7 +1300,11 @@ class CascadeStore extends RowStore_1.RowStore {
1283
1300
  const closeRootMode = context.openRootMode();
1284
1301
  await this.cascadeUpdateAsync('modi', modiUpsert, context, option);
1285
1302
  closeRootMode();
1286
- return 1;
1303
+ return {
1304
+ modi: {
1305
+ ['create']: 1,
1306
+ },
1307
+ };
1287
1308
  }
1288
1309
  else {
1289
1310
  const createOper = async () => {
@@ -1319,7 +1340,17 @@ class CascadeStore extends RowStore_1.RowStore {
1319
1340
  };
1320
1341
  if (action === 'remove') {
1321
1342
  if (!option.dontCollect) {
1322
- context.opRecords.push({
1343
+ context.saveOpRecord(entity, {
1344
+ id: operId,
1345
+ action,
1346
+ data: {},
1347
+ filter: {
1348
+ id: {
1349
+ $in: ids,
1350
+ }
1351
+ }
1352
+ });
1353
+ /* context.opRecords.push({
1323
1354
  a: 'r',
1324
1355
  e: entity,
1325
1356
  f: {
@@ -1327,7 +1358,7 @@ class CascadeStore extends RowStore_1.RowStore {
1327
1358
  $in: ids,
1328
1359
  }
1329
1360
  },
1330
- });
1361
+ }); */
1331
1362
  }
1332
1363
  }
1333
1364
  else {
@@ -1338,30 +1369,44 @@ class CascadeStore extends RowStore_1.RowStore {
1338
1369
  $$updateAt$$: now,
1339
1370
  });
1340
1371
  if (!option.dontCollect) {
1341
- context.opRecords.push({
1372
+ context.saveOpRecord(entity, {
1373
+ id: operId,
1374
+ action,
1375
+ data: data,
1376
+ filter: {
1377
+ id: {
1378
+ $in: ids,
1379
+ }
1380
+ },
1381
+ });
1382
+ /* context.opRecords.push({
1342
1383
  a: 'u',
1343
1384
  e: entity,
1344
- d: data,
1385
+ d: data as ED[T]['Update']['data'],
1345
1386
  f: {
1346
1387
  id: {
1347
1388
  $in: ids,
1348
1389
  }
1349
1390
  },
1350
- });
1391
+ }); */
1351
1392
  }
1352
1393
  }
1353
1394
  else if (action !== 'update') {
1354
1395
  // 如果不是update动作而是用户自定义的动作,这里还是要记录oper
1355
1396
  await createOper();
1356
- return 0;
1397
+ return {};
1357
1398
  }
1358
1399
  else {
1359
- return 0;
1400
+ return {};
1360
1401
  }
1361
1402
  }
1362
- const result = await this.updateAbjointRowAsync(entity, operation, context, option);
1403
+ await this.updateAbjointRowAsync(entity, operation, context, option);
1363
1404
  await createOper();
1364
- return result;
1405
+ return {
1406
+ [entity]: {
1407
+ [action]: ids.length,
1408
+ }
1409
+ };
1365
1410
  }
1366
1411
  }
1367
1412
  }
@@ -1467,7 +1512,6 @@ class CascadeStore extends RowStore_1.RowStore {
1467
1512
  let opData;
1468
1513
  const wholeBeforeFns = [];
1469
1514
  const wholeAfterFns = [];
1470
- const result = {};
1471
1515
  if (['create', 'create-l'].includes(action) && data instanceof Array) {
1472
1516
  opData = [];
1473
1517
  for (const d of data) {
@@ -1486,29 +1530,29 @@ class CascadeStore extends RowStore_1.RowStore {
1486
1530
  const operation2 = Object.assign({}, operation, {
1487
1531
  data: opData,
1488
1532
  });
1533
+ let result = {};
1489
1534
  for (const before of wholeBeforeFns) {
1490
- await before();
1535
+ const result2 = await before();
1536
+ result = this.mergeMultipleResults([result, result2]);
1491
1537
  }
1492
- const count = await this.doUpdateSingleRowAsync(entity, operation2, context, option);
1493
- this.mergeOperationResult(result, {
1494
- [entity]: {
1495
- [operation2.action]: count,
1496
- }
1497
- });
1538
+ const resultMe = await this.doUpdateSingleRowAsync(entity, operation2, context, option);
1539
+ result = this.mergeMultipleResults([result, resultMe]);
1498
1540
  for (const after of wholeAfterFns) {
1499
- await after();
1541
+ const result2 = await after();
1542
+ result = this.mergeMultipleResults([result, result2]);
1500
1543
  }
1501
1544
  return result;
1502
1545
  }
1503
1546
  cascadeSelect(entity, selection, context, option) {
1504
- const { data, filter, indexFrom, count, sorter } = selection;
1547
+ const { data, filter, indexFrom, count, sorter, distinct } = selection;
1505
1548
  const { projection, cascadeSelectionFns } = this.destructCascadeSelect(entity, data, context, this.cascadeSelect, this.aggregateSync, option);
1506
1549
  const rows = this.selectAbjointRow(entity, {
1507
1550
  data: projection,
1508
1551
  filter,
1509
1552
  indexFrom,
1510
1553
  count,
1511
- sorter
1554
+ sorter,
1555
+ distinct
1512
1556
  }, context, option);
1513
1557
  if (cascadeSelectionFns.length > 0) {
1514
1558
  const ruException = [];
@@ -1574,8 +1618,7 @@ class CascadeStore extends RowStore_1.RowStore {
1574
1618
  const entityBranch = lastOperation.d[entity];
1575
1619
  if (entityBranch) {
1576
1620
  rows.forEach((row) => {
1577
- if (row) {
1578
- (0, assert_1.default)(row.id);
1621
+ if (row && row.id) { // 如果没有row.id就不加入结果集了
1579
1622
  const { id } = row;
1580
1623
  if (!entityBranch[id]) {
1581
1624
  Object.assign(entityBranch, {
@@ -1611,12 +1654,13 @@ class CascadeStore extends RowStore_1.RowStore {
1611
1654
  });
1612
1655
  }
1613
1656
  async cascadeSelectAsync(entity, selection, context, option) {
1614
- const { data, filter, indexFrom, count, sorter, total, randomRange } = selection;
1657
+ const { data, filter, indexFrom, count, sorter, total, randomRange, distinct } = selection;
1615
1658
  const { projection, cascadeSelectionFns } = this.destructCascadeSelect(entity, data, context, this.cascadeSelectAsync, this.aggregateAsync, option);
1616
1659
  const rows2 = await this.selectAbjointRowAsync(entity, {
1617
1660
  data: projection,
1618
1661
  filter,
1619
1662
  indexFrom,
1663
+ distinct,
1620
1664
  count: randomRange || count,
1621
1665
  sorter
1622
1666
  }, context, option);
@@ -1668,6 +1712,14 @@ class CascadeStore extends RowStore_1.RowStore {
1668
1712
  }
1669
1713
  return rows;
1670
1714
  }
1715
+ async aggregateAsync(entity, aggregation, context, option) {
1716
+ await this.reinforceSelectionAsync(entity, aggregation, context, option, true);
1717
+ return this.aggregateAbjointRowAsync(entity, aggregation, context, option);
1718
+ }
1719
+ aggregateSync(entity, aggregation, context, option) {
1720
+ this.reinforceSelectionSync(entity, aggregation, context, option, true);
1721
+ return this.aggregateAbjointRowSync(entity, aggregation, context, option);
1722
+ }
1671
1723
  async selectAsync(entity, selection, context, option) {
1672
1724
  await this.reinforceSelectionAsync(entity, selection, context, option);
1673
1725
  return this.cascadeSelectAsync(entity, selection, context, option);
@@ -1681,7 +1733,7 @@ class CascadeStore extends RowStore_1.RowStore {
1681
1733
  return this.cascadeUpdate(entity, operation, context, option);
1682
1734
  }
1683
1735
  async operateAsync(entity, operation, context, option) {
1684
- await this.reinforceOperation(entity, operation, context);
1736
+ await this.reinforceOperation(entity, operation, context, option);
1685
1737
  return this.cascadeUpdateAsync(entity, operation, context, option);
1686
1738
  }
1687
1739
  }
@@ -2,7 +2,7 @@ import { EntityDict, OperateOption, SelectOption } from "../types/Entity";
2
2
  import { EntityDict as BaseEntityDict } from '../base-app-domain';
3
3
  import { Logger } from "../types/Logger";
4
4
  import { Checker } from '../types/Auth';
5
- import { Trigger } from "../types/Trigger";
5
+ import { Trigger, VolatileTrigger } from "../types/Trigger";
6
6
  import { AsyncContext } from './AsyncRowStore';
7
7
  /**
8
8
  * update可能会传入多种不同的action,此时都需要检查update trigger
@@ -14,15 +14,18 @@ export declare class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt
14
14
  private volatileEntities;
15
15
  private logger;
16
16
  private contextBuilder;
17
- constructor(contextBuilder: (cxtString?: string) => Promise<Cxt>, logger?: Logger);
17
+ private onVolatileTrigger;
18
+ constructor(contextBuilder: (cxtString?: string) => Promise<Cxt>, logger?: Logger, onVolatileTrigger?: <T extends keyof ED>(entity: T, trigger: VolatileTrigger<ED, T, Cxt>, ids: string[], cxtStr: string, option: OperateOption) => Promise<void>);
19
+ setOnVolatileTrigger(onVolatileTrigger: <T extends keyof ED>(entity: T, trigger: VolatileTrigger<ED, T, Cxt>, ids: string[], cxtStr: string, option: OperateOption) => Promise<void>): void;
18
20
  registerChecker<T extends keyof ED>(checker: Checker<ED, T, Cxt>): void;
19
21
  registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
20
22
  unregisterTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
21
23
  private preCommitTrigger;
24
+ private postCommitTrigger;
22
25
  preOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation'] | ED[T]['Selection'] & {
23
26
  action: 'select';
24
27
  }, context: Cxt, option: OperateOption | SelectOption): Promise<void> | void;
25
- private execVolatileTrigger;
28
+ execVolatileTrigger<T extends keyof ED>(entity: T, name: string, ids: string[], context: Cxt, option: OperateOption): Promise<void>;
26
29
  /**
27
30
  * 判断一个trigger和当前modi上下文是否符合
28
31
  * trigger的默认行为是:如果是commit时机的trigger,不显式声明则只能在modi apply时执行(create时不执行);非commit时机的trigger,不显式声明则只在modi create时执行