oak-domain 1.1.7 → 1.1.9

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.
@@ -40,7 +40,7 @@ exports.desc = {
40
40
  iState: {
41
41
  type: "varchar",
42
42
  params: {
43
- length: 16
43
+ length: 24
44
44
  }
45
45
  }
46
46
  },
@@ -5,7 +5,7 @@ export declare const ENTITY_PATH_IN_OAK_DOMAIN: () => string;
5
5
  export declare const TYPE_PATH_IN_OAK_DOMAIN: (level?: number) => string;
6
6
  export declare const ACTION_CONSTANT_IN_OAK_DOMAIN: (level?: number) => string;
7
7
  export declare const RESERVED_ENTITIES: string[];
8
- export declare const STRING_LITERAL_MAX_LENGTH = 16;
8
+ export declare const STRING_LITERAL_MAX_LENGTH = 24;
9
9
  export declare const NUMERICAL_LITERL_DEFAULT_PRECISION = 8;
10
10
  export declare const NUMERICAL_LITERL_DEFAULT_SCALE = 2;
11
11
  export declare const INT_LITERL_DEFAULT_WIDTH = 4;
@@ -33,7 +33,7 @@ exports.ACTION_CONSTANT_IN_OAK_DOMAIN = ACTION_CONSTANT_IN_OAK_DOMAIN;
33
33
  // export const OUTPUT_PATH = 'app-domain/entities';
34
34
  exports.RESERVED_ENTITIES = ['Schema', 'Filter', 'Query', 'SubQuery', 'Entity', 'Selection', 'Operation', 'File', 'Common',
35
35
  'Locale', 'Projection', 'Data'];
36
- exports.STRING_LITERAL_MAX_LENGTH = 16;
36
+ exports.STRING_LITERAL_MAX_LENGTH = 24;
37
37
  exports.NUMERICAL_LITERL_DEFAULT_PRECISION = 8;
38
38
  exports.NUMERICAL_LITERL_DEFAULT_SCALE = 2;
39
39
  exports.INT_LITERL_DEFAULT_WIDTH = 4;
@@ -1,2 +1,2 @@
1
- export declare function analyzeEntities(inputDir: string): void;
1
+ export declare function analyzeEntities(inputDir: string, relativePath?: string): void;
2
2
  export declare function buildSchema(outputDir: string): void;
@@ -150,7 +150,7 @@ function addActionSource(moduleName, name, node) {
150
150
  var _a;
151
151
  var ast = ActionAsts[moduleName];
152
152
  var moduleSpecifier = node.moduleSpecifier;
153
- // 目前应该只会引用oak-domain/src/actions/action里的公共action
153
+ // todo 目前应该只会引用oak-domain/src/actions/action里的公共action,未来如果有交叉引用这里代码要修正(如果domain中也有引用action_constants这里应该也会错)
154
154
  (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text === (0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)());
155
155
  (0, lodash_1.assign)(ast.importedFrom, (_a = {},
156
156
  _a[name.text] = node,
@@ -262,27 +262,26 @@ function dealWithActions(moduleName, filename, node, program, sourceFile, hasRel
262
262
  });
263
263
  pushStatementIntoActionAst(moduleName, factory.createVariableStatement([factory.createModifier(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("actions"), undefined, undefined, factory.createArrayLiteralExpression(actionTexts.map(function (ele) { return factory.createStringLiteral(ele); }), false))], ts.NodeFlags.Const)), sourceFile);
264
264
  }
265
- function getEntityImported(declaration, filename) {
265
+ /**
266
+ * entity的引用一定要以 import { Schema as XXX } from '..../XXX'这种形式
267
+ * @param declaration
268
+ * @param filename
269
+ * @returns
270
+ */
271
+ function getEntityImported(declaration) {
266
272
  var moduleSpecifier = declaration.moduleSpecifier, importClause = declaration.importClause;
267
273
  var entityImported;
268
274
  if (ts.isStringLiteral(moduleSpecifier)) {
269
- if (moduleSpecifier.text.startsWith('./')) {
270
- entityImported = moduleSpecifier.text.slice(2);
271
- }
272
- else if (moduleSpecifier.text.startsWith((0, env_1.ENTITY_PATH_IN_OAK_GENERAL_BUSINESS)())) {
273
- entityImported = moduleSpecifier.text.slice((0, env_1.ENTITY_PATH_IN_OAK_GENERAL_BUSINESS)().length);
274
- }
275
- else if (moduleSpecifier.text.startsWith((0, env_1.ENTITY_PATH_IN_OAK_DOMAIN)())) {
276
- entityImported = moduleSpecifier.text.slice((0, env_1.ENTITY_PATH_IN_OAK_DOMAIN)().length);
277
- }
278
- }
279
- if (entityImported) {
275
+ var importedFileName_1 = path_1.default.parse(moduleSpecifier.text).name;
280
276
  var namedBindings = importClause.namedBindings;
281
- (0, assert_1.default)(ts.isNamedImports(namedBindings));
282
- var elements = namedBindings.elements;
283
- (0, assert_1.default)(elements.find(function (ele) { return ts.isImportSpecifier(ele) && ele.name.text === entityImported && ele.propertyName.text === 'Schema'; }), "\u300C".concat(filename, "\u300D\u5BFC\u5165\u7684\u5BF9\u8C61\u540D\u79F0\u548C\u5BF9\u8C61\u6240\u5728\u7684\u6587\u4EF6\u540D\u79F0\u300C").concat(entityImported, "\u300D\u4E0D\u7B26"));
284
- return entityImported;
277
+ if (namedBindings && ts.isNamedImports(namedBindings)) {
278
+ var elements = namedBindings.elements;
279
+ if (elements.find(function (ele) { var _a; return ts.isImportSpecifier(ele) && ele.name.text === importedFileName_1 && ((_a = ele.propertyName) === null || _a === void 0 ? void 0 : _a.text) === 'Schema'; })) {
280
+ entityImported = importedFileName_1;
281
+ }
282
+ }
285
283
  }
284
+ return entityImported;
286
285
  }
287
286
  function checkLocaleEnumAttrs(node, attrs, filename) {
288
287
  var members = node.members;
@@ -312,7 +311,7 @@ function checkLocaleExpressionPropertyExists(root, attr, exists, filename) {
312
311
  }
313
312
  });
314
313
  }
315
- function analyzeEntity(filename, path, program) {
314
+ function analyzeEntity(filename, path, program, relativePath) {
316
315
  var _a;
317
316
  var fullPath = "".concat(path, "/").concat(filename);
318
317
  var sourceFile = program.getSourceFile(fullPath);
@@ -336,14 +335,30 @@ function analyzeEntity(filename, path, program) {
336
335
  var enumStringAttrs = [];
337
336
  var states = [];
338
337
  var localEnumStringTypes = [];
338
+ var additionalImports = [];
339
339
  var localeDef = undefined;
340
340
  ts.forEachChild(sourceFile, function (node) {
341
341
  var _a, _b, _c, _d;
342
342
  if (ts.isImportDeclaration(node)) {
343
- var entityImported = getEntityImported(node, filename);
343
+ var entityImported = getEntityImported(node);
344
344
  if (entityImported) {
345
345
  referencedSchemas.push(entityImported);
346
346
  }
347
+ else if (!process.env.COMPLING_IN_DOMAIN && !(relativePath === null || relativePath === void 0 ? void 0 : relativePath.startsWith(env_1.LIB_OAK_DOMAIN))) {
348
+ /**import了domain以外的其它定义类型,需要被复制到生成的Schema文件中
349
+ * 这里必须注意,1、假设了domain当中定义的几个entity不会引用其它文件上的定义(除了type里的那些通用类型,默认都会被输出到文件中)
350
+ * 2、假设了其它项目文件不会引用domain当中除了type通用类型之外的其它内容,否则不会被输出到文件中
351
+ * 这里主要是对import的处理比较粗略,日后有需要的时候再精修
352
+ */
353
+ var moduleSpecifier = node.moduleSpecifier, importClause = node.importClause;
354
+ if (ts.isStringLiteral(moduleSpecifier) && !moduleSpecifier.text.startsWith(env_1.LIB_OAK_DOMAIN)) {
355
+ // 编译后的路径默认要深一层
356
+ var moduleSpecifier2Text = relativePath
357
+ ? path_1.default.join(relativePath, moduleSpecifier.text).replace(/\\/g, '/')
358
+ : path_1.default.join('..', moduleSpecifier.text).replace(/\\/g, '/');
359
+ additionalImports.push(factory.updateImportDeclaration(node, undefined, undefined, importClause, factory.createStringLiteral(moduleSpecifier2Text), undefined));
360
+ }
361
+ }
347
362
  }
348
363
  if (ts.isInterfaceDeclaration(node)) {
349
364
  // schema 定义
@@ -417,6 +432,10 @@ function analyzeEntity(filename, path, program) {
417
432
  var types = type.types;
418
433
  if (ts.isLiteralTypeNode(types[0]) && ts.isStringLiteral(types[0].literal)) {
419
434
  enumStringAttrs.push(name.text);
435
+ types.forEach(function (ele) {
436
+ (0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal), "\u300C".concat(filename, "\u300D\u4E0D\u652F\u6301\u6DF7\u5408\u578B\u7684\u679A\u4E3E\u5C5E\u6027\u5B9A\u4E49\u300C").concat(attrName, "\u300D"));
437
+ (0, assert_1.default)(ele.literal.text.length < env_1.STRING_LITERAL_MAX_LENGTH, "\u300C".concat(filename, "\u300D\u4E2D\u5B9A\u4E49\u7684\u5C5E\u6027\u679A\u4E3E\u300C").concat(attrName, "\u300D\u7684\u5B57\u7B26\u4E32\u957F\u5EA6\u5E94\u5C0F\u4E8E").concat(env_1.STRING_LITERAL_MAX_LENGTH));
438
+ });
420
439
  }
421
440
  }
422
441
  }
@@ -552,6 +571,10 @@ function analyzeEntity(filename, path, program) {
552
571
  if (ts.isUnionTypeNode(node.type) && ts.isLiteralTypeNode(node.type.types[0]) && ts.isStringLiteral(node.type.types[0].literal)) {
553
572
  // 本文件内定义的枚举类型
554
573
  localEnumStringTypes.push(node.name.text);
574
+ node.type.types.forEach(function (ele) {
575
+ (0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal), "\u300C".concat(filename, "\u300D\u4E0D\u652F\u6301\u6DF7\u5408\u578B\u7684\u5E38\u91CF\u5B9A\u4E49\u300C").concat(node.name.text, "\u300D"));
576
+ (0, assert_1.default)(ele.literal.text.length < env_1.STRING_LITERAL_MAX_LENGTH, "\u300C".concat(filename, "\u300D\u4E2D\u5B9A\u4E49\u7684\u5E38\u91CF\u679A\u4E3E\u300C").concat(node.name.text, "\u300D\u7684\u5B57\u7B26\u4E32\u957F\u5EA6\u5E94\u5C0F\u4E8E").concat(env_1.STRING_LITERAL_MAX_LENGTH));
577
+ });
555
578
  }
556
579
  }
557
580
  }
@@ -793,6 +816,8 @@ function analyzeEntity(filename, path, program) {
793
816
  actionType: actionType,
794
817
  static: _static,
795
818
  hasRelationDef: hasRelationDef,
819
+ enumStringAttrs: enumStringAttrs.concat(states),
820
+ additionalImports: additionalImports,
796
821
  };
797
822
  if (hasFulltextIndex) {
798
823
  (0, lodash_1.assign)(schema, {
@@ -2628,6 +2653,10 @@ function outputSchema(outputDir, printer) {
2628
2653
  factory.createImportSpecifier(false, undefined, factory.createIdentifier("RelationAction")),
2629
2654
  ])), factory.createStringLiteral((0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)()), undefined));
2630
2655
  }
2656
+ var additionalImports = Schema[entity].additionalImports;
2657
+ if ((additionalImports === null || additionalImports === void 0 ? void 0 : additionalImports.length) > 0) {
2658
+ statements.push.apply(statements, tslib_1.__spreadArray([], tslib_1.__read(additionalImports), false));
2659
+ }
2631
2660
  constructSchema(statements, entity);
2632
2661
  constructFilter(statements, entity);
2633
2662
  constructProjection(statements, entity);
@@ -2709,8 +2738,8 @@ function outputAction(outputDir, printer) {
2709
2738
  (0, fs_1.writeFileSync)(fileName, result, { flag: 'w' });
2710
2739
  }
2711
2740
  function constructAttributes(entity) {
2712
- var schemaAttrs = Schema[entity].schemaAttrs;
2713
- var _a = ManyToOne, _b = entity, manyToOneSet = _a[_b];
2741
+ var _a = Schema[entity], schemaAttrs = _a.schemaAttrs, enumStringAttrs = _a.enumStringAttrs;
2742
+ var _b = ManyToOne, _c = entity, manyToOneSet = _b[_c];
2714
2743
  var result = [];
2715
2744
  schemaAttrs.forEach(function (attr) {
2716
2745
  var attrAssignments = [];
@@ -2786,11 +2815,11 @@ function constructAttributes(entity) {
2786
2815
  attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("ref")), factory.createPropertyAssignment(factory.createIdentifier("ref"), factory.createStringLiteral((0, string_1.firstLetterLowerCase)(text2_6))));
2787
2816
  }
2788
2817
  else {
2789
- if (text.endsWith('State')) {
2818
+ if (enumStringAttrs.includes(name.text)) {
2790
2819
  attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("varchar")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([factory.createPropertyAssignment(factory.createIdentifier("length"), factory.createNumericLiteral(env_1.STRING_LITERAL_MAX_LENGTH))], true)));
2791
2820
  }
2792
2821
  else {
2793
- // 引用的shape
2822
+ // todo 引用的非string定义,目前没有处理int类型的引用,等遇到了再处理
2794
2823
  attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("object")));
2795
2824
  }
2796
2825
  }
@@ -3065,7 +3094,6 @@ function analyzeInModi() {
3065
3094
  if (schema.toModi || schema.inModi || schema.actionType === 'readOnly' || schema.static) {
3066
3095
  return;
3067
3096
  }
3068
- console.log('setInModi', entity);
3069
3097
  schema.inModi = true;
3070
3098
  var related = getRelateEntities(entity);
3071
3099
  related.forEach(function (ele) { return setInModi(ele); });
@@ -3077,7 +3105,7 @@ function analyzeInModi() {
3077
3105
  }
3078
3106
  }
3079
3107
  }
3080
- function analyzeEntities(inputDir) {
3108
+ function analyzeEntities(inputDir, relativePath) {
3081
3109
  var files = (0, fs_1.readdirSync)(inputDir);
3082
3110
  var fullFilenames = files.map(function (ele) {
3083
3111
  var entity = ele.slice(0, ele.indexOf('.'));
@@ -3088,7 +3116,7 @@ function analyzeEntities(inputDir) {
3088
3116
  });
3089
3117
  var program = ts.createProgram(fullFilenames, { allowJs: true });
3090
3118
  files.forEach(function (filename) {
3091
- analyzeEntity(filename, inputDir, program);
3119
+ analyzeEntity(filename, inputDir, program, relativePath);
3092
3120
  });
3093
3121
  analyzeInModi();
3094
3122
  }
@@ -280,7 +280,7 @@ var CascadeStore = /** @class */ (function (_super) {
280
280
  }
281
281
  else {
282
282
  (0, assert_1.default)(relation instanceof Array);
283
- var _g = projection2[attr], subProjection_1 = _g.data, subFilter_1 = _g.filter, indexFrom_1 = _g.indexFrom, count_1 = _g.count, subSorter = _g.sorter;
283
+ var _g = projection2[attr], subProjection_1 = _g.data, subFilter_1 = _g.filter, indexFrom_1 = _g.indexFrom, count_1 = _g.count, subSorter_1 = _g.sorter;
284
284
  var _h = tslib_1.__read(relation, 2), entity2_1 = _h[0], foreignKey_1 = _h[1];
285
285
  if (foreignKey_1) {
286
286
  // 基于属性的一对多
@@ -298,6 +298,7 @@ var CascadeStore = /** @class */ (function (_super) {
298
298
  $in: ids,
299
299
  },
300
300
  _a), subFilter_1]),
301
+ sorter: subSorter_1,
301
302
  indexFrom: indexFrom_1,
302
303
  count: count_1
303
304
  }, context, option)];
@@ -332,6 +333,7 @@ var CascadeStore = /** @class */ (function (_super) {
332
333
  $in: ids,
333
334
  }
334
335
  }, subFilter_1]),
336
+ sorter: subSorter_1,
335
337
  indexFrom: indexFrom_1,
336
338
  count: count_1
337
339
  }, context, option)];
@@ -1005,36 +1007,34 @@ var CascadeStore = /** @class */ (function (_super) {
1005
1007
  */
1006
1008
  CascadeStore.prototype.cascadeUpdate = function (entity, operation, context, option) {
1007
1009
  return tslib_1.__awaiter(this, void 0, void 0, function () {
1008
- var action, data, filter, id, opData, result, multipleCreate, data_1, data_1_1, d, od, e_3_1, data_2, data_2_1, dataEle, result2, e_4_1, operation2, count;
1009
- var e_3, _a, e_4, _b, _c, _d;
1010
- return tslib_1.__generator(this, function (_e) {
1011
- switch (_e.label) {
1010
+ var action, data, filter, id, opData, result, data_1, data_1_1, d, od, e_3_1, operation2, count;
1011
+ var e_3, _a, _b, _c;
1012
+ return tslib_1.__generator(this, function (_d) {
1013
+ switch (_d.label) {
1012
1014
  case 0:
1013
1015
  action = operation.action, data = operation.data, filter = operation.filter, id = operation.id;
1014
1016
  result = {};
1015
- if (!(['create', 'create-l'].includes(action) && data instanceof Array)) return [3 /*break*/, 18];
1016
- multipleCreate = this.supportMultipleCreate();
1017
- if (!multipleCreate) return [3 /*break*/, 9];
1017
+ if (!(['create', 'create-l'].includes(action) && data instanceof Array)) return [3 /*break*/, 9];
1018
1018
  opData = [];
1019
- _e.label = 1;
1019
+ _d.label = 1;
1020
1020
  case 1:
1021
- _e.trys.push([1, 6, 7, 8]);
1021
+ _d.trys.push([1, 6, 7, 8]);
1022
1022
  data_1 = tslib_1.__values(data), data_1_1 = data_1.next();
1023
- _e.label = 2;
1023
+ _d.label = 2;
1024
1024
  case 2:
1025
1025
  if (!!data_1_1.done) return [3 /*break*/, 5];
1026
1026
  d = data_1_1.value;
1027
1027
  return [4 /*yield*/, this.destructCascadeUpdate(entity, action, d, context, option, result)];
1028
1028
  case 3:
1029
- od = _e.sent();
1029
+ od = _d.sent();
1030
1030
  opData.push(od);
1031
- _e.label = 4;
1031
+ _d.label = 4;
1032
1032
  case 4:
1033
1033
  data_1_1 = data_1.next();
1034
1034
  return [3 /*break*/, 2];
1035
1035
  case 5: return [3 /*break*/, 8];
1036
1036
  case 6:
1037
- e_3_1 = _e.sent();
1037
+ e_3_1 = _d.sent();
1038
1038
  e_3 = { error: e_3_1 };
1039
1039
  return [3 /*break*/, 8];
1040
1040
  case 7:
@@ -1043,55 +1043,23 @@ var CascadeStore = /** @class */ (function (_super) {
1043
1043
  }
1044
1044
  finally { if (e_3) throw e_3.error; }
1045
1045
  return [7 /*endfinally*/];
1046
- case 8: return [3 /*break*/, 17];
1047
- case 9:
1048
- _e.trys.push([9, 14, 15, 16]);
1049
- data_2 = tslib_1.__values(data), data_2_1 = data_2.next();
1050
- _e.label = 10;
1046
+ case 8: return [3 /*break*/, 11];
1047
+ case 9: return [4 /*yield*/, this.destructCascadeUpdate(entity, action, data, context, option, result, filter)];
1051
1048
  case 10:
1052
- if (!!data_2_1.done) return [3 /*break*/, 13];
1053
- dataEle = data_2_1.value;
1054
- return [4 /*yield*/, this.cascadeUpdate(entity, {
1055
- id: id,
1056
- action: action,
1057
- data: dataEle,
1058
- }, context, option)];
1049
+ opData = _d.sent();
1050
+ _d.label = 11;
1059
1051
  case 11:
1060
- result2 = _e.sent();
1061
- this.mergeOperationResult(result, result2);
1062
- _e.label = 12;
1063
- case 12:
1064
- data_2_1 = data_2.next();
1065
- return [3 /*break*/, 10];
1066
- case 13: return [3 /*break*/, 16];
1067
- case 14:
1068
- e_4_1 = _e.sent();
1069
- e_4 = { error: e_4_1 };
1070
- return [3 /*break*/, 16];
1071
- case 15:
1072
- try {
1073
- if (data_2_1 && !data_2_1.done && (_b = data_2.return)) _b.call(data_2);
1074
- }
1075
- finally { if (e_4) throw e_4.error; }
1076
- return [7 /*endfinally*/];
1077
- case 16: return [2 /*return*/, result];
1078
- case 17: return [3 /*break*/, 20];
1079
- case 18: return [4 /*yield*/, this.destructCascadeUpdate(entity, action, data, context, option, result, filter)];
1080
- case 19:
1081
- opData = _e.sent();
1082
- _e.label = 20;
1083
- case 20:
1084
1052
  operation2 = Object.assign({}, operation, {
1085
1053
  data: opData,
1086
1054
  });
1087
1055
  return [4 /*yield*/, this.doUpdateSingleRow(entity, operation2, context, option)];
1088
- case 21:
1089
- count = _e.sent();
1090
- this.mergeOperationResult(result, (_c = {},
1091
- _c[entity] = (_d = {},
1092
- _d[operation2.action] = count,
1093
- _d),
1094
- _c));
1056
+ case 12:
1057
+ count = _d.sent();
1058
+ this.mergeOperationResult(result, (_b = {},
1059
+ _b[entity] = (_c = {},
1060
+ _c[operation2.action] = count,
1061
+ _c),
1062
+ _b));
1095
1063
  return [2 /*return*/, result];
1096
1064
  }
1097
1065
  });
@@ -1106,11 +1074,11 @@ var CascadeStore = /** @class */ (function (_super) {
1106
1074
  */
1107
1075
  CascadeStore.prototype.doUpdateSingleRow = function (entity, operation, context, option) {
1108
1076
  return tslib_1.__awaiter(this, void 0, void 0, function () {
1109
- var data, action, operId, filter, now, _a, modiCreate, addTimestamp_1, result_1, e_5, congruentRow_1, rest, result2, row, updateData, result3, _b, _c, updateData, result2, _d, _e, createOper, _f, ids_1, selection, rows, modiUpsert, upsertModis, _g, originData, originId, createOper, updateAttrCount, result_2;
1110
- var _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
1077
+ var data, action, operId, filter, now, _a, modiCreate, addTimestamp_1, result_1, createInner, multipleCreate, data_2, data_2_1, d, createSingleOper, e_4_1, createOper, _b, ids_1, selection, rows, modiUpsert, upsertModis, _c, originData, originId, createOper, updateAttrCount, result_2;
1078
+ var e_4, _d, _e, _f, _g, _h, _j, _k, _l, _m;
1111
1079
  var _this = this;
1112
- return tslib_1.__generator(this, function (_t) {
1113
- switch (_t.label) {
1080
+ return tslib_1.__generator(this, function (_o) {
1081
+ switch (_o.label) {
1114
1082
  case 0:
1115
1083
  data = operation.data, action = operation.action, operId = operation.id, filter = operation.filter;
1116
1084
  now = Date.now();
@@ -1141,7 +1109,7 @@ var CascadeStore = /** @class */ (function (_super) {
1141
1109
  };
1142
1110
  return [4 /*yield*/, this.cascadeUpdate('modi', modiCreate, context, option)];
1143
1111
  case 2:
1144
- _t.sent();
1112
+ _o.sent();
1145
1113
  return [2 /*return*/, 1];
1146
1114
  case 3:
1147
1115
  addTimestamp_1 = function (data2) {
@@ -1156,67 +1124,128 @@ var CascadeStore = /** @class */ (function (_super) {
1156
1124
  else {
1157
1125
  addTimestamp_1(data);
1158
1126
  }
1159
- _t.label = 4;
1127
+ createInner = function (operation2) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
1128
+ var e_5;
1129
+ return tslib_1.__generator(this, function (_a) {
1130
+ switch (_a.label) {
1131
+ case 0:
1132
+ _a.trys.push([0, 2, , 3]);
1133
+ return [4 /*yield*/, this.updateAbjointRow(entity, operation2, context, option)];
1134
+ case 1:
1135
+ result_1 = _a.sent();
1136
+ return [3 /*break*/, 3];
1137
+ case 2:
1138
+ e_5 = _a.sent();
1139
+ /* 这段代码是处理插入时有重复的行,现在看有问题,等实际需求出现再写
1140
+ if (e instanceof OakCongruentRowExists) {
1141
+ if (option.allowExists) {
1142
+ // 如果允许存在,对已存在行进行update,剩下的行继续insert
1143
+ const congruentRow = e.getData() as ED[T]['OpSchema'];
1144
+ if (data instanceof Array) {
1145
+ const rest = data.filter(
1146
+ ele => ele.id !== congruentRow.id
1147
+ );
1148
+ if (rest.length === data.length) {
1149
+ throw e;
1150
+ }
1151
+ const result2 = await this.updateAbjointRow(
1152
+ entity,
1153
+ Object.assign({}, operation, {
1154
+ data: rest,
1155
+ }),
1156
+ context,
1157
+ option
1158
+ );
1159
+
1160
+ const row = data.find(
1161
+ ele => ele.id === congruentRow.id
1162
+ );
1163
+ const updateData = omit(row, ['id', '$$createAt$$']);
1164
+ const result3 = await this.updateAbjointRow(
1165
+ entity,
1166
+ {
1167
+ id: await generateNewId(),
1168
+ action: 'update',
1169
+ data: updateData,
1170
+ filter: {
1171
+ id: congruentRow.id,
1172
+ } as any,
1173
+ },
1174
+ context,
1175
+ option
1176
+ );
1177
+
1178
+ return result2 + result3;
1179
+ }
1180
+ else {
1181
+ if (data.id !== congruentRow.id) {
1182
+ throw e;
1183
+ }
1184
+ const updateData = omit(data, ['id', '$$createAt$$']);
1185
+ const result2 = await this.updateAbjointRow(
1186
+ entity,
1187
+ {
1188
+ id: await generateNewId(),
1189
+ action: 'update',
1190
+ data: updateData,
1191
+ filter: {
1192
+ id: congruentRow.id,
1193
+ } as any,
1194
+ },
1195
+ context,
1196
+ option
1197
+ );
1198
+ return result2;
1199
+ }
1200
+ }
1201
+ } */
1202
+ throw e_5;
1203
+ case 3: return [2 /*return*/];
1204
+ }
1205
+ });
1206
+ }); };
1207
+ if (!(data instanceof Array)) return [3 /*break*/, 13];
1208
+ multipleCreate = this.supportMultipleCreate();
1209
+ if (!multipleCreate) return [3 /*break*/, 5];
1210
+ return [4 /*yield*/, createInner(operation)];
1160
1211
  case 4:
1161
- _t.trys.push([4, 6, , 15]);
1162
- return [4 /*yield*/, this.updateAbjointRow(entity, operation, context, option)];
1212
+ _o.sent();
1213
+ return [3 /*break*/, 12];
1163
1214
  case 5:
1164
- result_1 = _t.sent();
1165
- return [3 /*break*/, 15];
1215
+ _o.trys.push([5, 10, 11, 12]);
1216
+ data_2 = tslib_1.__values(data), data_2_1 = data_2.next();
1217
+ _o.label = 6;
1166
1218
  case 6:
1167
- e_5 = _t.sent();
1168
- if (!(e_5 instanceof types_1.OakCongruentRowExists)) return [3 /*break*/, 14];
1169
- if (!option.allowExists) return [3 /*break*/, 13];
1170
- congruentRow_1 = e_5.getData();
1171
- if (!(data instanceof Array)) return [3 /*break*/, 10];
1172
- rest = data.filter(function (ele) { return ele.id !== congruentRow_1.id; });
1173
- if (rest.length === data.length) {
1174
- throw e_5;
1175
- }
1176
- return [4 /*yield*/, this.updateAbjointRow(entity, Object.assign({}, operation, {
1177
- data: rest,
1178
- }), context, option)];
1219
+ if (!!data_2_1.done) return [3 /*break*/, 9];
1220
+ d = data_2_1.value;
1221
+ createSingleOper = {
1222
+ id: 'any',
1223
+ action: 'create',
1224
+ data: d,
1225
+ };
1226
+ return [4 /*yield*/, createInner(createSingleOper)];
1179
1227
  case 7:
1180
- result2 = _t.sent();
1181
- row = data.find(function (ele) { return ele.id === congruentRow_1.id; });
1182
- updateData = (0, lodash_1.omit)(row, ['id', '$$createAt$$']);
1183
- _b = this.updateAbjointRow;
1184
- _c = [entity];
1185
- _h = {};
1186
- return [4 /*yield*/, generateNewId()];
1187
- case 8: return [4 /*yield*/, _b.apply(this, _c.concat([(_h.id = _t.sent(),
1188
- _h.action = 'update',
1189
- _h.data = updateData,
1190
- _h.filter = {
1191
- id: congruentRow_1.id,
1192
- },
1193
- _h), context,
1194
- option]))];
1195
- case 9:
1196
- result3 = _t.sent();
1197
- return [2 /*return*/, result2 + result3];
1228
+ _o.sent();
1229
+ _o.label = 8;
1230
+ case 8:
1231
+ data_2_1 = data_2.next();
1232
+ return [3 /*break*/, 6];
1233
+ case 9: return [3 /*break*/, 12];
1198
1234
  case 10:
1199
- if (data.id !== congruentRow_1.id) {
1200
- throw e_5;
1235
+ e_4_1 = _o.sent();
1236
+ e_4 = { error: e_4_1 };
1237
+ return [3 /*break*/, 12];
1238
+ case 11:
1239
+ try {
1240
+ if (data_2_1 && !data_2_1.done && (_d = data_2.return)) _d.call(data_2);
1201
1241
  }
1202
- updateData = (0, lodash_1.omit)(data, ['id', '$$createAt$$']);
1203
- _d = this.updateAbjointRow;
1204
- _e = [entity];
1205
- _j = {};
1206
- return [4 /*yield*/, generateNewId()];
1207
- case 11: return [4 /*yield*/, _d.apply(this, _e.concat([(_j.id = _t.sent(),
1208
- _j.action = 'update',
1209
- _j.data = updateData,
1210
- _j.filter = {
1211
- id: congruentRow_1.id,
1212
- },
1213
- _j), context,
1214
- option]))];
1215
- case 12:
1216
- result2 = _t.sent();
1217
- return [2 /*return*/, result2];
1218
- case 13: throw e_5;
1219
- case 14: return [3 /*break*/, 15];
1242
+ finally { if (e_4) throw e_4.error; }
1243
+ return [7 /*endfinally*/];
1244
+ case 12: return [3 /*break*/, 15];
1245
+ case 13: return [4 /*yield*/, createInner(operation)];
1246
+ case 14:
1247
+ _o.sent();
1248
+ _o.label = 15;
1220
1249
  case 15:
1221
1250
  if (!option.dontCollect) {
1222
1251
  context.opRecords.push({
@@ -1228,20 +1257,20 @@ var CascadeStore = /** @class */ (function (_super) {
1228
1257
  if (!(!option.dontCreateOper && !['oper', 'operEntity', 'modiEntity', 'modi'].includes(entity))) return [3 /*break*/, 22];
1229
1258
  // 按照框架要求生成Oper和OperEntity这两个内置的对象
1230
1259
  (0, assert_1.default)(operId);
1231
- _k = {
1260
+ _e = {
1232
1261
  id: 'dummy',
1233
1262
  action: 'create'
1234
1263
  };
1235
- _l = {
1264
+ _f = {
1236
1265
  id: operId,
1237
1266
  action: action,
1238
1267
  data: data
1239
1268
  };
1240
1269
  return [4 /*yield*/, context.getCurrentUserId()];
1241
1270
  case 16:
1242
- _l.operatorId = _t.sent();
1271
+ _f.operatorId = _o.sent();
1243
1272
  if (!(data instanceof Array)) return [3 /*break*/, 18];
1244
- _m = {
1273
+ _g = {
1245
1274
  id: 'dummy',
1246
1275
  action: 'create'
1247
1276
  };
@@ -1260,34 +1289,34 @@ var CascadeStore = /** @class */ (function (_super) {
1260
1289
  });
1261
1290
  }); }))];
1262
1291
  case 17:
1263
- _f = (_m.data = _t.sent(),
1264
- _m);
1292
+ _b = (_g.data = _o.sent(),
1293
+ _g);
1265
1294
  return [3 /*break*/, 20];
1266
1295
  case 18:
1267
- _o = {
1296
+ _h = {
1268
1297
  id: 'dummy',
1269
1298
  action: 'create'
1270
1299
  };
1271
- _p = {};
1300
+ _j = {};
1272
1301
  return [4 /*yield*/, generateNewId()];
1273
1302
  case 19:
1274
- _f = [(_o.data = (_p.id = _t.sent(),
1275
- _p.entity = entity,
1276
- _p.entityId = data.id,
1277
- _p),
1278
- _o)];
1279
- _t.label = 20;
1303
+ _b = [(_h.data = (_j.id = _o.sent(),
1304
+ _j.entity = entity,
1305
+ _j.entityId = data.id,
1306
+ _j),
1307
+ _h)];
1308
+ _o.label = 20;
1280
1309
  case 20:
1281
- createOper = (_k.data = (_l.operEntity$oper = _f,
1282
- _l),
1283
- _k);
1310
+ createOper = (_e.data = (_f.operEntity$oper = _b,
1311
+ _f),
1312
+ _e);
1284
1313
  return [4 /*yield*/, this.cascadeUpdate('oper', createOper, context, {
1285
1314
  dontCollect: true,
1286
1315
  dontCreateOper: true,
1287
1316
  })];
1288
1317
  case 21:
1289
- _t.sent();
1290
- _t.label = 22;
1318
+ _o.sent();
1319
+ _o.label = 22;
1291
1320
  case 22: return [2 /*return*/, result_1];
1292
1321
  case 23:
1293
1322
  ids_1 = (0, filter_1.getRelevantIds)(filter);
@@ -1304,9 +1333,9 @@ var CascadeStore = /** @class */ (function (_super) {
1304
1333
  dontCollect: true,
1305
1334
  })];
1306
1335
  case 24:
1307
- rows = _t.sent();
1336
+ rows = _o.sent();
1308
1337
  ids_1.push.apply(ids_1, tslib_1.__spreadArray([], tslib_1.__read((rows.map(function (ele) { return ele.id; }))), false));
1309
- _t.label = 25;
1338
+ _o.label = 25;
1310
1339
  case 25:
1311
1340
  if (!(option.modiParentEntity && !['modi', 'modiEntity'].includes(entity))) return [3 /*break*/, 31];
1312
1341
  modiUpsert = void 0;
@@ -1340,9 +1369,9 @@ var CascadeStore = /** @class */ (function (_super) {
1340
1369
  count: 1,
1341
1370
  }, context, option)];
1342
1371
  case 26:
1343
- upsertModis = _t.sent();
1372
+ upsertModis = _o.sent();
1344
1373
  if (upsertModis.length > 0) {
1345
- _g = upsertModis[0], originData = _g.data, originId = _g.id;
1374
+ _c = upsertModis[0], originData = _c.data, originId = _c.id;
1346
1375
  modiUpsert = {
1347
1376
  id: 'dummy',
1348
1377
  action: 'update',
@@ -1354,14 +1383,14 @@ var CascadeStore = /** @class */ (function (_super) {
1354
1383
  }
1355
1384
  };
1356
1385
  }
1357
- _t.label = 27;
1386
+ _o.label = 27;
1358
1387
  case 27:
1359
1388
  if (!!modiUpsert) return [3 /*break*/, 29];
1360
- _q = {
1389
+ _k = {
1361
1390
  id: 'dummy',
1362
1391
  action: 'create'
1363
1392
  };
1364
- _r = {
1393
+ _l = {
1365
1394
  id: operId,
1366
1395
  targetEntity: entity,
1367
1396
  entity: option.modiParentEntity,
@@ -1375,7 +1404,7 @@ var CascadeStore = /** @class */ (function (_super) {
1375
1404
  },
1376
1405
  }
1377
1406
  };
1378
- _s = {
1407
+ _m = {
1379
1408
  id: 'dummy',
1380
1409
  action: 'create'
1381
1410
  };
@@ -1394,14 +1423,14 @@ var CascadeStore = /** @class */ (function (_super) {
1394
1423
  });
1395
1424
  }); }))];
1396
1425
  case 28:
1397
- modiUpsert = (_q.data = (_r.modiEntity$modi = (_s.data = _t.sent(),
1398
- _s),
1399
- _r),
1400
- _q);
1401
- _t.label = 29;
1426
+ modiUpsert = (_k.data = (_l.modiEntity$modi = (_m.data = _o.sent(),
1427
+ _m),
1428
+ _l),
1429
+ _k);
1430
+ _o.label = 29;
1402
1431
  case 29: return [4 /*yield*/, this.cascadeUpdate('modi', modiUpsert, context, option)];
1403
1432
  case 30:
1404
- _t.sent();
1433
+ _o.sent();
1405
1434
  return [2 /*return*/, 1];
1406
1435
  case 31:
1407
1436
  createOper = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
@@ -1496,15 +1525,15 @@ var CascadeStore = /** @class */ (function (_super) {
1496
1525
  return [4 /*yield*/, createOper()];
1497
1526
  case 34:
1498
1527
  // 如果不是update动作而是用户自定义的动作,这里还是要记录oper
1499
- _t.sent();
1528
+ _o.sent();
1500
1529
  return [2 /*return*/, 0];
1501
1530
  case 35: return [2 /*return*/, 0];
1502
1531
  case 36: return [4 /*yield*/, this.updateAbjointRow(entity, operation, context, option)];
1503
1532
  case 37:
1504
- result_2 = _t.sent();
1533
+ result_2 = _o.sent();
1505
1534
  return [4 /*yield*/, createOper()];
1506
1535
  case 38:
1507
- _t.sent();
1536
+ _o.sent();
1508
1537
  return [2 /*return*/, result_2];
1509
1538
  }
1510
1539
  });
@@ -3,7 +3,7 @@ import { EntityDict as BaseEntityDict } from '../base-app-domain';
3
3
  import { Logger } from "../types/Logger";
4
4
  import { Checker } from '../types/Auth';
5
5
  import { Context } from '../types/Context';
6
- import { Trigger, Executor } from "../types/Trigger";
6
+ import { Trigger, Executor, CheckerType } from "../types/Trigger";
7
7
  /**
8
8
  * update可能会传入多种不同的action,此时都需要检查update trigger
9
9
  */
@@ -16,6 +16,7 @@ export declare class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt
16
16
  private contextBuilder;
17
17
  constructor(contextBuilder: (cxtString: string) => Promise<Cxt>, logger?: Logger);
18
18
  registerChecker<T extends keyof ED>(checker: Checker<ED, T, Cxt>): void;
19
+ getCheckers<T extends keyof ED>(entity: T, action: ED[T]['Action'], checkerTypes?: CheckerType[]): Trigger<ED, T, Cxt>[] | undefined;
19
20
  registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
20
21
  unregisterTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
21
22
  private preCommitTrigger;
@@ -43,6 +43,12 @@ var TriggerExecutor = /** @class */ (function (_super) {
43
43
  };
44
44
  this.registerTrigger(trigger);
45
45
  };
46
+ TriggerExecutor.prototype.getCheckers = function (entity, action, checkerTypes) {
47
+ var _a;
48
+ var triggers = this.triggerMap[entity] && ((_a = this.triggerMap[entity][action]) === null || _a === void 0 ? void 0 : _a.filter(function (trigger) { return (typeof trigger.action === 'string' && trigger.action === action || (trigger.action).includes(action))
49
+ && (!checkerTypes || trigger.checkerType && checkerTypes.includes(trigger.checkerType)); }));
50
+ return triggers;
51
+ };
46
52
  TriggerExecutor.prototype.registerTrigger = function (trigger) {
47
53
  var _a;
48
54
  var _this = this;
@@ -1,3 +1,5 @@
1
+ /// <reference types="node" />
2
+ import { IncomingHttpHeaders } from 'http';
1
3
  import { EntityDict, OpRecord, RowStore, TxnOption, Context } from "../types";
2
4
  export declare abstract class UniversalContext<ED extends EntityDict> implements Context<ED> {
3
5
  rowStore: RowStore<ED, this>;
@@ -5,11 +7,14 @@ export declare abstract class UniversalContext<ED extends EntityDict> implements
5
7
  opRecords: OpRecord<ED>[];
6
8
  private scene?;
7
9
  private rwLock;
10
+ private headers?;
8
11
  events: {
9
12
  commit: Array<() => Promise<void>>;
10
13
  rollback: Array<() => Promise<void>>;
11
14
  };
12
- constructor(store: RowStore<ED, UniversalContext<ED>>);
15
+ constructor(store: RowStore<ED, UniversalContext<ED>>, headers?: IncomingHttpHeaders);
16
+ setHeaders(headers: IncomingHttpHeaders): void;
17
+ getHeader(key: string): string | string[] | undefined;
13
18
  getScene(): string | undefined;
14
19
  setScene(scene?: string): void;
15
20
  private resetEvents;
@@ -5,7 +5,7 @@ var tslib_1 = require("tslib");
5
5
  var assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  var concurrent_1 = require("../utils/concurrent");
7
7
  var UniversalContext = /** @class */ (function () {
8
- function UniversalContext(store) {
8
+ function UniversalContext(store, headers) {
9
9
  this.rowStore = store;
10
10
  this.opRecords = [];
11
11
  this.rwLock = new concurrent_1.RWLock();
@@ -13,7 +13,18 @@ var UniversalContext = /** @class */ (function () {
13
13
  commit: [],
14
14
  rollback: [],
15
15
  };
16
+ if (headers) {
17
+ this.headers = headers;
18
+ }
16
19
  }
20
+ UniversalContext.prototype.setHeaders = function (headers) {
21
+ this.headers = headers;
22
+ };
23
+ UniversalContext.prototype.getHeader = function (key) {
24
+ if (this.headers) {
25
+ return this.headers[key];
26
+ }
27
+ };
17
28
  UniversalContext.prototype.getScene = function () {
18
29
  return this.scene;
19
30
  };
@@ -1,7 +1,8 @@
1
1
  import { StorageSchema } from '../types';
2
2
  import { EntityDict } from "../types/Entity";
3
3
  export declare function addFilterSegment<ED extends EntityDict, T extends keyof ED>(...filters: ED[T]['Selection']['filter'][]): ED[T]["Selection"]["filter"];
4
- export declare function combineFilters<ED extends EntityDict, T extends keyof ED>(filters: Array<ED[T]['Selection']['filter']>): ED[T]["Selection"]["filter"];
4
+ export declare function unionFilterSegment<ED extends EntityDict, T extends keyof ED>(...filters: ED[T]['Selection']['filter'][]): ED[T]["Selection"]["filter"];
5
+ export declare function combineFilters<ED extends EntityDict, T extends keyof ED>(filters: Array<ED[T]['Selection']['filter']>, union?: true): ED[T]["Selection"]["filter"];
5
6
  /**
6
7
  * 判断filter是否包含conditionalFilter中的查询条件,即filter查询的结果一定满足conditionalFilter的约束
7
8
  * filter = {
@@ -40,3 +41,29 @@ export declare function repel<ED extends EntityDict, T extends keyof ED>(entity:
40
41
  * @returns
41
42
  */
42
43
  export declare function getRelevantIds<ED extends EntityDict, T extends keyof ED>(filter: ED[T]['Selection']['filter']): string[];
44
+ /**
45
+ * 判断两个过滤条件是否完全一致
46
+ * @param entity
47
+ * @param schema
48
+ * @param filter1
49
+ * @param filter2
50
+ */
51
+ export declare function same<ED extends EntityDict, T extends keyof ED>(entity: T, schema: StorageSchema<ED>, filter1: ED[T]['Selection']['filter'], filter2: ED[T]['Selection']['filter']): boolean;
52
+ /**
53
+ * 寻找在树形结构中满足条件的数据行的上层数据
54
+ * 例如在area表中,如果“杭州市”满足这一条件,则希望查到更高层的“浙江省”和“中国”,即可构造出满足条件的filter
55
+ * @param entity
56
+ * @param parentKey parentId属性名
57
+ * @param filter 查询当前行的条件
58
+ * @param level
59
+ */
60
+ export declare function makeTreeAncestorFilter<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'];
61
+ /**
62
+ * 寻找在树形结构中满足条件的数据行的下层数据
63
+ * 例如在area表中,如果“杭州市”满足这一条件,则希望查到更低层的“西湖区”,即可构造出满足条件的filter
64
+ * @param entity
65
+ * @param parentKey parentId属性名
66
+ * @param filter 查询当前行的条件
67
+ * @param level
68
+ */
69
+ 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'];
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRelevantIds = exports.repel = exports.contains = exports.combineFilters = exports.addFilterSegment = void 0;
3
+ exports.makeTreeDescendantFilter = exports.makeTreeAncestorFilter = exports.same = exports.getRelevantIds = exports.repel = exports.contains = exports.combineFilters = exports.unionFilterSegment = exports.addFilterSegment = void 0;
4
4
  var tslib_1 = require("tslib");
5
+ var assert_1 = tslib_1.__importDefault(require("assert"));
5
6
  var lodash_1 = require("../utils/lodash");
6
7
  function addFilterSegment() {
7
8
  var filters = [];
@@ -52,7 +53,45 @@ function addFilterSegment() {
52
53
  return filter;
53
54
  }
54
55
  exports.addFilterSegment = addFilterSegment;
55
- function combineFilters(filters) {
56
+ function unionFilterSegment() {
57
+ var e_1, _a;
58
+ var filters = [];
59
+ for (var _i = 0; _i < arguments.length; _i++) {
60
+ filters[_i] = arguments[_i];
61
+ }
62
+ var allOnlyOneOr = true;
63
+ try {
64
+ for (var filters_1 = tslib_1.__values(filters), filters_1_1 = filters_1.next(); !filters_1_1.done; filters_1_1 = filters_1.next()) {
65
+ var f = filters_1_1.value;
66
+ if (Object.keys(f).length > 1 || !f.$or) {
67
+ allOnlyOneOr = false;
68
+ break;
69
+ }
70
+ }
71
+ }
72
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
73
+ finally {
74
+ try {
75
+ if (filters_1_1 && !filters_1_1.done && (_a = filters_1.return)) _a.call(filters_1);
76
+ }
77
+ finally { if (e_1) throw e_1.error; }
78
+ }
79
+ if (allOnlyOneOr) {
80
+ // 优化特殊情况,全部都是$or,直接合并
81
+ var ors = filters.map(function (ele) { return ele.$or; });
82
+ return {
83
+ $or: ors.reduce(function (prev, next) { return prev.concat(next); }, [])
84
+ };
85
+ }
86
+ return {
87
+ $or: filters,
88
+ };
89
+ }
90
+ exports.unionFilterSegment = unionFilterSegment;
91
+ function combineFilters(filters, union) {
92
+ if (union) {
93
+ return unionFilterSegment.apply(void 0, tslib_1.__spreadArray([], tslib_1.__read(filters), false));
94
+ }
56
95
  return addFilterSegment.apply(void 0, tslib_1.__spreadArray([], tslib_1.__read(filters), false));
57
96
  }
58
97
  exports.combineFilters = combineFilters;
@@ -150,3 +189,98 @@ function getRelevantIds(filter) {
150
189
  return result;
151
190
  }
152
191
  exports.getRelevantIds = getRelevantIds;
192
+ /**
193
+ * 判断两个过滤条件是否完全一致
194
+ * @param entity
195
+ * @param schema
196
+ * @param filter1
197
+ * @param filter2
198
+ */
199
+ function same(entity, schema, filter1, filter2) {
200
+ // 当前只需要判断是不是id相等就行了,在runningTree的operation合并的时间使用
201
+ if (!filter1 || !filter1.id || Object.keys(filter1).length > 1 || !filter2 || !filter2.id || Object.keys(filter2).length > 1) {
202
+ return false;
203
+ }
204
+ return filter1.id === filter2.id;
205
+ }
206
+ exports.same = same;
207
+ /**
208
+ * 寻找在树形结构中满足条件的数据行的上层数据
209
+ * 例如在area表中,如果“杭州市”满足这一条件,则希望查到更高层的“浙江省”和“中国”,即可构造出满足条件的filter
210
+ * @param entity
211
+ * @param parentKey parentId属性名
212
+ * @param filter 查询当前行的条件
213
+ * @param level
214
+ */
215
+ function makeTreeAncestorFilter(entity, parentKey, filter, level, includeAll, includeSelf) {
216
+ var _a;
217
+ if (level === void 0) { level = 1; }
218
+ (0, assert_1.default)(level >= 0);
219
+ var idInFilters = [];
220
+ if (includeSelf) {
221
+ idInFilters.push(filter);
222
+ }
223
+ var currentLevelInFilter = filter;
224
+ while (level > 0) {
225
+ currentLevelInFilter = {
226
+ id: {
227
+ $in: {
228
+ entity: entity,
229
+ data: (_a = {},
230
+ _a[parentKey] = 1,
231
+ _a),
232
+ filter: currentLevelInFilter,
233
+ }
234
+ },
235
+ };
236
+ if (includeAll) {
237
+ idInFilters.push(currentLevelInFilter);
238
+ }
239
+ level--;
240
+ }
241
+ ;
242
+ if (includeAll) {
243
+ return {
244
+ $or: idInFilters,
245
+ };
246
+ }
247
+ return currentLevelInFilter;
248
+ }
249
+ exports.makeTreeAncestorFilter = makeTreeAncestorFilter;
250
+ /**
251
+ * 寻找在树形结构中满足条件的数据行的下层数据
252
+ * 例如在area表中,如果“杭州市”满足这一条件,则希望查到更低层的“西湖区”,即可构造出满足条件的filter
253
+ * @param entity
254
+ * @param parentKey parentId属性名
255
+ * @param filter 查询当前行的条件
256
+ * @param level
257
+ */
258
+ function makeTreeDescendantFilter(entity, parentKey, filter, level, includeAll, includeSelf) {
259
+ var _a;
260
+ if (level === void 0) { level = 1; }
261
+ (0, assert_1.default)(level >= 0);
262
+ (0, assert_1.default)(parentKey.endsWith('Id'));
263
+ var parentKeyRef = parentKey.slice(0, parentKey.length - 2);
264
+ var idInFilters = [];
265
+ if (includeSelf) {
266
+ idInFilters.push(filter);
267
+ }
268
+ var currentLevelInFilter = filter;
269
+ while (level > 0) {
270
+ currentLevelInFilter = (_a = {},
271
+ _a[parentKeyRef] = currentLevelInFilter,
272
+ _a);
273
+ if (includeAll) {
274
+ idInFilters.push(currentLevelInFilter);
275
+ }
276
+ level--;
277
+ }
278
+ ;
279
+ if (includeAll) {
280
+ return {
281
+ $or: idInFilters,
282
+ };
283
+ }
284
+ return currentLevelInFilter;
285
+ }
286
+ exports.makeTreeDescendantFilter = makeTreeDescendantFilter;
@@ -10,11 +10,11 @@ export declare abstract class Connector<ED extends EntityDict, Cxt extends Conte
10
10
  opRecords: OpRecord<ED>[];
11
11
  }>;
12
12
  abstract getRouter(): string;
13
- abstract parseRequest(headers: IncomingHttpHeaders, body: any, store: RowStore<ED, Cxt>): {
13
+ abstract parseRequest(headers: IncomingHttpHeaders, body: any, store: RowStore<ED, Cxt>): Promise<{
14
14
  name: string;
15
15
  params: any;
16
16
  context: Cxt;
17
- };
17
+ }>;
18
18
  abstract serializeResult(result: any, context: Cxt, headers: IncomingHttpHeaders, body: any): {
19
19
  body: any;
20
20
  headers?: Record<string, any>;
@@ -12,4 +12,5 @@ export interface Context<ED extends EntityDict> {
12
12
  getScene(): string | undefined;
13
13
  setScene(scene?: string): void;
14
14
  getCurrentUserId(): Promise<string | undefined>;
15
+ getHeader(key: string): string | string[] | undefined;
15
16
  }
@@ -65,8 +65,10 @@ export declare class OakRowLockedException extends OakUserException {
65
65
  */
66
66
  export declare class OakCongruentRowExists<ED extends EntityDict, T extends keyof ED> extends OakUserException {
67
67
  private data;
68
- constructor(data: ED[T]['OpSchema'], message?: string);
68
+ private entity;
69
+ constructor(entity: T, data: ED[T]['OpSchema'], message?: string);
69
70
  getData(): ED[T]["OpSchema"];
71
+ getEntity(): T;
70
72
  toString(): string;
71
73
  }
72
74
  export declare function makeException(data: {
@@ -172,19 +172,24 @@ exports.OakRowLockedException = OakRowLockedException;
172
172
  */
173
173
  var OakCongruentRowExists = /** @class */ (function (_super) {
174
174
  tslib_1.__extends(OakCongruentRowExists, _super);
175
- function OakCongruentRowExists(data, message) {
175
+ function OakCongruentRowExists(entity, data, message) {
176
176
  var _this = _super.call(this, message) || this;
177
177
  _this.data = data;
178
+ _this.entity = entity;
178
179
  return _this;
179
180
  }
180
181
  OakCongruentRowExists.prototype.getData = function () {
181
182
  return this.data;
182
183
  };
184
+ OakCongruentRowExists.prototype.getEntity = function () {
185
+ return this.entity;
186
+ };
183
187
  OakCongruentRowExists.prototype.toString = function () {
184
188
  return JSON.stringify({
185
189
  name: this.constructor.name,
186
190
  message: this.message,
187
191
  data: this.data,
192
+ entity: this.entity,
188
193
  });
189
194
  };
190
195
  return OakCongruentRowExists;
@@ -215,7 +220,7 @@ function makeException(data) {
215
220
  return new OakUnloggedInException(data.message);
216
221
  }
217
222
  case OakCongruentRowExists.name: {
218
- return new OakCongruentRowExists(data.data, data.message);
223
+ return new OakCongruentRowExists(data.entity, data.data, data.message);
219
224
  }
220
225
  case OakRowLockedException.name: {
221
226
  return new OakRowLockedException(data.message);
@@ -19,4 +19,5 @@ export declare abstract class RowStore<ED extends EntityDict, Cxt extends Contex
19
19
  abstract rollback(txnId: string): Promise<void>;
20
20
  getSchema(): StorageSchema<ED>;
21
21
  mergeOperationResult(result: OperationResult<ED>, toBeMerged: OperationResult<ED>): void;
22
+ mergeMultipleResults(toBeMerged: OperationResult<ED>[]): OperationResult<ED>;
22
23
  }
@@ -22,6 +22,12 @@ var RowStore = /** @class */ (function () {
22
22
  }
23
23
  }
24
24
  };
25
+ RowStore.prototype.mergeMultipleResults = function (toBeMerged) {
26
+ var _this = this;
27
+ var result = {};
28
+ toBeMerged.forEach(function (ele) { return _this.mergeOperationResult(result, ele); });
29
+ return result;
30
+ };
25
31
  RowStore.$$LEVEL = 'store';
26
32
  RowStore.$$CODES = {
27
33
  primaryKeyConfilict: [1, '主键重复'],
@@ -1,5 +1,6 @@
1
+ import { SelectRowShape } from ".";
1
2
  import { Context } from "./Context";
2
- import { EntityDict, OperationResult, SelectionResult } from "./Entity";
3
+ import { EntityDict, OperationResult } from "./Entity";
3
4
  declare type ActionData<ED extends EntityDict, T extends keyof ED> = ED[T]['Update']['data'] | ED[T]['Remove']['data'];
4
5
  export interface BBWatcher<ED extends EntityDict, T extends keyof ED> {
5
6
  name: string;
@@ -8,12 +9,12 @@ export interface BBWatcher<ED extends EntityDict, T extends keyof ED> {
8
9
  action: ED[T]['Operation']['action'];
9
10
  actionData: ActionData<ED, T> | (() => Promise<ActionData<ED, T>>);
10
11
  }
11
- export interface WBWatcher<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> {
12
+ export interface WBWatcher<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>, Proj extends ED[T]['Selection']['data'] = ED[T]['Selection']['data']> {
12
13
  name: string;
13
14
  entity: T;
14
15
  filter: ED[T]['Selection']['filter'] | (() => Promise<ED[T]['Selection']['filter']>);
15
- projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>);
16
- fn: (context: Cxt, data: SelectionResult<ED[T]['Schema'], Required<this['projection']>>['result']) => Promise<OperationResult<ED>>;
16
+ projection: Proj | (() => Promise<Proj>);
17
+ fn: (context: Cxt, data: SelectRowShape<ED[T]['Schema'], Proj>[]) => Promise<OperationResult<ED>>;
17
18
  }
18
19
  export declare type Watcher<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>> = BBWatcher<ED, T> | WBWatcher<ED, T, Cxt>;
19
20
  export {};
@@ -7,17 +7,17 @@ export declare class SimpleConnector<ED extends EntityDict, Cxt extends Universa
7
7
  private serverUrl;
8
8
  private makeException;
9
9
  private contextBuilder;
10
- constructor(serverUrl: string, makeException: (exceptionData: any) => OakException, contextBuilder: (str: string | undefined) => (store: RowStore<ED, Cxt>) => Cxt);
10
+ constructor(serverUrl: string, makeException: (exceptionData: any) => OakException, contextBuilder: (str: string | undefined) => (store: RowStore<ED, Cxt>) => Promise<Cxt>);
11
11
  callAspect(name: string, params: any, context: Cxt): Promise<{
12
12
  result: any;
13
13
  opRecords: OpRecord<ED>[];
14
14
  }>;
15
15
  getRouter(): string;
16
- parseRequest(headers: IncomingHttpHeaders, body: any, store: RowStore<ED, Cxt>): {
16
+ parseRequest(headers: IncomingHttpHeaders, body: any, store: RowStore<ED, Cxt>): Promise<{
17
17
  name: string;
18
18
  params: any;
19
19
  context: Cxt;
20
- };
20
+ }>;
21
21
  serializeResult(result: any, context: Cxt, headers: IncomingHttpHeaders, body: any): {
22
22
  body: any;
23
23
  headers?: Record<string, any> | undefined;
@@ -61,15 +61,26 @@ var SimpleConnector = /** @class */ (function (_super) {
61
61
  return SimpleConnector.ROUTER;
62
62
  };
63
63
  SimpleConnector.prototype.parseRequest = function (headers, body, store) {
64
- var oakCxtStr = headers["oak-cxt"], aspectName = headers["oak-aspect"];
65
- (0, assert_1.default)(typeof oakCxtStr === 'string' || oakCxtStr === undefined);
66
- (0, assert_1.default)(typeof aspectName === 'string');
67
- var context = this.contextBuilder(oakCxtStr)(store);
68
- return {
69
- name: aspectName,
70
- params: body,
71
- context: context,
72
- };
64
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
65
+ var oakCxtStr, aspectName, context;
66
+ return tslib_1.__generator(this, function (_a) {
67
+ switch (_a.label) {
68
+ case 0:
69
+ oakCxtStr = headers["oak-cxt"], aspectName = headers["oak-aspect"];
70
+ (0, assert_1.default)(typeof oakCxtStr === 'string' || oakCxtStr === undefined);
71
+ (0, assert_1.default)(typeof aspectName === 'string');
72
+ return [4 /*yield*/, this.contextBuilder(oakCxtStr)(store)];
73
+ case 1:
74
+ context = _a.sent();
75
+ context.setHeaders(headers);
76
+ return [2 /*return*/, {
77
+ name: aspectName,
78
+ params: body,
79
+ context: context,
80
+ }];
81
+ }
82
+ });
83
+ });
73
84
  };
74
85
  SimpleConnector.prototype.serializeResult = function (result, context, headers, body) {
75
86
  return {
@@ -3,6 +3,7 @@
3
3
  * 像assign, keys尽量使用Object的函数
4
4
  */
5
5
  import unset from 'lodash/unset';
6
+ import uniqBy from 'lodash/uniqBy';
6
7
  import pull from 'lodash/pull';
7
8
  import uniq from 'lodash/uniq';
8
9
  import get from 'lodash/get';
@@ -16,4 +17,4 @@ import isEqual from 'lodash/isEqual';
16
17
  import union from 'lodash/union';
17
18
  import difference from 'lodash/difference';
18
19
  import groupBy from 'lodash/groupBy';
19
- export { unset, pull, uniq, get, set, intersection, omit, merge, cloneDeep, pick, isEqual, union, difference, groupBy, };
20
+ export { unset, pull, uniq, uniqBy, get, set, intersection, omit, merge, cloneDeep, pick, isEqual, union, difference, groupBy, };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.groupBy = exports.difference = exports.union = exports.isEqual = exports.pick = exports.cloneDeep = exports.merge = exports.omit = exports.intersection = exports.set = exports.get = exports.uniq = exports.pull = exports.unset = void 0;
3
+ exports.groupBy = exports.difference = exports.union = exports.isEqual = exports.pick = exports.cloneDeep = exports.merge = exports.omit = exports.intersection = exports.set = exports.get = exports.uniqBy = exports.uniq = exports.pull = exports.unset = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  /**
6
6
  * 避免lodash打包体积过大
@@ -8,6 +8,8 @@ var tslib_1 = require("tslib");
8
8
  */
9
9
  var unset_1 = tslib_1.__importDefault(require("lodash/unset"));
10
10
  exports.unset = unset_1.default;
11
+ var uniqBy_1 = tslib_1.__importDefault(require("lodash/uniqBy"));
12
+ exports.uniqBy = uniqBy_1.default;
11
13
  var pull_1 = tslib_1.__importDefault(require("lodash/pull"));
12
14
  exports.pull = pull_1.default;
13
15
  var uniq_1 = tslib_1.__importDefault(require("lodash/uniq"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oak-domain",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "author": {
5
5
  "name": "XuChang"
6
6
  },
@@ -30,6 +30,7 @@
30
30
  "@types/uuid": "^8.3.0",
31
31
  "assert": "^2.0.0",
32
32
  "cross-env": "^7.0.2",
33
+ "cross-spawn": "^7.0.3",
33
34
  "fs-extra": "^10.0.0",
34
35
  "mocha": "^8.2.1",
35
36
  "ts-node": "~10.9.1",