oak-domain 2.4.3 → 2.4.4

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.
@@ -12,7 +12,8 @@ exports.desc = {
12
12
  type: "varchar",
13
13
  params: {
14
14
  length: 32
15
- }
15
+ },
16
+ ref: ["user"]
16
17
  },
17
18
  entityId: {
18
19
  type: "varchar",
@@ -12,7 +12,8 @@ exports.desc = {
12
12
  type: "varchar",
13
13
  params: {
14
14
  length: 32
15
- }
15
+ },
16
+ ref: ["modi", "user"]
16
17
  },
17
18
  entityId: {
18
19
  type: "varchar",
@@ -7,6 +7,7 @@ var modi_1 = require("../store/modi");
7
7
  function createDynamicCheckers(schema, authDict) {
8
8
  var checkers = [];
9
9
  checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, modi_1.createModiRelatedCheckers)(schema)), false));
10
+ // checkers.push(...createRemoveCheckers<ED, Cxt>(schema));
10
11
  if (authDict) {
11
12
  checkers.push.apply(checkers, tslib_1.__spreadArray([], tslib_1.__read((0, checker_1.createAuthCheckers)(schema, authDict)), false));
12
13
  }
@@ -2871,6 +2871,14 @@ function constructAttributes(entity) {
2871
2871
  attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("varchar")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
2872
2872
  factory.createPropertyAssignment(factory.createIdentifier("length"), factory.createNumericLiteral(typeArguments[0].literal.text)),
2873
2873
  ], true)));
2874
+ // 如果是entity,在这里处理一下ref
2875
+ if (ts.isIdentifier(name) && name.text === 'entity') {
2876
+ var mtoRelations = ReversePointerRelations[entity];
2877
+ if (mtoRelations) {
2878
+ var mtoEntities = mtoRelations.map(function (ele) { return (0, string_1.firstLetterLowerCase)(ele); });
2879
+ attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("ref"), factory.createArrayLiteralExpression(mtoEntities.map(function (ele) { return factory.createStringLiteral(ele); }), false)));
2880
+ }
2881
+ }
2874
2882
  break;
2875
2883
  }
2876
2884
  case 'Text':
@@ -6,6 +6,7 @@ var assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  var lodash_1 = require("../utils/lodash");
7
7
  var filter_1 = require("../store/filter");
8
8
  var Entity_1 = require("../types/Entity");
9
+ var Trigger_1 = require("../types/Trigger");
9
10
  var SyncRowStore_1 = require("./SyncRowStore");
10
11
  var checker_1 = require("./checker");
11
12
  /**
@@ -33,10 +34,11 @@ var TriggerExecutor = /** @class */ (function () {
33
34
  var entity = checker.entity, action = checker.action, type = checker.type, conditionalFilter = checker.conditionalFilter;
34
35
  var triggerName = "".concat(String(entity)).concat(action, "\u6743\u9650\u68C0\u67E5-").concat(this.counter++);
35
36
  var _a = (0, checker_1.translateCheckerInAsyncContext)(checker), fn = _a.fn, when = _a.when;
37
+ var priority = type === 'data' ? Trigger_1.DATA_CHECKER_DEFAULT_PRIORITY : Trigger_1.CHECKER_DEFAULT_PRIORITY; // checker的默认优先级最低(前面的trigger可能会赋上一些相应的值)
36
38
  var trigger = {
37
39
  checkerType: type,
38
40
  name: triggerName,
39
- priority: checker.priority || 20,
41
+ priority: checker.priority || priority,
40
42
  entity: entity,
41
43
  action: action,
42
44
  fn: fn,
@@ -59,7 +61,10 @@ var TriggerExecutor = /** @class */ (function () {
59
61
  throw new Error("\u4E0D\u53EF\u6709\u540C\u540D\u7684\u89E6\u53D1\u5668\u300C".concat(trigger.name, "\u300D"));
60
62
  }
61
63
  if (typeof trigger.priority !== 'number') {
62
- trigger.priority = 10; // 默认值
64
+ trigger.priority = Trigger_1.TRIGGER_DEFAULT_PRIORITY; // 默认值
65
+ }
66
+ else {
67
+ (0, assert_1.default)(trigger.priority <= Trigger_1.TRIGGER_MAX_PRIORITY && trigger.priority >= Trigger_1.TRIGGER_MIN_PRIORITY, "trigger\u300C".concat(trigger.name, "\u300D\u7684\u4F18\u5148\u7EA7\u5B9A\u4E49\u8D8A\u754C\uFF0C\u5E94\u8BE5\u5728").concat(Trigger_1.TRIGGER_MIN_PRIORITY, "\u5230").concat(Trigger_1.TRIGGER_MAX_PRIORITY, "\u4E4B\u95F4"));
63
68
  }
64
69
  if (trigger.filter) {
65
70
  (0, assert_1.default)(typeof trigger.action === 'string' && trigger.action !== 'create'
@@ -10,4 +10,17 @@ export declare function translateCheckerInSyncContext<ED extends EntityDict & Ba
10
10
  fn: (operation: ED[T]['Operation'], context: Cxt, option: OperateOption | SelectOption) => void;
11
11
  when: 'before' | 'after';
12
12
  };
13
+ /**
14
+ * 根据权限定义,创建出相应的checker
15
+ * @param schema
16
+ * @param authDict
17
+ * @returns
18
+ */
13
19
  export declare function createAuthCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>, authDict: AuthDefDict<ED>): Checker<ED, keyof ED, Cxt>[];
20
+ /**
21
+ * 对对象的删除,检查其是否会产生其他行上的空指针,不允许这种情况的出现
22
+ * @param schema
23
+ * @returns
24
+ * 如果有的对象允许删除,需要使用trigger来处理其相关联的外键对象,这些trigger写作before,则会在checker之前执行,仍然可以删除成功
25
+ */
26
+ export declare function createRemoveCheckers<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED> | SyncContext<ED>>(schema: StorageSchema<ED>): Checker<ED, keyof ED, Cxt>[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createAuthCheckers = exports.translateCheckerInSyncContext = exports.translateCheckerInAsyncContext = void 0;
3
+ exports.createRemoveCheckers = exports.createAuthCheckers = 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");
@@ -392,6 +392,12 @@ function translateActionAuthFilterMaker(schema, relationItem, entity) {
392
392
  var filterMaker = translateCascadeRelationFilterMaker(schema, relationItem, entity);
393
393
  return function (userId) { return filterMaker(userId); };
394
394
  }
395
+ /**
396
+ * 根据权限定义,创建出相应的checker
397
+ * @param schema
398
+ * @param authDict
399
+ * @returns
400
+ */
395
401
  function createAuthCheckers(schema, authDict) {
396
402
  var checkers = [];
397
403
  var _loop_1 = function (entity) {
@@ -496,3 +502,224 @@ function createAuthCheckers(schema, authDict) {
496
502
  return checkers;
497
503
  }
498
504
  exports.createAuthCheckers = createAuthCheckers;
505
+ /**
506
+ * 对对象的删除,检查其是否会产生其他行上的空指针,不允许这种情况的出现
507
+ * @param schema
508
+ * @returns
509
+ * 如果有的对象允许删除,需要使用trigger来处理其相关联的外键对象,这些trigger写作before,则会在checker之前执行,仍然可以删除成功
510
+ */
511
+ function createRemoveCheckers(schema) {
512
+ var e_1, _a;
513
+ var checkers = [];
514
+ // 先建立所有的一对多的关系
515
+ var OneToManyMatrix = {};
516
+ var OneToManyOnEntityMatrix = {};
517
+ var addToMto = function (e, f, attr) {
518
+ var _a;
519
+ if (OneToManyMatrix[f]) {
520
+ (_a = OneToManyMatrix[f]) === null || _a === void 0 ? void 0 : _a.push([e, attr]);
521
+ }
522
+ else {
523
+ OneToManyMatrix[f] = [[e, attr]];
524
+ }
525
+ };
526
+ var addToMtoEntity = function (e, fs) {
527
+ var e_2, _a;
528
+ var _b;
529
+ try {
530
+ for (var fs_1 = tslib_1.__values(fs), fs_1_1 = fs_1.next(); !fs_1_1.done; fs_1_1 = fs_1.next()) {
531
+ var f = fs_1_1.value;
532
+ if (!OneToManyOnEntityMatrix[f]) {
533
+ OneToManyOnEntityMatrix[f] = [e];
534
+ }
535
+ else {
536
+ (_b = OneToManyOnEntityMatrix[f]) === null || _b === void 0 ? void 0 : _b.push(e);
537
+ }
538
+ }
539
+ }
540
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
541
+ finally {
542
+ try {
543
+ if (fs_1_1 && !fs_1_1.done && (_a = fs_1.return)) _a.call(fs_1);
544
+ }
545
+ finally { if (e_2) throw e_2.error; }
546
+ }
547
+ };
548
+ for (var entity in schema) {
549
+ if (['operEntity'].includes(entity)) {
550
+ continue; // OperEntity会指向每一个对象,不必处理
551
+ }
552
+ var attributes = schema[entity].attributes;
553
+ for (var attr in attributes) {
554
+ if (attributes[attr].type === 'ref') {
555
+ addToMto(entity, attributes[attr].ref, attr);
556
+ }
557
+ else if (attr === 'entity') {
558
+ if (attributes[attr].ref) {
559
+ addToMtoEntity(entity, attributes[attr].ref);
560
+ }
561
+ else if (process.env.NODE_ENV === 'development') {
562
+ console.warn("".concat(entity, "\u7684entity\u53CD\u6307\u6307\u9488\u627E\u4E0D\u5230\u6709\u6548\u7684\u5BF9\u8C61"));
563
+ }
564
+ }
565
+ }
566
+ }
567
+ // 当删除一时,要确认多上面没有指向一的数据
568
+ var entities = (0, lodash_1.intersection)(Object.keys(OneToManyMatrix), Object.keys(OneToManyOnEntityMatrix));
569
+ var _loop_3 = function (entity) {
570
+ checkers.push({
571
+ entity: entity,
572
+ action: 'remove',
573
+ type: 'logical',
574
+ checker: function (operation, context, option) {
575
+ var e_3, _a, e_4, _b;
576
+ var promises = [];
577
+ if (OneToManyMatrix[entity]) {
578
+ var _loop_4 = function (otm) {
579
+ var _g, _h, _j, _k;
580
+ var _l = tslib_1.__read(otm, 2), e = _l[0], attr = _l[1];
581
+ var proj = (_g = {
582
+ id: 1
583
+ },
584
+ _g[attr] = 1,
585
+ _g);
586
+ var filter = operation.filter && (_h = {},
587
+ _h[attr.slice(0, attr.length - 2)] = operation.filter,
588
+ _h);
589
+ var result = context.select(e, {
590
+ data: proj,
591
+ filter: filter,
592
+ indexFrom: 0,
593
+ count: 1
594
+ }, { dontCollect: true });
595
+ if (result instanceof Promise) {
596
+ promises.push(result.then(function (_a) {
597
+ var _b, _c;
598
+ var _d = tslib_1.__read(_a, 1), row = _d[0];
599
+ if (row) {
600
+ var record = {
601
+ a: 's',
602
+ d: (_b = {},
603
+ _b[e] = (_c = {},
604
+ _c[row.id] = row,
605
+ _c),
606
+ _b)
607
+ };
608
+ throw new Exception_1.OakRowInconsistencyException(record, "\u60A8\u65E0\u6CD5\u5220\u9664\u5B58\u5728\u6709\u6548\u6570\u636E\u300C".concat(e, "\u300D\u5173\u8054\u7684\u884C"));
609
+ }
610
+ }));
611
+ }
612
+ else {
613
+ var _m = tslib_1.__read(result, 1), row = _m[0];
614
+ if (row) {
615
+ var record = {
616
+ a: 's',
617
+ d: (_j = {},
618
+ _j[e] = (_k = {},
619
+ _k[row.id] = row,
620
+ _k),
621
+ _j)
622
+ };
623
+ throw new Exception_1.OakRowInconsistencyException(record, "\u60A8\u65E0\u6CD5\u5220\u9664\u5B58\u5728\u6709\u6548\u6570\u636E\u300C".concat(e, "\u300D\u5173\u8054\u7684\u884C"));
624
+ }
625
+ }
626
+ };
627
+ try {
628
+ for (var _c = (e_3 = void 0, tslib_1.__values(OneToManyMatrix[entity])), _d = _c.next(); !_d.done; _d = _c.next()) {
629
+ var otm = _d.value;
630
+ _loop_4(otm);
631
+ }
632
+ }
633
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
634
+ finally {
635
+ try {
636
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
637
+ }
638
+ finally { if (e_3) throw e_3.error; }
639
+ }
640
+ }
641
+ if (OneToManyOnEntityMatrix[entity]) {
642
+ var _loop_5 = function (otm) {
643
+ var _o, _p, _q;
644
+ var proj = {
645
+ id: 1,
646
+ entity: 1,
647
+ entityId: 1,
648
+ };
649
+ var filter = operation.filter && (_o = {},
650
+ _o[entity] = operation.filter,
651
+ _o);
652
+ var result = context.select(otm, {
653
+ data: proj,
654
+ filter: filter,
655
+ indexFrom: 0,
656
+ count: 1
657
+ }, { dontCollect: true });
658
+ if (result instanceof Promise) {
659
+ promises.push(result.then(function (_a) {
660
+ var _b, _c;
661
+ var _d = tslib_1.__read(_a, 1), row = _d[0];
662
+ if (row) {
663
+ var record = {
664
+ a: 's',
665
+ d: (_b = {},
666
+ _b[otm] = (_c = {},
667
+ _c[row.id] = row,
668
+ _c),
669
+ _b)
670
+ };
671
+ throw new Exception_1.OakRowInconsistencyException(record, "\u60A8\u65E0\u6CD5\u5220\u9664\u5B58\u5728\u6709\u6548\u6570\u636E\u300C".concat(otm, "\u300D\u5173\u8054\u7684\u884C"));
672
+ }
673
+ }));
674
+ }
675
+ else {
676
+ var _r = tslib_1.__read(result, 1), row = _r[0];
677
+ if (row) {
678
+ var record = {
679
+ a: 's',
680
+ d: (_p = {},
681
+ _p[otm] = (_q = {},
682
+ _q[row.id] = row,
683
+ _q),
684
+ _p)
685
+ };
686
+ throw new Exception_1.OakRowInconsistencyException(record, "\u60A8\u65E0\u6CD5\u5220\u9664\u5B58\u5728\u6709\u6548\u6570\u636E\u300C".concat(otm, "\u300D\u5173\u8054\u7684\u884C"));
687
+ }
688
+ }
689
+ };
690
+ try {
691
+ for (var _e = (e_4 = void 0, tslib_1.__values(OneToManyOnEntityMatrix[entity])), _f = _e.next(); !_f.done; _f = _e.next()) {
692
+ var otm = _f.value;
693
+ _loop_5(otm);
694
+ }
695
+ }
696
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
697
+ finally {
698
+ try {
699
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
700
+ }
701
+ finally { if (e_4) throw e_4.error; }
702
+ }
703
+ }
704
+ if (promises.length > 0) {
705
+ return Promise.all(promises).then(function () { return undefined; });
706
+ }
707
+ }
708
+ });
709
+ };
710
+ try {
711
+ for (var entities_1 = tslib_1.__values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) {
712
+ var entity = entities_1_1.value;
713
+ _loop_3(entity);
714
+ }
715
+ }
716
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
717
+ finally {
718
+ try {
719
+ if (entities_1_1 && !entities_1_1.done && (_a = entities_1.return)) _a.call(entities_1);
720
+ }
721
+ finally { if (e_1) throw e_1.error; }
722
+ }
723
+ return checkers;
724
+ }
725
+ exports.createRemoveCheckers = createRemoveCheckers;
@@ -12,7 +12,7 @@ export declare type DataChecker<ED extends EntityDict, T extends keyof ED, Cxt e
12
12
  type: 'data';
13
13
  entity: T;
14
14
  action: Omit<ED[T]['Action'], 'remove'> | Array<Omit<ED[T]['Action'], 'remove'>>;
15
- checker: (data: ED[T]['Create']['data'] | ED[T]['Update']['data'], context: Cxt) => void | Promise<void>;
15
+ checker: (data: ED[T]['Create']['data'] | ED[T]['Update']['data'], context: Cxt) => any | Promise<any>;
16
16
  conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter'] | Promise<ED[T]['Selection']['filter']>);
17
17
  };
18
18
  export declare type RowChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
@@ -44,7 +44,7 @@ export declare type LogicalChecker<ED extends EntityDict, T extends keyof ED, Cx
44
44
  when?: 'after';
45
45
  entity: T;
46
46
  action: ED[T]['Action'] | Array<ED[T]['Action']>;
47
- checker: (operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => void | Promise<void>;
47
+ checker: (operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => any | Promise<any>;
48
48
  conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
49
49
  };
50
50
  export declare type LogicalRelationChecker<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> = {
@@ -53,7 +53,7 @@ export declare type LogicalRelationChecker<ED extends EntityDict, T extends keyo
53
53
  when?: 'after';
54
54
  entity: T;
55
55
  action: ED[T]['Action'] | Array<ED[T]['Action']>;
56
- checker: (operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => void | Promise<void>;
56
+ checker: (operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => any | Promise<any>;
57
57
  conditionalFilter?: ED[T]['Update']['filter'] | ((operation: ED[T]['Operation'], context: Cxt, option: OperateOption) => ED[T]['Update']['filter']);
58
58
  };
59
59
  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> | LogicalChecker<ED, T, Cxt> | LogicalRelationChecker<ED, T, Cxt>;
@@ -20,7 +20,7 @@ export interface Index<SH extends EntityShape> {
20
20
  export interface Attribute {
21
21
  type: DataType | Ref;
22
22
  params?: DataTypeParams;
23
- ref?: string;
23
+ ref?: string | string[];
24
24
  onRefDelete?: 'delete' | 'setNull' | 'ignore';
25
25
  default?: string | number | boolean;
26
26
  notNull?: boolean;
@@ -4,6 +4,14 @@ import { AsyncContext } from "../store/AsyncRowStore";
4
4
  import { SyncContext } from "../store/SyncRowStore";
5
5
  import { EntityDict, OperateOption } from "../types/Entity";
6
6
  import { EntityShape } from "../types/Entity";
7
+ /**
8
+ * 优先级越小,越早执行。定义在1~99之间
9
+ */
10
+ export declare const TRIGGER_DEFAULT_PRIORITY = 50;
11
+ export declare const TRIGGER_MIN_PRIORITY = 1;
12
+ export declare const TRIGGER_MAX_PRIORITY = 99;
13
+ export declare const DATA_CHECKER_DEFAULT_PRIORITY = 60;
14
+ export declare const CHECKER_DEFAULT_PRIORITY = 99;
7
15
  interface TriggerBase<ED extends EntityDict, T extends keyof ED> {
8
16
  checkerType?: CheckerType;
9
17
  entity: T;
@@ -1,5 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CHECKER_DEFAULT_PRIORITY = exports.DATA_CHECKER_DEFAULT_PRIORITY = exports.TRIGGER_MAX_PRIORITY = exports.TRIGGER_MIN_PRIORITY = exports.TRIGGER_DEFAULT_PRIORITY = void 0;
4
+ /**
5
+ * 优先级越小,越早执行。定义在1~99之间
6
+ */
7
+ exports.TRIGGER_DEFAULT_PRIORITY = 50;
8
+ exports.TRIGGER_MIN_PRIORITY = 1;
9
+ exports.TRIGGER_MAX_PRIORITY = 99;
10
+ exports.DATA_CHECKER_DEFAULT_PRIORITY = 60;
11
+ exports.CHECKER_DEFAULT_PRIORITY = 99;
3
12
  ;
4
13
  ;
5
14
  ;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oak-domain",
3
- "version": "2.4.3",
3
+ "version": "2.4.4",
4
4
  "author": {
5
5
  "name": "XuChang"
6
6
  },