oak-domain 2.2.0 → 2.3.0

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.
@@ -17,7 +17,7 @@ var CascadeStore = /** @class */ (function (_super) {
17
17
  function CascadeStore(storageSchema) {
18
18
  return _super.call(this, storageSchema) || this;
19
19
  }
20
- CascadeStore.prototype.destructCascadeSelect = function (entity, projection2, context, cascadeSelect, option) {
20
+ CascadeStore.prototype.destructCascadeSelect = function (entity, projection2, context, cascadeSelectFn, aggregateFn, option) {
21
21
  var _this = this;
22
22
  var projection = {};
23
23
  var cascadeSelectionFns = [];
@@ -58,7 +58,7 @@ var CascadeStore = /** @class */ (function (_super) {
58
58
  });
59
59
  }
60
60
  });
61
- var _e = this_1.destructCascadeSelect(attr, projection2[attr], context, cascadeSelect, option), subProjection = _e.projection, subCascadeSelectionFns = _e.cascadeSelectionFns;
61
+ var _e = this_1.destructCascadeSelect(attr, projection2[attr], context, cascadeSelectFn, aggregateFn, option), subProjection = _e.projection, subCascadeSelectionFns = _e.cascadeSelectionFns;
62
62
  Object.assign(projection, (_b = {},
63
63
  _b[attr] = subProjection,
64
64
  _b));
@@ -101,7 +101,7 @@ var CascadeStore = /** @class */ (function (_super) {
101
101
  });
102
102
  };
103
103
  var entityIds = (0, lodash_1.uniq)(result.filter(function (ele) { return ele.entity === attr; }).map(function (ele) { return ele.entityId; }));
104
- var subRows = cascadeSelect.call(_this, attr, {
104
+ var subRows = cascadeSelectFn.call(_this, attr, {
105
105
  data: projection2[attr],
106
106
  filter: {
107
107
  id: {
@@ -143,7 +143,7 @@ var CascadeStore = /** @class */ (function (_super) {
143
143
  }
144
144
  });
145
145
  }
146
- var _f = this_1.destructCascadeSelect(relation, projection2[attr], context, cascadeSelect, option), subProjection = _f.projection, subCascadeSelectionFns = _f.cascadeSelectionFns;
146
+ var _f = this_1.destructCascadeSelect(relation, projection2[attr], context, cascadeSelectFn, aggregateFn, option), subProjection = _f.projection, subCascadeSelectionFns = _f.cascadeSelectionFns;
147
147
  Object.assign(projection, (_d = {},
148
148
  _d[attr] = subProjection,
149
149
  _d));
@@ -191,7 +191,7 @@ var CascadeStore = /** @class */ (function (_super) {
191
191
  });
192
192
  };
193
193
  var ids = (0, lodash_1.uniq)(result.filter(function (ele) { return !!(ele["".concat(attr, "Id")]); }).map(function (ele) { return ele["".concat(attr, "Id")]; }));
194
- var subRows = cascadeSelect.call(_this, relation, {
194
+ var subRows = cascadeSelectFn.call(_this, relation, {
195
195
  data: projection2[attr],
196
196
  filter: {
197
197
  id: {
@@ -210,69 +210,143 @@ var CascadeStore = /** @class */ (function (_super) {
210
210
  (0, assert_1.default)(relation instanceof Array);
211
211
  var _g = projection2[attr], subProjection_1 = _g.data, subFilter_1 = _g.filter, indexFrom_1 = _g.indexFrom, count_1 = _g.count, subSorter_1 = _g.sorter;
212
212
  var _h = tslib_1.__read(relation, 2), entity2_1 = _h[0], foreignKey_1 = _h[1];
213
+ var isAggr = attr.endsWith('$$aggr');
213
214
  if (foreignKey_1) {
214
215
  // 基于属性的一对多
215
- cascadeSelectionFns.push(function (result) {
216
- var _a;
217
- var ids = result.map(function (ele) { return ele.id; });
218
- var dealWithSubRows = function (subRows) {
219
- result.forEach(function (ele) {
220
- var _a;
221
- var subRowss = subRows.filter(function (ele2) { return ele2[foreignKey_1] === ele.id; });
222
- (0, assert_1.default)(subRowss);
223
- Object.assign(ele, (_a = {},
224
- _a[attr] = subRowss,
225
- _a));
216
+ if (isAggr) {
217
+ // 是聚合运算
218
+ cascadeSelectionFns.push(function (result) {
219
+ var aggrResults = result.map(function (row) {
220
+ var _a, _b;
221
+ var aggrResult = aggregateFn.call(_this, entity2_1, {
222
+ data: subProjection_1,
223
+ filter: (0, filter_1.combineFilters)([(_a = {},
224
+ _a[foreignKey_1] = row.id,
225
+ _a), subFilter_1]),
226
+ sorter: subSorter_1,
227
+ indexFrom: indexFrom_1,
228
+ count: count_1
229
+ }, context, option);
230
+ if (aggrResult instanceof Promise) {
231
+ return aggrResult.then(function (aggrResultResult) {
232
+ var _a;
233
+ return Object.assign(row, (_a = {},
234
+ _a[attr] = aggrResultResult,
235
+ _a));
236
+ });
237
+ }
238
+ else {
239
+ Object.assign(row, (_b = {},
240
+ _b[attr] = aggrResult,
241
+ _b));
242
+ }
226
243
  });
227
- };
228
- var subRows = cascadeSelect.call(_this, entity2_1, {
229
- data: subProjection_1,
230
- filter: (0, filter_1.combineFilters)([(_a = {},
231
- _a[foreignKey_1] = {
232
- $in: ids,
233
- },
234
- _a), subFilter_1]),
235
- sorter: subSorter_1,
236
- indexFrom: indexFrom_1,
237
- count: count_1
238
- }, context, option);
239
- if (subRows instanceof Promise) {
240
- return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
241
- }
242
- dealWithSubRows(subRows);
243
- });
244
+ if (aggrResults.length > 0 && aggrResults[0] instanceof Promise) {
245
+ return Promise.all(aggrResults).then(function () { return undefined; });
246
+ }
247
+ });
248
+ }
249
+ else {
250
+ // 是一对多查询
251
+ cascadeSelectionFns.push(function (result) {
252
+ var _a;
253
+ var ids = result.map(function (ele) { return ele.id; });
254
+ var dealWithSubRows = function (subRows) {
255
+ result.forEach(function (ele) {
256
+ var _a;
257
+ var subRowss = subRows.filter(function (ele2) { return ele2[foreignKey_1] === ele.id; });
258
+ (0, assert_1.default)(subRowss);
259
+ Object.assign(ele, (_a = {},
260
+ _a[attr] = subRowss,
261
+ _a));
262
+ });
263
+ };
264
+ var subRows = cascadeSelectFn.call(_this, entity2_1, {
265
+ data: subProjection_1,
266
+ filter: (0, filter_1.combineFilters)([(_a = {},
267
+ _a[foreignKey_1] = {
268
+ $in: ids,
269
+ },
270
+ _a), subFilter_1]),
271
+ sorter: subSorter_1,
272
+ indexFrom: indexFrom_1,
273
+ count: count_1
274
+ }, context, option);
275
+ if (subRows instanceof Promise) {
276
+ return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
277
+ }
278
+ dealWithSubRows(subRows);
279
+ });
280
+ }
244
281
  }
245
282
  else {
246
283
  // 基于entity的多对一
247
- cascadeSelectionFns.push(function (result) {
248
- var ids = result.map(function (ele) { return ele.id; });
249
- var dealWithSubRows = function (subRows) {
250
- result.forEach(function (ele) {
284
+ if (isAggr) {
285
+ // 是聚合运算
286
+ cascadeSelectionFns.push(function (result) {
287
+ var aggrResults = result.map(function (row) {
251
288
  var _a;
252
- var subRowss = subRows.filter(function (ele2) { return ele2.entityId === ele.id; });
253
- (0, assert_1.default)(subRowss);
254
- Object.assign(ele, (_a = {},
255
- _a[attr] = subRowss,
256
- _a));
289
+ var aggrResult = aggregateFn.call(_this, entity2_1, {
290
+ data: subProjection_1,
291
+ filter: (0, filter_1.combineFilters)([{
292
+ entity: entity,
293
+ entityId: row.id,
294
+ }, subFilter_1]),
295
+ sorter: subSorter_1,
296
+ indexFrom: indexFrom_1,
297
+ count: count_1
298
+ }, context, option);
299
+ if (aggrResult instanceof Promise) {
300
+ return aggrResult.then(function (aggrResultResult) {
301
+ var _a;
302
+ return Object.assign(row, (_a = {},
303
+ _a[attr] = aggrResultResult,
304
+ _a));
305
+ });
306
+ }
307
+ else {
308
+ Object.assign(row, (_a = {},
309
+ _a[attr] = aggrResult,
310
+ _a));
311
+ }
257
312
  });
258
- };
259
- var subRows = cascadeSelect.call(_this, entity2_1, {
260
- data: subProjection_1,
261
- filter: (0, filter_1.combineFilters)([{
262
- entity: entity,
263
- entityId: {
264
- $in: ids,
265
- }
266
- }, subFilter_1]),
267
- sorter: subSorter_1,
268
- indexFrom: indexFrom_1,
269
- count: count_1
270
- }, context, option);
271
- if (subRows instanceof Promise) {
272
- return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
273
- }
274
- dealWithSubRows(subRows);
275
- });
313
+ if (aggrResults.length > 0 && aggrResults[0] instanceof Promise) {
314
+ return Promise.all(aggrResults).then(function () { return undefined; });
315
+ }
316
+ });
317
+ }
318
+ else {
319
+ // 是一对多查询
320
+ cascadeSelectionFns.push(function (result) {
321
+ var ids = result.map(function (ele) { return ele.id; });
322
+ var dealWithSubRows = function (subRows) {
323
+ result.forEach(function (ele) {
324
+ var _a;
325
+ var subRowss = subRows.filter(function (ele2) { return ele2.entityId === ele.id; });
326
+ (0, assert_1.default)(subRowss);
327
+ Object.assign(ele, (_a = {},
328
+ _a[attr] = subRowss,
329
+ _a));
330
+ });
331
+ };
332
+ var subRows = cascadeSelectFn.call(_this, entity2_1, {
333
+ data: subProjection_1,
334
+ filter: (0, filter_1.combineFilters)([{
335
+ entity: entity,
336
+ entityId: {
337
+ $in: ids,
338
+ }
339
+ }, subFilter_1]),
340
+ sorter: subSorter_1,
341
+ indexFrom: indexFrom_1,
342
+ count: count_1
343
+ }, context, option);
344
+ if (subRows instanceof Promise) {
345
+ return subRows.then(function (subRowss) { return dealWithSubRows(subRowss); });
346
+ }
347
+ dealWithSubRows(subRows);
348
+ });
349
+ }
276
350
  }
277
351
  }
278
352
  };
@@ -1339,7 +1413,7 @@ var CascadeStore = /** @class */ (function (_super) {
1339
1413
  };
1340
1414
  CascadeStore.prototype.cascadeSelect = function (entity, selection, context, option) {
1341
1415
  var data = selection.data, filter = selection.filter, indexFrom = selection.indexFrom, count = selection.count, sorter = selection.sorter;
1342
- var _a = this.destructCascadeSelect(entity, data, context, this.cascadeSelect, option), projection = _a.projection, cascadeSelectionFns = _a.cascadeSelectionFns;
1416
+ var _a = this.destructCascadeSelect(entity, data, context, this.cascadeSelect, this.aggregateSync, option), projection = _a.projection, cascadeSelectionFns = _a.cascadeSelectionFns;
1343
1417
  var rows = this.selectAbjointRow(entity, {
1344
1418
  data: projection,
1345
1419
  filter: filter,
@@ -1460,7 +1534,7 @@ var CascadeStore = /** @class */ (function (_super) {
1460
1534
  switch (_b.label) {
1461
1535
  case 0:
1462
1536
  data = selection.data, filter = selection.filter, indexFrom = selection.indexFrom, count = selection.count, sorter = selection.sorter;
1463
- _a = this.destructCascadeSelect(entity, data, context, this.cascadeSelectAsync, option), projection = _a.projection, cascadeSelectionFns = _a.cascadeSelectionFns;
1537
+ _a = this.destructCascadeSelect(entity, data, context, this.cascadeSelectAsync, this.aggregateAsync, option), projection = _a.projection, cascadeSelectionFns = _a.cascadeSelectionFns;
1464
1538
  return [4 /*yield*/, this.selectAbjointRowAsync(entity, {
1465
1539
  data: projection,
1466
1540
  filter: filter,
@@ -1,4 +1,4 @@
1
- import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, TxnOption, Context } from "../types";
1
+ import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, TxnOption, Context, AggregationResult } from "../types";
2
2
  export declare abstract class SyncContext<ED extends EntityDict> implements Context {
3
3
  private rowStore;
4
4
  private uuid?;
@@ -13,6 +13,7 @@ export declare abstract class SyncContext<ED extends EntityDict> implements Cont
13
13
  getSchema(): import("../types").StorageSchema<ED>;
14
14
  operate<T extends keyof ED, OP extends OperateOption>(entity: T, operation: ED[T]['Operation'], option: OP): OperationResult<ED>;
15
15
  select<T extends keyof ED, OP extends SelectOption>(entity: T, selection: ED[T]['Selection'], option: OP): Partial<ED[T]["Schema"]>[];
16
+ aggregate<T extends keyof ED, OP extends SelectOption>(entity: T, aggregation: ED[T]['Aggregation'], option: OP): AggregationResult<ED[T]["Schema"]>;
16
17
  count<T extends keyof ED, OP extends SelectOption>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, option: OP): number;
17
18
  mergeMultipleResults(toBeMerged: OperationResult<ED>[]): OperationResult<ED>;
18
19
  abstract allowUserUpdate(): boolean;
@@ -21,6 +22,7 @@ export interface SyncRowStore<ED extends EntityDict, Cxt extends Context> extend
21
22
  operate<T extends keyof ED, OP extends OperateOption>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): OperationResult<ED>;
22
23
  select<T extends keyof ED, OP extends SelectOption>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]['Schema']>[];
23
24
  count<T extends keyof ED, OP extends SelectOption>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: Cxt, option: OP): number;
25
+ aggregate<T extends keyof ED, OP extends SelectOption>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): AggregationResult<ED[T]['Schema']>;
24
26
  begin(option?: TxnOption): string;
25
27
  commit(txnId: string): void;
26
28
  rollback(txnId: string): void;
@@ -32,6 +32,9 @@ var SyncContext = /** @class */ (function () {
32
32
  SyncContext.prototype.select = function (entity, selection, option) {
33
33
  return this.rowStore.select(entity, selection, this, option);
34
34
  };
35
+ SyncContext.prototype.aggregate = function (entity, aggregation, option) {
36
+ return this.rowStore.aggregate(entity, aggregation, this, option);
37
+ };
35
38
  SyncContext.prototype.count = function (entity, selection, option) {
36
39
  return this.rowStore.count(entity, selection, this, option);
37
40
  };
@@ -30,7 +30,7 @@ var TriggerExecutor = /** @class */ (function () {
30
30
  this.counter = 0;
31
31
  }
32
32
  TriggerExecutor.prototype.registerChecker = function (checker) {
33
- var entity = checker.entity, action = checker.action, type = checker.type;
33
+ var entity = checker.entity, action = checker.action, type = checker.type, conditionalFilter = checker.conditionalFilter;
34
34
  var triggerName = "".concat(String(entity)).concat(action, "\u6743\u9650\u68C0\u67E5-").concat(this.counter++);
35
35
  var fn = (0, checker_1.translateCheckerInAsyncContext)(checker);
36
36
  var trigger = {
@@ -41,6 +41,7 @@ var TriggerExecutor = /** @class */ (function () {
41
41
  action: action,
42
42
  fn: fn,
43
43
  when: 'before',
44
+ filter: conditionalFilter,
44
45
  };
45
46
  this.registerTrigger(trigger);
46
47
  };
@@ -60,6 +61,11 @@ var TriggerExecutor = /** @class */ (function () {
60
61
  if (typeof trigger.priority !== 'number') {
61
62
  trigger.priority = 1; // 默认最低
62
63
  }
64
+ if (trigger.filter) {
65
+ (0, assert_1.default)(typeof trigger.action === 'string' && trigger.action !== 'create'
66
+ || trigger.action instanceof Array && !trigger.action.includes('create'), "trigger\u3010".concat(trigger.name, "\u3011\u662Fcreate\u7C7B\u578B\u4F46\u5374\u5E26\u6709filter"));
67
+ (0, assert_1.default)(trigger.when === 'before' || trigger.when === 'commit', "\u5B9A\u4E49\u4E86filter\u7684trigger\u3010".concat(trigger.name, "\u3011\u7684when\u53EA\u80FD\u662Fbefore\u6216\u8005commit"));
68
+ }
63
69
  Object.assign(this.triggerNameMap, (_a = {},
64
70
  _a[trigger.name] = trigger,
65
71
  _a));
@@ -194,6 +200,16 @@ var TriggerExecutor = /** @class */ (function () {
194
200
  try {
195
201
  for (var preTriggers_1 = tslib_1.__values(preTriggers_2), preTriggers_1_1 = preTriggers_1.next(); !preTriggers_1_1.done; preTriggers_1_1 = preTriggers_1.next()) {
196
202
  var trigger = preTriggers_1_1.value;
203
+ if (trigger.filter) {
204
+ // trigger只对满足条件的前项进行判断,如果确定不满足可以pass
205
+ (0, assert_1.default)(operation.action !== 'create');
206
+ var filter = trigger.filter;
207
+ var filterr = typeof filter === 'function' ? filter(operation, context, option) : filter;
208
+ var filterRepelled = (0, filter_1.checkFilterRepel)(entity, context, filterr, operation.filter);
209
+ if (filterRepelled) {
210
+ continue;
211
+ }
212
+ }
197
213
  var number = trigger.fn({ operation: operation }, context, option);
198
214
  if (number > 0) {
199
215
  this.logger.info("\u89E6\u53D1\u5668\u300C".concat(trigger.name, "\u300D\u6210\u529F\u89E6\u53D1\u4E86\u300C").concat(number, "\u300D\u884C\u6570\u636E\u66F4\u6539"));
@@ -212,7 +228,7 @@ var TriggerExecutor = /** @class */ (function () {
212
228
  else {
213
229
  // 异步context
214
230
  var execPreTrigger_1 = function (idx) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
215
- var trigger, number;
231
+ var trigger, filter, filterr, filterRepelled, number;
216
232
  return tslib_1.__generator(this, function (_a) {
217
233
  switch (_a.label) {
218
234
  case 0:
@@ -220,8 +236,19 @@ var TriggerExecutor = /** @class */ (function () {
220
236
  return [2 /*return*/];
221
237
  }
222
238
  trigger = preTriggers_2[idx];
223
- return [4 /*yield*/, trigger.fn({ operation: operation }, context, option)];
239
+ if (!trigger.filter) return [3 /*break*/, 2];
240
+ (0, assert_1.default)(operation.action !== 'create');
241
+ filter = trigger.filter;
242
+ filterr = typeof filter === 'function' ? filter(operation, context, option) : filter;
243
+ return [4 /*yield*/, (0, filter_1.checkFilterRepel)(entity, context, filterr, operation.filter)];
224
244
  case 1:
245
+ filterRepelled = _a.sent();
246
+ if (filterRepelled) {
247
+ return [2 /*return*/, execPreTrigger_1(idx + 1)];
248
+ }
249
+ _a.label = 2;
250
+ case 2: return [4 /*yield*/, trigger.fn({ operation: operation }, context, option)];
251
+ case 3:
225
252
  number = _a.sent();
226
253
  if (number > 0) {
227
254
  this.logger.info("\u89E6\u53D1\u5668\u300C".concat(trigger.name, "\u300D\u6210\u529F\u89E6\u53D1\u4E86\u300C").concat(number, "\u300D\u884C\u6570\u636E\u66F4\u6539"));
@@ -231,7 +258,7 @@ var TriggerExecutor = /** @class */ (function () {
231
258
  });
232
259
  }); };
233
260
  var execCommitTrigger_1 = function (idx) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
234
- var trigger;
261
+ var trigger, filter, filterr, filterRepelled;
235
262
  return tslib_1.__generator(this, function (_a) {
236
263
  switch (_a.label) {
237
264
  case 0:
@@ -239,8 +266,19 @@ var TriggerExecutor = /** @class */ (function () {
239
266
  return [2 /*return*/];
240
267
  }
241
268
  trigger = commitTriggers_1[idx];
242
- return [4 /*yield*/, this.preCommitTrigger(entity, operation, trigger, context, option)];
269
+ if (!trigger.filter) return [3 /*break*/, 2];
270
+ (0, assert_1.default)(operation.action !== 'create');
271
+ filter = trigger.filter;
272
+ filterr = typeof filter === 'function' ? filter(operation, context, option) : filter;
273
+ return [4 /*yield*/, (0, filter_1.checkFilterRepel)(entity, context, filterr, operation.filter)];
243
274
  case 1:
275
+ filterRepelled = _a.sent();
276
+ if (filterRepelled) {
277
+ return [2 /*return*/, execCommitTrigger_1(idx + 1)];
278
+ }
279
+ _a.label = 2;
280
+ case 2: return [4 /*yield*/, this.preCommitTrigger(entity, operation, trigger, context, option)];
281
+ case 3:
244
282
  _a.sent();
245
283
  return [2 /*return*/, execCommitTrigger_1(idx + 1)];
246
284
  }
@@ -1,6 +1,7 @@
1
- import { Checker, EntityDict, OperateOption, SelectOption, Trigger } from "../types";
1
+ import { Checker, EntityDict, ExpressionRelationChecker, OperateOption, SelectOption, StorageSchema, Trigger } from "../types";
2
2
  import { EntityDict as BaseEntityDict } from '../base-app-domain';
3
3
  import { AsyncContext } from "./AsyncRowStore";
4
4
  import { SyncContext } from './SyncRowStore';
5
5
  export declare function translateCheckerInAsyncContext<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(checker: Checker<ED, keyof ED, Cxt>): Trigger<ED, keyof ED, Cxt>['fn'];
6
6
  export declare function translateCheckerInSyncContext<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends SyncContext<ED>>(checker: Checker<ED, T, Cxt>): (operation: ED[T]['Operation'], context: Cxt, option: OperateOption | SelectOption) => void;
7
+ export declare function createRelationHierarchyCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>): ExpressionRelationChecker<ED, keyof ED, Cxt>[];
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.translateCheckerInSyncContext = exports.translateCheckerInAsyncContext = void 0;
3
+ exports.createRelationHierarchyCheckers = exports.translateCheckerInSyncContext = exports.translateCheckerInAsyncContext = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  var filter_1 = require("../store/filter");
7
7
  var Exception_1 = require("../types/Exception");
8
8
  var actionDef_1 = require("./actionDef");
9
+ var string_1 = require("../utils/string");
9
10
  function translateCheckerInAsyncContext(checker) {
10
11
  var _this = this;
11
12
  var entity = checker.entity, type = checker.type;
@@ -35,12 +36,11 @@ function translateCheckerInAsyncContext(checker) {
35
36
  switch (_d.label) {
36
37
  case 0:
37
38
  operationFilter = operation.filter, action = operation.action;
38
- (0, assert_1.default)(operationFilter);
39
39
  filter2 = typeof filter_2 === 'function' ? filter_2(operation, context, option) : filter_2;
40
40
  if (!['select', 'count', 'stat'].includes(action)) return [3 /*break*/, 1];
41
- operation.filter = (0, filter_1.addFilterSegment)(operationFilter, filter2);
41
+ operation.filter = (0, filter_1.addFilterSegment)(operationFilter || {}, filter2);
42
42
  return [2 /*return*/, 0];
43
- case 1: return [4 /*yield*/, (0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter)];
43
+ case 1: return [4 /*yield*/, (0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter || {})];
44
44
  case 2:
45
45
  if (_d.sent()) {
46
46
  return [2 /*return*/, 0];
@@ -117,27 +117,35 @@ function translateCheckerInAsyncContext(checker) {
117
117
  return (function (_a, context, option) {
118
118
  var operation = _a.operation;
119
119
  return tslib_1.__awaiter(_this, void 0, void 0, function () {
120
- var _b, expressionEntity, expr, expressionFilter, _c, result;
121
- return tslib_1.__generator(this, function (_d) {
122
- switch (_d.label) {
120
+ var exprResult, expressionEntity, expr, expressionFilter, _b, result;
121
+ return tslib_1.__generator(this, function (_c) {
122
+ switch (_c.label) {
123
123
  case 0:
124
124
  if (context.isRoot() && type === 'expressionRelation') {
125
125
  return [2 /*return*/, 0];
126
126
  }
127
- _b = expression_1(operation, context, option), expressionEntity = _b.entity, expr = _b.expr, expressionFilter = _b.filter;
127
+ exprResult = expression_1(operation, context, option);
128
+ if (!(typeof exprResult === 'string')) return [3 /*break*/, 1];
129
+ throw new Exception_1.OakUserUnpermittedException(exprResult || errMsg_2);
130
+ case 1:
131
+ if (!(exprResult === undefined)) return [3 /*break*/, 2];
132
+ return [2 /*return*/, 0];
133
+ case 2:
134
+ expressionEntity = exprResult.entity, expr = exprResult.expr, expressionFilter = exprResult.filter;
128
135
  return [4 /*yield*/, context.select(expressionEntity, {
129
136
  data: {
130
137
  $expr: expr,
131
138
  },
132
139
  filter: expressionFilter,
133
140
  }, Object.assign({}, option, { dontCollect: true }))];
134
- case 1:
135
- _c = tslib_1.__read.apply(void 0, [_d.sent(), 1]), result = _c[0];
141
+ case 3:
142
+ _b = tslib_1.__read.apply(void 0, [_c.sent(), 1]), result = _b[0];
136
143
  if (!result) {
137
144
  // 条件判定为假,抛异常
138
- throw new Exception_1.OakRowInconsistencyException(undefined, errMsg_2);
145
+ throw new Exception_1.OakUserUnpermittedException(errMsg_2);
139
146
  }
140
- return [2 /*return*/, 0];
147
+ _c.label = 4;
148
+ case 4: return [2 /*return*/, 0];
141
149
  }
142
150
  });
143
151
  });
@@ -196,18 +204,27 @@ function translateCheckerInSyncContext(checker) {
196
204
  if (context.isRoot() && type === 'expressionRelation') {
197
205
  return;
198
206
  }
199
- var _a = expression_2(operation, context, option), expressionEntity = _a.entity, expr = _a.expr, expressionFilter = _a.filter;
200
- var _b = tslib_1.__read(context.select(expressionEntity, {
201
- data: {
202
- $expr: expr,
203
- },
204
- filter: expressionFilter,
205
- }, Object.assign({}, option, { dontCollect: true })), 1), result = _b[0];
206
- if (!result.$expr) {
207
- // 条件判定为假,抛异常
208
- throw new Exception_1.OakRowInconsistencyException(undefined, errMsg_5);
207
+ var exprResult = expression_2(operation, context, option);
208
+ if (typeof exprResult === 'string') {
209
+ throw new Exception_1.OakUserUnpermittedException(exprResult || errMsg_5);
210
+ }
211
+ else if (exprResult === undefined) {
212
+ return 0;
213
+ }
214
+ else {
215
+ var expressionEntity = exprResult.entity, expr = exprResult.expr, expressionFilter = exprResult.filter;
216
+ var _a = tslib_1.__read(context.select(expressionEntity, {
217
+ data: {
218
+ $expr: expr,
219
+ },
220
+ filter: expressionFilter,
221
+ }, Object.assign({}, option, { dontCollect: true })), 1), result = _a[0];
222
+ if (!result.$expr) {
223
+ // 条件判定为假,抛异常
224
+ throw new Exception_1.OakRowInconsistencyException(undefined, errMsg_5);
225
+ }
226
+ return;
209
227
  }
210
- return;
211
228
  };
212
229
  }
213
230
  default: {
@@ -216,3 +233,121 @@ function translateCheckerInSyncContext(checker) {
216
233
  }
217
234
  }
218
235
  exports.translateCheckerInSyncContext = translateCheckerInSyncContext;
236
+ function createRelationHierarchyCheckers(schema) {
237
+ var checkers = [];
238
+ var _loop_1 = function (entity) {
239
+ var e_1, _a;
240
+ var relationHierarchy = schema[entity].relationHierarchy;
241
+ if (relationHierarchy) {
242
+ // 先build反向hierarchy的map
243
+ var reverseHierarchy_1 = {};
244
+ for (var r in relationHierarchy) {
245
+ try {
246
+ for (var _b = (e_1 = void 0, tslib_1.__values(relationHierarchy[r])), _c = _b.next(); !_c.done; _c = _b.next()) {
247
+ var r2 = _c.value;
248
+ if (!reverseHierarchy_1[r2]) {
249
+ reverseHierarchy_1[r2] = [r];
250
+ }
251
+ else {
252
+ reverseHierarchy_1[r2].push(r);
253
+ }
254
+ }
255
+ }
256
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
257
+ finally {
258
+ try {
259
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
260
+ }
261
+ finally { if (e_1) throw e_1.error; }
262
+ }
263
+ }
264
+ // 对userEntity对象的授权和回收建立checker
265
+ var userEntityName_1 = "user".concat((0, string_1.firstLetterUpperCase)(entity));
266
+ var entityIdAttr_1 = "".concat(entity, "Id");
267
+ checkers.push({
268
+ entity: userEntityName_1,
269
+ action: 'create',
270
+ type: 'expressionRelation',
271
+ expression: function (operation, context) {
272
+ var _a;
273
+ var data = operation.data;
274
+ var _b = data, relation = _b.relation, _c = entityIdAttr_1, entityId = _b[_c];
275
+ var legalRelations = reverseHierarchy_1[relation];
276
+ if (!legalRelations) {
277
+ return undefined;
278
+ }
279
+ if (legalRelations.length === 0) {
280
+ return '这是不应该跑出来的情况,请杀程序员祭天';
281
+ }
282
+ var userId = context.getCurrentUserId();
283
+ return {
284
+ entity: userEntityName_1,
285
+ expr: {
286
+ $gt: [{
287
+ '#attr': '$$createAt$$',
288
+ }, 0]
289
+ },
290
+ filter: (_a = {
291
+ userId: userId
292
+ },
293
+ _a[entityIdAttr_1] = entityId,
294
+ _a.relation = {
295
+ $in: legalRelations,
296
+ },
297
+ _a)
298
+ };
299
+ },
300
+ errMsg: '越权操作',
301
+ });
302
+ var _loop_2 = function (r) {
303
+ checkers.push({
304
+ entity: userEntityName_1,
305
+ action: 'remove',
306
+ type: 'expressionRelation',
307
+ expression: function (operation, context) {
308
+ var _a, _b;
309
+ var userId = context.getCurrentUserId();
310
+ var filter = operation.filter;
311
+ var legalRelations = reverseHierarchy_1[r];
312
+ if (legalRelations.length === 0) {
313
+ return '这是不应该跑出来的情况,请杀程序员祭天';
314
+ }
315
+ return {
316
+ entity: userEntityName_1,
317
+ expr: {
318
+ $gt: [{
319
+ '#attr': '$$createAt$$',
320
+ }, 0]
321
+ },
322
+ filter: (_a = {
323
+ userId: userId
324
+ },
325
+ _a[entityIdAttr_1] = {
326
+ $in: {
327
+ entity: userEntityName_1,
328
+ data: (_b = {},
329
+ _b[entityIdAttr_1] = 1,
330
+ _b),
331
+ filter: filter,
332
+ }
333
+ },
334
+ _a.relation = {
335
+ $in: legalRelations,
336
+ },
337
+ _a),
338
+ };
339
+ },
340
+ errMsg: '越权操作',
341
+ });
342
+ };
343
+ for (var r in reverseHierarchy_1) {
344
+ _loop_2(r);
345
+ }
346
+ }
347
+ };
348
+ for (var entity in schema) {
349
+ _loop_1(entity);
350
+ }
351
+ return checkers;
352
+ }
353
+ exports.createRelationHierarchyCheckers = createRelationHierarchyCheckers;