oak-domain 2.2.0 → 2.3.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.
@@ -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,156 @@ 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
+ checkers.push({
348
+ entity: userEntityName as keyof ED,
349
+ action: 'create' as ED[keyof ED]['Action'],
350
+ type: 'data',
351
+ checker: (data, context) => {
352
+ assert(!(data instanceof Array));
353
+ const { userId } = data as ED[keyof ED]['CreateSingle']['data'];
354
+ const userId2 = context.getCurrentUserId(true);
355
+ if (userId === userId2) {
356
+ throw new OakDataException('不允许授权给自己');
357
+ }
358
+ }
359
+ });
360
+
361
+ checkers.push({
362
+ entity: userEntityName as keyof ED,
363
+ action: 'remove' as ED[keyof ED]['Action'],
364
+ type: 'row',
365
+ filter: (operation, context) => {
366
+ const userId = context.getCurrentUserId(true);
367
+ if (userId) {
368
+ return {
369
+ userId: {
370
+ $ne: userId,
371
+ },
372
+ };
373
+ }
374
+ console.warn(`没有当前用户但在删除权限,请检查。对象是${entity}`);
375
+ return {};
376
+ },
377
+ errMsg: '不允许回收自己的授权',
378
+ }); */
379
+ // 转让权限现在用update动作,只允许update userId给其它人
380
+ // todo 等实现的时候再写
381
+ }
382
+ };
383
+ for (var entity in schema) {
384
+ _loop_1(entity);
385
+ }
386
+ return checkers;
387
+ }
388
+ exports.createRelationHierarchyCheckers = createRelationHierarchyCheckers;
@@ -97,3 +97,4 @@ export declare function makeTreeAncestorFilter<ED extends EntityDict, T extends
97
97
  */
98
98
  export declare function makeTreeDescendantFilter<ED extends EntityDict, T extends keyof ED>(entity: T, parentKey: string, filter: ED[T]['Selection']['filter'], level?: number, includeAll?: boolean, includeSelf?: boolean): ED[T]['Selection']['filter'];
99
99
  export declare function checkFilterContains<ED extends EntityDict, T extends keyof ED, Cxt extends SyncContext<ED> | AsyncContext<ED>>(entity: T, context: Cxt, contained: ED[T]['Selection']['filter'], filter?: ED[T]['Selection']['filter']): boolean | Promise<boolean>;
100
+ export declare function checkFilterRepel<ED extends EntityDict, T extends keyof ED, Cxt extends SyncContext<ED> | AsyncContext<ED>>(entity: T, context: Cxt, filter1: ED[T]['Selection']['filter'], filter2: ED[T]['Selection']['filter']): boolean | Promise<boolean>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkFilterContains = exports.makeTreeDescendantFilter = exports.makeTreeAncestorFilter = exports.same = exports.getRelevantIds = exports.repel = exports.contains = exports.judgeValueRelation = exports.combineFilters = exports.unionFilterSegment = exports.addFilterSegment = void 0;
3
+ exports.checkFilterRepel = exports.checkFilterContains = exports.makeTreeDescendantFilter = exports.makeTreeAncestorFilter = exports.same = exports.getRelevantIds = exports.repel = exports.contains = exports.judgeValueRelation = exports.combineFilters = exports.unionFilterSegment = exports.addFilterSegment = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  var types_1 = require("../types");
@@ -502,7 +502,7 @@ function judgeFilter2ValueRelation(entity, schema, attr, filter, conditionalFilt
502
502
  var logicQueries = filter[attr2];
503
503
  var results = logicQueries.map(function (logicQuery) { return judgeFilter2ValueRelation(entity, schema, attr, logicQuery, conditionalFilterAttrValue, contained); });
504
504
  // 如果filter的多个算子是and关系,则只要有一个包含此条件就是包含,只要有一个与此条件相斥就是相斥
505
- // 如果filter的多个算子是or关系,则必须所有的条件都包含此条件才是包含,必须所有的条件都与此条件相斥才是相斥
505
+ // 如果filter的多个算子是or关系,则必须所有的条件都包含此条件才是包含,必须所有的条件都与此条件相斥才是相斥
506
506
  if (attr2 === '$and') {
507
507
  if (results.includes(true)) {
508
508
  return true;
@@ -520,25 +520,17 @@ function judgeFilter2ValueRelation(entity, schema, attr, filter, conditionalFilt
520
520
  }
521
521
  case '$not': {
522
522
  /*
523
- * 若filter的not条件被conditionalFilterAttrValue包容,则说明两者互斥
524
- * filter的not条件被conditionalFilterAttrValuenot条件所包容,则说明此条件包容conditionalFilterAttrValue
525
- * 但两条规则都没法应用,会无限递归
523
+ * 若filter的not条件被conditionalFilterAttrValue条件包容,则说明两者互斥
524
+ * filter包容conditionalFilterAttrValue条件暂时无法由其not条件推论出来
526
525
  */
527
526
  var logicQuery = filter[attr2];
528
- /* if (contained && judgeFilterRelation(entity, schema, {
529
- [attr2]: {
530
- $not: conditionalFilterAttrValue
531
- }
532
- }, logicQuery, contained)) {
533
- return true;
534
- } */
535
- if (!contained && judgeFilterRelation(entity, schema, (_a = {}, _a[attr2] = conditionalFilterAttrValue, _a), logicQuery, contained)) {
527
+ if (!contained && judgeFilterRelation(entity, schema, logicQuery, (_a = {}, _a[attr] = conditionalFilterAttrValue, _a), true)) {
536
528
  return true;
537
529
  }
538
530
  break;
539
531
  }
540
532
  default: {
541
- break;
533
+ (0, assert_1.default)(false);
542
534
  }
543
535
  }
544
536
  }
@@ -566,6 +558,7 @@ function judgeFilter2ValueRelation(entity, schema, attr, filter, conditionalFilt
566
558
  }
567
559
  }
568
560
  }
561
+ // 到这里说明无法判断相容或者相斥,安全起见全返回false
569
562
  return false;
570
563
  }
571
564
  /**
@@ -584,15 +577,15 @@ function judgeFilterRelation(entity, schema, filter, conditionalFilter, containe
584
577
  var logicQueries = conditionalFilter[attr];
585
578
  var results = logicQueries.map(function (logicQuery) { return judgeFilterRelation(entity, schema, filter, logicQuery, contained); });
586
579
  if (contained) {
587
- // 如果是包容关系,则无论and还是or,conditionalFilter中的任何一个查询条件都应当被filter所包容
580
+ // 如果是包容关系,or和and需要全部被包容
588
581
  if (results.includes(false)) {
589
582
  return false;
590
583
  }
591
584
  }
592
585
  else if (!contained) {
593
- // 如果是相斥关系,则无论and还是or,conditionalFilter中的任何一个查询条件都应当与filter所相斥
594
- if (!results.includes(true)) {
595
- return false;
586
+ // 如果是相斥关系,and只需要和一个相斥,or需要和全部相斥
587
+ if (attr === '$and' && results.includes(true) || attr === '$or' && !results.includes(false)) {
588
+ return true;
596
589
  }
597
590
  }
598
591
  else {
@@ -602,12 +595,19 @@ function judgeFilterRelation(entity, schema, filter, conditionalFilter, containe
602
595
  }
603
596
  case '$not': {
604
597
  /**
605
- * 若filter与not所定义的filter相斥,则filter与conditionalFilter相容
606
- * 若filternot所定义的filter相容,则filter与conditionalFilter相斥
598
+ * 若filter与conditionalFilter not所定义的部分相斥,则filter与conditionalFilter相容
599
+ * 若filter将conditionalFilter not所定义的部分包容,则filter与conditionalFilter相斥
607
600
  */
608
601
  var logicQuery = conditionalFilter[attr];
609
- if (judgeFilterRelation(entity, schema, filter, logicQuery, !contained)) {
610
- return true;
602
+ if (contained) {
603
+ if (!judgeFilterRelation(entity, schema, filter, logicQuery, false)) {
604
+ return false;
605
+ }
606
+ }
607
+ else {
608
+ if (judgeFilterRelation(entity, schema, filter, logicQuery, true)) {
609
+ return true;
610
+ }
611
611
  }
612
612
  break;
613
613
  }
@@ -655,8 +655,8 @@ function judgeFilterRelation(entity, schema, filter, conditionalFilter, containe
655
655
  * @returns
656
656
  */
657
657
  function contains(entity, schema, filter, conditionalFilter) {
658
- // return judgeFilterRelation(entity, schema, filter, conditionalFilter, true);
659
- return false;
658
+ return judgeFilterRelation(entity, schema, filter, conditionalFilter, true);
659
+ // return false;
660
660
  }
661
661
  exports.contains = contains;
662
662
  /**
@@ -675,8 +675,8 @@ exports.contains = contains;
675
675
  */
676
676
  function repel(entity, schema, filter1, filter2) {
677
677
  // todo
678
- // return judgeFilterRelation(entity, schema, filter1, filter2, false);
679
- return false;
678
+ return judgeFilterRelation(entity, schema, filter1, filter2, false);
679
+ // return false;
680
680
  }
681
681
  exports.repel = repel;
682
682
  /**
@@ -853,3 +853,26 @@ function checkFilterContains(entity, context, contained, filter) {
853
853
  return count === 0;
854
854
  }
855
855
  exports.checkFilterContains = checkFilterContains;
856
+ function checkFilterRepel(entity, context, filter1, filter2) {
857
+ if (!filter2) {
858
+ throw new types_1.OakRowInconsistencyException();
859
+ }
860
+ var schema = context.getSchema();
861
+ // 优先判断两个条件是否相容
862
+ if (repel(entity, schema, filter2, filter1)) {
863
+ return true;
864
+ }
865
+ // 再判断两者同时成立时取得的行数是否为0
866
+ var filter3 = combineFilters([filter2, filter1]);
867
+ var count = context.count(entity, {
868
+ filter: filter3,
869
+ }, {
870
+ dontCollect: true,
871
+ blockTrigger: true,
872
+ });
873
+ if (count instanceof Promise) {
874
+ return count.then(function (count2) { return count2 !== 0; });
875
+ }
876
+ return count !== 0;
877
+ }
878
+ exports.checkFilterRepel = checkFilterRepel;
package/lib/store/modi.js CHANGED
@@ -5,6 +5,7 @@ var tslib_1 = require("tslib");
5
5
  var action_1 = require("../actions/action");
6
6
  var lodash_1 = require("../utils/lodash");
7
7
  var uuid_1 = require("../utils/uuid");
8
+ var assert_1 = tslib_1.__importDefault(require("assert"));
8
9
  function createOperationsFromModies(modies) {
9
10
  return modies.map(function (modi) {
10
11
  return {
@@ -86,12 +87,45 @@ function createModiRelatedCheckers(schema) {
86
87
  action: restActions,
87
88
  type: 'row',
88
89
  filter: function (operation, context, option) {
89
- if (option.modiParentId && option.modiParentEntity) {
90
- // 如果本身也是创建modi就允许通过
90
+ /**
91
+ * 只有一种情况可以通过,即当前是在更新和active的modi所指向同一个父更新对象。
92
+ * 比如:先申请了一个公司(company),再申请修改公司(companyApplyment),这时所有的active modi都指向此条companyApplyment
93
+ * 这时:
94
+ * 1)再申请一条新的修改公司(create companyApplyment),应被拒绝
95
+ * 2)申请修改原来的companyApplyment(update companyApplyment),可以通过
96
+ * 3)在其它路径上对此company对象进行直接的更新,应被拒绝
97
+ */
98
+ if (option.modiParentEntity) {
99
+ var _a = option, modiParentEntity = _a.modiParentEntity, modiParentId = _a.modiParentId;
100
+ (0, assert_1.default)(modiParentEntity);
101
+ (0, assert_1.default)(modiParentId);
91
102
  return {
92
103
  id: {
93
- $exists: true,
94
- },
104
+ $nin: {
105
+ entity: 'modiEntity',
106
+ data: {
107
+ entityId: 1,
108
+ },
109
+ filter: {
110
+ entity: entity,
111
+ modi: {
112
+ iState: 'active',
113
+ $or: [
114
+ {
115
+ entity: {
116
+ $ne: modiParentEntity,
117
+ },
118
+ },
119
+ {
120
+ entityId: {
121
+ $ne: modiParentId,
122
+ },
123
+ }
124
+ ],
125
+ },
126
+ },
127
+ },
128
+ }
95
129
  };
96
130
  }
97
131
  return {
@@ -111,7 +145,7 @@ function createModiRelatedCheckers(schema) {
111
145
  }
112
146
  };
113
147
  },
114
- errMsg: "\u66F4\u65B0\u7684\u5BF9\u8C61".concat(entity, "\u4E0A\u6709\u5C1A\u672A\u7ED3\u675F\u7684modi"),
148
+ errMsg: '您请求的更新对象上还有正在申请的更新,请等该更新结束后再试',
115
149
  });
116
150
  };
117
151
  for (var entity in schema) {
@@ -24,9 +24,11 @@ function judgeRelation(schema, entity, attr) {
24
24
  return 1;
25
25
  }
26
26
  if (attr.includes('$')) {
27
- var entity2 = attr.slice(0, attr.indexOf('$'));
27
+ var firstDelimiter = attr.indexOf('$');
28
+ var entity2 = attr.slice(0, firstDelimiter);
28
29
  (0, assert_1.default)(schema.hasOwnProperty(entity2));
29
- var foreignKey = attr.slice(attr.indexOf('$') + 1);
30
+ var secondDelemiter = attr.indexOf('$', firstDelimiter + 1);
31
+ var foreignKey = attr.slice(firstDelimiter + 1, secondDelemiter > 0 ? secondDelemiter : attr.length);
30
32
  var _c = schema, _d = entity2, attributes2 = _c[_d].attributes;
31
33
  if (foreignKey === 'entity') {
32
34
  // 基于反指对象的反向关联
@@ -181,7 +181,7 @@ function reinforceSelection(schema, entity, selection) {
181
181
  necessaryAttrs.push("".concat(attr, "Id"));
182
182
  checkProjectionNode(rel, projectionNode[attr]);
183
183
  }
184
- else if (rel instanceof Array) {
184
+ else if (rel instanceof Array && !attr.endsWith('$$aggr')) {
185
185
  var data_1 = projectionNode[attr].data;
186
186
  if (rel[1]) {
187
187
  checkNode(data_1, [rel[1]]);
@@ -189,7 +189,7 @@ function reinforceSelection(schema, entity, selection) {
189
189
  else {
190
190
  checkNode(data_1, ['entity', 'entityId']);
191
191
  }
192
- checkProjectionNode(rel[0], data_1);
192
+ reinforceSelection(schema, rel[0], projectionNode[attr]);
193
193
  }
194
194
  }
195
195
  }
@@ -3,12 +3,17 @@ import { SyncContext } from "../store/SyncRowStore";
3
3
  import { EntityDict, OperateOption, SelectOption } from "../types/Entity";
4
4
  import { RefOrExpression } from "./Expression";
5
5
  export declare type CheckerType = 'relation' | 'row' | 'data' | 'expression' | 'expressionRelation';
6
+ /**
7
+ * conditionalFilter是指该action发生时,operation所操作的行中有满足conditionalFilter的行
8
+ * 被转化成trigger的filter条件,详细可看trigger中的说明
9
+ */
6
10
  export declare type DataChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
7
11
  priority?: number;
8
12
  type: 'data';
9
13
  entity: T;
10
14
  action: Omit<ED[T]['Action'], 'remove'> | Array<Omit<ED[T]['Action'], 'remove'>>;
11
15
  checker: (data: ED[T]['Create']['data'] | ED[T]['Update']['data'], context: Cxt) => void;
16
+ conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
12
17
  };
13
18
  export declare type RowChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
14
19
  priority?: number;
@@ -21,6 +26,7 @@ export declare type RowChecker<ED extends EntityDict, T extends keyof ED, Cxt ex
21
26
  entity: keyof ED;
22
27
  selection: (filter?: ED[T]['Selection']['filter']) => ED[keyof ED]['Selection'];
23
28
  };
29
+ conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
24
30
  };
25
31
  export declare type RelationChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
26
32
  priority?: number;
@@ -29,6 +35,7 @@ export declare type RelationChecker<ED extends EntityDict, T extends keyof ED, C
29
35
  action: Omit<ED[T]['Action'], 'create'> | Array<Omit<ED[T]['Action'], 'create'>>;
30
36
  relationFilter: (operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => ED[T]['Selection']['filter'];
31
37
  errMsg: string;
38
+ conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
32
39
  };
33
40
  export declare type ExpressionChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
34
41
  priority?: number;
@@ -39,8 +46,9 @@ export declare type ExpressionChecker<ED extends EntityDict, T extends keyof ED,
39
46
  entity: T2;
40
47
  expr: RefOrExpression<keyof ED[T2]['OpSchema']>;
41
48
  filter: ED[T2]['Selection']['filter'];
42
- };
49
+ } | undefined | string;
43
50
  errMsg: string;
51
+ conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
44
52
  };
45
53
  export declare type ExpressionRelationChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
46
54
  priority?: number;
@@ -51,7 +59,8 @@ export declare type ExpressionRelationChecker<ED extends EntityDict, T extends k
51
59
  entity: T2;
52
60
  expr: RefOrExpression<keyof ED[T2]['OpSchema']>;
53
61
  filter: ED[T2]['Selection']['filter'];
54
- };
62
+ } | undefined | string;
55
63
  errMsg: string;
64
+ conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
56
65
  };
57
66
  export declare type Checker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = DataChecker<ED, T, Cxt> | RowChecker<ED, T, Cxt> | RelationChecker<ED, T, Cxt> | ExpressionChecker<ED, T, Cxt> | ExpressionRelationChecker<ED, T, Cxt>;
@@ -73,6 +73,7 @@ export interface EntityDef {
73
73
  Action: string;
74
74
  ParticularAction?: string;
75
75
  Selection: Omit<DeduceSelection<this['Schema']>, 'action'>;
76
+ Aggregation: Omit<DeduceAggregation<this['Schema'], DeduceProjection<this['Schema']>, DeduceFilter<this['Schema']>, DeduceSorter<this['Schema']>>, 'action'>;
76
77
  Operation: DeduceOperation<this['Schema']>;
77
78
  Create: DeduceCreateOperation<this['Schema']>;
78
79
  CreateSingle: DeduceCreateSingleOperation<this['Schema']>;
@@ -90,7 +91,18 @@ declare type DeduceProjection<SH extends GeneralEntityShape> = {
90
91
  '#id'?: NodeId;
91
92
  } & {
92
93
  [K in keyof SH]?: number | OtmSubProjection | any;
93
- } & Partial<ExprOp<keyof SH>>;
94
+ } & Partial<ExprOp<keyof SH | string>>;
95
+ export declare type AggregationOp = `#max-${number}` | `#min-${number}` | `#avg-${number}` | `#count-${number}` | `#sum-${number}`;
96
+ export declare type DeduceAggregationData<SH extends GeneralEntityShape, P extends DeduceProjection<SH>> = {
97
+ [A in AggregationOp]?: P;
98
+ } & {
99
+ '#aggr'?: P;
100
+ };
101
+ export declare type AggregationResult<SH extends GeneralEntityShape> = Array<{
102
+ [A in AggregationOp]?: number | string;
103
+ } & {
104
+ '#data'?: Partial<SH>;
105
+ }>;
94
106
  export declare type AttrFilter<SH extends GeneralEntityShape> = {
95
107
  [K in keyof SH]: any;
96
108
  };
@@ -104,6 +116,7 @@ export declare type DeduceSorterItem<SH extends GeneralEntityShape> = {
104
116
  };
105
117
  export declare type DeduceSorter<SH extends GeneralEntityShape> = Array<DeduceSorterItem<SH>>;
106
118
  export declare type DeduceSelection<SH extends GeneralEntityShape> = Selection<DeduceProjection<SH>, DeduceFilter<SH>, DeduceSorter<SH>>;
119
+ export declare type DeduceAggregation<SH extends GeneralEntityShape, P extends DeduceProjection<SH>, F extends DeduceFilter<SH>, S extends DeduceSorter<SH>> = Omit<Operation<'aggregate', DeduceAggregationData<SH, P>, F, S>, 'action'>;
107
120
  export declare type DeduceCreateOperationData<SH extends GeneralEntityShape> = {
108
121
  id: string;
109
122
  } & {
@@ -137,6 +150,9 @@ export declare type RemoveOpResult<ED extends EntityDict, T extends keyof ED> =
137
150
  e: T;
138
151
  f?: DeduceFilter<ED[T]['Schema']>;
139
152
  };
153
+ export declare type RelationHierarchy<R extends string> = {
154
+ [K in R]?: R[];
155
+ };
140
156
  export declare type SelectOpResult<ED extends EntityDict> = {
141
157
  a: 's';
142
158
  d: {
@@ -156,4 +172,19 @@ export declare type Configuration = {
156
172
  actionType?: ActionType;
157
173
  static?: boolean;
158
174
  };
175
+ export declare type Exportation<ED extends EntityDict, T extends keyof ED, K extends string> = {
176
+ name: string;
177
+ id: string;
178
+ entity: T;
179
+ projection: ED[T]['Selection']['data'];
180
+ headers: K[];
181
+ fn: (data: ED[T]['Schema']) => Partial<Record<K, string | number | boolean | null>>;
182
+ };
183
+ export declare type Importation<ED extends EntityDict, T extends keyof ED, K extends string> = {
184
+ name: string;
185
+ id: string;
186
+ entity: T;
187
+ headers: K[];
188
+ fn: (data: Partial<Record<K, string | number | boolean>>) => ED[T]['CreateSingle']['data'];
189
+ };
159
190
  export {};