oak-domain 5.1.8 → 5.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.
@@ -160,7 +160,7 @@ function pushStatementIntoSchemaAst(moduleName, statement, sourceFile) {
160
160
  */
161
161
  function checkActionDefNameConsistent(filename, actionDefNode) {
162
162
  const { name, type } = actionDefNode;
163
- (0, assert_1.default)(ts.isTypeReferenceNode(type));
163
+ (0, assert_1.default)(ts.isTypeReferenceNode(type), "ActionDef应该是一个类型引用");
164
164
  const { typeArguments } = type;
165
165
  (0, assert_1.default)(typeArguments.length === 2);
166
166
  const [actionNode, stateNode] = typeArguments;
@@ -189,13 +189,13 @@ function addImportedFrom(moduleName, name, node) {
189
189
  let propertyName;
190
190
  if (typeof node === 'object') {
191
191
  const { moduleSpecifier, importClause } = node;
192
- (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier));
193
- (0, assert_1.default)(importClause);
192
+ (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier), `${moduleName}中的${name}未引用正确的moduleSpecifier`);
193
+ (0, assert_1.default)(importClause, `${moduleName}中的${name}未引用正确的importClause`);
194
194
  const { namedBindings } = importClause;
195
- (0, assert_1.default)(namedBindings);
195
+ (0, assert_1.default)(namedBindings, `${moduleName}中的${name}未引用正确的namedBindings`);
196
196
  (0, assert_1.default)(ts.isNamedImports(namedBindings));
197
197
  const importSpecifier = namedBindings.elements.find((ele) => ele.name.text === name);
198
- (0, assert_1.default)(importSpecifier);
198
+ (0, assert_1.default)(importSpecifier, `${moduleName}中的${name}未引用正确的importSpecifier`);
199
199
  propertyName = importSpecifier.propertyName && importSpecifier.propertyName.text;
200
200
  importFrom = moduleSpecifier.text;
201
201
  }
@@ -210,7 +210,7 @@ function addImportedFrom(moduleName, name, node) {
210
210
  });
211
211
  }
212
212
  else {
213
- (0, assert_1.default)(name.endsWith("State"));
213
+ (0, assert_1.default)(name.endsWith("State"), `${moduleName}中的${name}未以State结尾`);
214
214
  (0, lodash_1.assign)(ast.importStateFrom, {
215
215
  [name]: [importFrom, propertyName],
216
216
  });
@@ -226,15 +226,15 @@ function analyzeExternalAttrImport(node, program, importAttrFrom, relativePath)
226
226
  if (ts.isImportSpecifier(declaration)) {
227
227
  const name = declaration.name.text;
228
228
  const importDeclartion = declaration.parent.parent.parent;
229
- (0, assert_1.default)(ts.isImportDeclaration(importDeclartion));
229
+ (0, assert_1.default)(ts.isImportDeclaration(importDeclartion), `未找到${name}的importDeclaration`);
230
230
  const { moduleSpecifier, importClause } = importDeclartion;
231
- (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier));
232
- (0, assert_1.default)(importClause);
231
+ (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier), `未找到${name}的moduleSpecifier`);
232
+ (0, assert_1.default)(importClause, `未找到${name}的importClause`);
233
233
  const { namedBindings } = importClause;
234
- (0, assert_1.default)(namedBindings);
235
- (0, assert_1.default)(ts.isNamedImports(namedBindings));
234
+ (0, assert_1.default)(namedBindings, `未找到${name}的namedBindings`);
235
+ (0, assert_1.default)(ts.isNamedImports(namedBindings), `未找到${name}的namedImports`);
236
236
  const importSpecifier = namedBindings.elements.find((ele) => ele.name.text === name);
237
- (0, assert_1.default)(importSpecifier);
237
+ (0, assert_1.default)(importSpecifier, `未找到${name}的importSpecifier`);
238
238
  const propertyName = importSpecifier.propertyName && importSpecifier.propertyName.text;
239
239
  const importFrom = moduleSpecifier.text;
240
240
  const importFromRelatively = importFrom.startsWith('.') ? (relativePath
@@ -282,7 +282,7 @@ function tryGetStringLiteralValues(moduleName, filename, obj, node, program) {
282
282
  if (['state', 'action'].includes(obj)) {
283
283
  (0, assert_1.default)(values.length > 0, `${filename}中的${obj} ${node.typeName.getText()}未定义`);
284
284
  const importDeclartion = declaration.parent.parent.parent;
285
- (0, assert_1.default)(ts.isImportDeclaration(importDeclartion));
285
+ (0, assert_1.default)(ts.isImportDeclaration(importDeclartion), '未找到importDeclaration');
286
286
  addImportedFrom(moduleName, declaration.name.text, importDeclartion);
287
287
  }
288
288
  }
@@ -307,7 +307,7 @@ function tryGetStringLiteralValues(moduleName, filename, obj, node, program) {
307
307
  values.push(action);
308
308
  }
309
309
  if (['state', 'action'].includes(obj)) {
310
- (0, assert_1.default)(values.length > 0);
310
+ (0, assert_1.default)(values.length > 0, `${filename}中的${obj} ${node.typeName.getText()}未定义`);
311
311
  const ast = ActionAsts[moduleName];
312
312
  addImportedFrom(moduleName, declaration.name.text, './');
313
313
  }
@@ -340,8 +340,9 @@ function dealWithActionTypeNode(moduleName, filename, actionTypeNode, program, s
340
340
  (0, assert_1.default)((0, lodash_1.intersection)(actionNames, RESERVED_ACTION_NAMES).length === 0, `${filename}中的Action命名不能是「${RESERVED_ACTION_NAMES.join(',')}」之一`);
341
341
  actionTypeNode.types.forEach(ele => {
342
342
  if (ts.isTypeReferenceNode(ele)) {
343
+ // 这里递归了类型定义,去查找所有的action字符串
343
344
  const actionStrings = tryGetStringLiteralValues(moduleName, filename, 'action', ele, program);
344
- (0, assert_1.default)(actionStrings.length > 0);
345
+ (0, assert_1.default)(actionStrings.length > 0, `${filename}中的Action所引用的Type定义为空`);
345
346
  actionTexts.push(...actionStrings);
346
347
  }
347
348
  else {
@@ -355,7 +356,7 @@ function dealWithActionTypeNode(moduleName, filename, actionTypeNode, program, s
355
356
  (0, assert_1.default)(!RESERVED_ACTION_NAMES.includes(actionTypeNode.typeName.text), `${filename}中的Action命名不能是「${RESERVED_ACTION_NAMES.join(',')}」之一`);
356
357
  }
357
358
  const actionStrings = tryGetStringLiteralValues(moduleName, filename, 'action', actionTypeNode, program);
358
- (0, assert_1.default)(actionStrings.length > 0);
359
+ (0, assert_1.default)(actionStrings.length > 0, `${filename}中的Action定义为空`);
359
360
  actionTexts.push(...actionStrings);
360
361
  }
361
362
  else {
@@ -383,10 +384,10 @@ function dealWithActionDefInitializer(moduleName, initializer, program) {
383
384
  // 是从别处的引用,注入到mportActionDefFrom
384
385
  const checker = program.getTypeChecker();
385
386
  const identifier = ts.isIdentifier(initializer) ? initializer : initializer.expression;
386
- (0, assert_1.default)(ts.isIdentifier(identifier));
387
+ (0, assert_1.default)(ts.isIdentifier(identifier), "ActionDef的initializer不是一个Identifier");
387
388
  const symbol = checker.getSymbolAtLocation(identifier);
388
389
  const declaration = symbol?.getDeclarations()[0];
389
- (0, assert_1.default)(ts.isImportSpecifier(declaration));
390
+ (0, assert_1.default)(ts.isImportSpecifier(declaration), "ActionDef的initializer不是一个ImportSpecifier");
390
391
  const importDeclartion = declaration.parent.parent.parent;
391
392
  addImportedFrom(moduleName, identifier.text, importDeclartion);
392
393
  }
@@ -419,7 +420,7 @@ function getEntityImported(declaration) {
419
420
  function checkLocaleEnumAttrs(node, attrs, filename) {
420
421
  const { members } = node;
421
422
  const memberKeys = members.map((ele) => {
422
- (0, assert_1.default)(ts.isPropertySignature(ele) && ts.isIdentifier(ele.name));
423
+ (0, assert_1.default)(ts.isPropertySignature(ele) && ts.isIdentifier(ele.name), 'locale定义中的属性必须是identifier');
423
424
  return ele.name.text;
424
425
  });
425
426
  const lack = (0, lodash_1.difference)(attrs, memberKeys);
@@ -433,7 +434,7 @@ function checkLocaleExpressionPropertyExists(root, attr, exists, filename) {
433
434
  (0, assert_1.default)(ts.isPropertyAssignment(ele) && (ts.isIdentifier(ele.name) || ts.isStringLiteral(ele.name)) && ts.isObjectLiteralExpression(ele.initializer));
434
435
  const { properties: p2 } = ele.initializer;
435
436
  const pp = p2.find((ele2) => {
436
- (0, assert_1.default)(ts.isPropertyAssignment(ele2) && ts.isIdentifier(ele2.name));
437
+ (0, assert_1.default)(ts.isPropertyAssignment(ele2) && ts.isIdentifier(ele2.name), 'locale定义中的属性必须是identifier');
437
438
  return ele2.name.text === attr;
438
439
  });
439
440
  if (exists && !pp) {
@@ -565,6 +566,38 @@ function analyzeImportDeclaration(node, referencedSchemas, additionalImports, fi
565
566
  } */
566
567
  }
567
568
  }
569
+ /**
570
+ * 处理模块的导入,得到导入文件的sourcefile
571
+ */
572
+ function dealImportedFile(path, fileSpecifierPath, filename, program) {
573
+ let importedFilepath = '';
574
+ const getExistedFileName = () => {
575
+ if ((0, fs_1.existsSync)(`${importedFilepath}.ts`)) {
576
+ return `${importedFilepath}.ts`;
577
+ }
578
+ else if ((0, fs_1.existsSync)(`${importedFilepath}.d.ts`)) {
579
+ return `${importedFilepath}.d.ts`;
580
+ }
581
+ return '';
582
+ };
583
+ if (fileSpecifierPath.startsWith('.')) {
584
+ importedFilepath = path_1.default.join(path, fileSpecifierPath);
585
+ const importedFilename = getExistedFileName();
586
+ (0, assert_1.default)(importedFilename, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
587
+ const sourceFile = program.getSourceFile(importedFilename);
588
+ (0, assert_1.default)(sourceFile, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
589
+ return [sourceFile, importedFilename];
590
+ }
591
+ // 创建编译器主机
592
+ const compilerHost = ts.createCompilerHost(program.getCompilerOptions());
593
+ // 解析模块
594
+ const resolvedModule = ts.resolveModuleName(fileSpecifierPath, filename, program.getCompilerOptions(), compilerHost);
595
+ (0, assert_1.default)(resolvedModule.resolvedModule, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
596
+ const pathName = resolvedModule.resolvedModule.resolvedFileName;
597
+ const sourceFile = program.getSourceFile(pathName);
598
+ (0, assert_1.default)(sourceFile, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
599
+ return [sourceFile, pathName];
600
+ }
568
601
  /**
569
602
  * 在path下的filename文件中import了fileSpecifierPath,要找到其对应的引用路径
570
603
  * 这里关键是要处理形如file:的依赖声明
@@ -594,7 +627,7 @@ function analyzeImportDeclaration(node, referencedSchemas, additionalImports, fi
594
627
  // const cwd = process.cwd();
595
628
  // const fileSpecifierPaths = fileSpecifierPath.split('/');
596
629
  // const moduleName = fileSpecifierPaths[0] || fileSpecifierPaths[1];
597
- // assert(moduleName);
630
+ // assert(moduleName, '「${filename}」中import路径不合法');
598
631
  // // 从path向外找package.json -> node_modules直至找到fileSpecifier
599
632
  // const paths = path.split('/');
600
633
  // for (let iter = paths.length; iter >= 0; iter--) {
@@ -628,37 +661,28 @@ function analyzeSchemaDefinition(node, moduleName, filename, path, program, refe
628
661
  let toLog = false;
629
662
  const extendsFrom = [];
630
663
  const { members, heritageClauses } = node;
631
- (0, assert_1.default)(heritageClauses);
664
+ (0, assert_1.default)(heritageClauses, `「${filename}」中的Schema定义需要继承EntityShape或者其他Entity`);
632
665
  const heritagedResult = heritageClauses.map((clause) => {
633
666
  const { expression } = clause.types[0];
634
- (0, assert_1.default)(ts.isIdentifier(expression));
667
+ (0, assert_1.default)(ts.isIdentifier(expression), `${expression}不是一个合法的继承类型`);
635
668
  if (expression.text === 'EntityShape') {
636
669
  // import { EntityShape } from 'oak-domain/lib/types/Entities; 所有schema的公共祖先类型,不用处理
637
670
  return;
638
671
  }
639
672
  // 从其它文件的Schema类继承,这里需要将所继承的对象的属性进行访问并展开
640
- (0, assert_1.default)(referencedSchemas.includes(expression.text));
673
+ (0, assert_1.default)(referencedSchemas.includes(expression.text), `「${filename}」中的Schema继承了未定义的实体「${expression.text}」`);
641
674
  const checker = program.getTypeChecker();
642
675
  const symbol = checker.getSymbolAtLocation(expression);
643
676
  let declaration = symbol?.getDeclarations()[0];
644
- (0, assert_1.default)(ts.isImportSpecifier(declaration));
677
+ (0, assert_1.default)(ts.isImportSpecifier(declaration), `${declaration.getText()}应该是导入的类型`);
645
678
  const importDeclaration = declaration.parent.parent.parent;
646
- (0, assert_1.default)(ts.isImportDeclaration(importDeclaration));
679
+ (0, assert_1.default)(ts.isImportDeclaration(importDeclaration), `${declaration.getText()}应该是导入的类型`);
647
680
  const { moduleSpecifier } = importDeclaration;
648
- (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier));
681
+ (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier), `${declaration.getText()}应该是导入的类型`);
649
682
  const { text: from } = moduleSpecifier;
650
683
  extendsFrom.push(from);
651
- // 创建编译器主机
652
- const compilerHost = ts.createCompilerHost(program.getCompilerOptions());
653
- // 解析模块
654
- const resolvedModule = ts.resolveModuleName(from, filename, program.getCompilerOptions(), compilerHost);
655
- (0, assert_1.default)(resolvedModule.resolvedModule, "找不到module定义");
656
- const resolvedFileName = resolvedModule.resolvedModule.resolvedFileName;
657
- const sourceFile = program.getSourceFile(resolvedFileName);
658
- // const importedFilename = getImportedFilePath(path, from, filename);
659
- // const sourceFile = program.getSourceFile(importedFilename);
660
- (0, assert_1.default)(sourceFile, `「${filename}」找不到相应的sourceFile:${resolvedFileName}`);
661
- const relativeFilename = path_1.default.relative(process.cwd(), resolvedFileName);
684
+ const [sourceFile, pathName] = dealImportedFile(path, from, filename, program);
685
+ const relativeFilename = path_1.default.relative(process.cwd(), pathName);
662
686
  const result = analyzeReferenceSchemaFile(moduleName, path_1.default.basename(relativeFilename), path_1.default.dirname(relativeFilename), sourceFile, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, path_1.default.join(from, '..'));
663
687
  return result;
664
688
  }).filter(ele => !!ele);
@@ -738,7 +762,7 @@ function analyzeSchemaDefinition(node, moduleName, filename, path, program, refe
738
762
  else {
739
763
  schemaAttrs.push(attrNode);
740
764
  if (ts.isUnionTypeNode(type) && ts.isLiteralTypeNode(type.types[0]) && ts.isStringLiteral(type.types[0].literal)) {
741
- (0, assert_1.default)(ts.isIdentifier(name));
765
+ (0, assert_1.default)(ts.isIdentifier(name), `「${filename}」中的属性定义不是String类型`);
742
766
  const { types } = type;
743
767
  const enumValues = types.map((ele) => checkStringLiteralLegal(filename, '属性', name.text, ele));
744
768
  enumAttributes[name.text] = enumValues;
@@ -833,13 +857,13 @@ function analyzeReferenceSchemaFile(moduleName, filename, path, sourceFile, prog
833
857
  }
834
858
  }
835
859
  });
836
- (0, assert_1.default)(result);
860
+ (0, assert_1.default)(result, `「${filename}」中没有找到Schema定义`);
837
861
  return result;
838
862
  }
839
863
  function analyzeEntity(filename, path, program, relativePath) {
840
864
  const fullPath = `${path}/${filename}`;
841
865
  const sourceFile = program.getSourceFile(fullPath);
842
- (0, assert_1.default)(sourceFile);
866
+ (0, assert_1.default)(sourceFile, `「${filename}」文件不存在`);
843
867
  const moduleName = filename.split('.')[0];
844
868
  if (Schema.hasOwnProperty(moduleName)) {
845
869
  delete ActionAsts[moduleName];
@@ -926,13 +950,13 @@ function analyzeEntity(filename, path, program, relativePath) {
926
950
  (0, assert_1.default)(!localeDef, `【${filename}】locale定义须在Relation之后`);
927
951
  const relationValues = [];
928
952
  if (ts.isLiteralTypeNode(node.type)) {
929
- (0, assert_1.default)(ts.isStringLiteral(node.type.literal));
953
+ (0, assert_1.default)(ts.isStringLiteral(node.type.literal), `${filename}中的Relation的定义只能是string类型`);
930
954
  (0, assert_1.default)(node.type.literal.text.length < env_1.STRING_LITERAL_MAX_LENGTH, `Relation定义的字符串长度不长于${env_1.STRING_LITERAL_MAX_LENGTH}(${filename},${node.type.literal.text})`);
931
955
  relationValues.push(node.type.literal.text);
932
956
  }
933
957
  else if (ts.isTypeReferenceNode(node.type)) {
934
958
  const relationStrings = tryGetStringLiteralValues(moduleName, filename, 'relation', node.type, program);
935
- (0, assert_1.default)(relationStrings.length > 0);
959
+ (0, assert_1.default)(relationStrings.length > 0, `文件${filename}中的relation${node.type.typeName.text}定义未找到字符串类型`);
936
960
  relationValues.push(...relationStrings);
937
961
  }
938
962
  else {
@@ -946,7 +970,7 @@ function analyzeEntity(filename, path, program, relativePath) {
946
970
  else {
947
971
  (0, assert_1.default)(ts.isTypeReferenceNode(ele), `Relation的定义只能是string类型,或者string union类型,或者两者的union(${filename})`);
948
972
  const relationStrings = tryGetStringLiteralValues(moduleName, filename, 'relation', ele, program);
949
- (0, assert_1.default)(relationStrings.length > 0);
973
+ (0, assert_1.default)(relationStrings.length > 0, `文件${filename}中的relation${ele.typeName.text}定义未找到字符串类型`);
950
974
  relationValues.push(...relationStrings);
951
975
  }
952
976
  });
@@ -998,7 +1022,7 @@ function analyzeEntity(filename, path, program, relativePath) {
998
1022
  ]) : type), sourceFile);
999
1023
  }
1000
1024
  else {
1001
- (0, assert_1.default)(ts.isLiteralTypeNode(type) || ts.isTypeReferenceNode(type), `${moduleName} - ${node.name}`);
1025
+ (0, assert_1.default)(ts.isLiteralTypeNode(type) || ts.isTypeReferenceNode(type), `文件${filename}中的${type.getText()}应该是字面量或引用类型`);
1002
1026
  pushStatementIntoActionAst(moduleName, factory.updateTypeAliasDeclaration(node, [factory.createModifier(ts.SyntaxKind.ExportKeyword)], node.name, node.typeParameters, process.env.COMPLING_AS_LIB ? factory.createUnionTypeNode([
1003
1027
  type,
1004
1028
  factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
@@ -1015,12 +1039,12 @@ function analyzeEntity(filename, path, program, relativePath) {
1015
1039
  const dealWithActionDef = (declaration) => {
1016
1040
  checkActionDefNameConsistent(filename, declaration);
1017
1041
  const { typeArguments } = declaration.type;
1018
- (0, assert_1.default)(typeArguments.length === 2);
1042
+ (0, assert_1.default)(typeArguments.length === 2, `文件${filename}中的action定义不是两个泛型参数`);
1019
1043
  const [actionNode, stateNode] = typeArguments;
1020
- (0, assert_1.default)(ts.isTypeReferenceNode(actionNode));
1044
+ (0, assert_1.default)(ts.isTypeReferenceNode(actionNode), `文件${filename}中的action定义不是TypeReferenceNode`);
1021
1045
  // 这里有可能引用的Action不是本文件的定义,要调用这个函数加到importFrom中
1022
1046
  tryGetStringLiteralValues(moduleName, filename, 'action', actionNode, program);
1023
- (0, assert_1.default)(ts.isTypeReferenceNode(stateNode));
1047
+ (0, assert_1.default)(ts.isTypeReferenceNode(stateNode), `文件${filename}中的action定义不是TypeReferenceNode`);
1024
1048
  const enumStateValues = tryGetStringLiteralValues(moduleName, filename, 'state', stateNode, program);
1025
1049
  (0, assert_1.default)(enumStateValues.length > 0, `文件${filename}中的state${stateNode.typeName.text}定义不是字符串类型`);
1026
1050
  pushStatementIntoActionAst(moduleName, node, sourceFile);
@@ -1037,18 +1061,18 @@ function analyzeEntity(filename, path, program, relativePath) {
1037
1061
  const { elements } = declaration;
1038
1062
  elements.forEach((ele) => {
1039
1063
  let isFulltextIndex = false;
1040
- (0, assert_1.default)(ts.isObjectLiteralExpression(ele));
1064
+ (0, assert_1.default)(ts.isObjectLiteralExpression(ele), `「${filename}」中索引定义应该是对象字面量`);
1041
1065
  const { properties } = ele;
1042
1066
  const attrProperty = properties.find((ele2) => {
1043
- (0, assert_1.default)(ts.isPropertyAssignment(ele2));
1067
+ (0, assert_1.default)(ts.isPropertyAssignment(ele2), `「${filename}」中索引的属性不为PropertyAssignment`);
1044
1068
  return ele2.name.getText() === 'attributes';
1045
1069
  });
1046
- (0, assert_1.default)(ts.isArrayLiteralExpression(attrProperty.initializer));
1070
+ (0, assert_1.default)(ts.isArrayLiteralExpression(attrProperty.initializer), `「${filename}」中索引的attributes属性应该是数组字面量`);
1047
1071
  const nameProperty = properties.find((ele2) => {
1048
1072
  (0, assert_1.default)(ts.isPropertyAssignment(ele2));
1049
1073
  return ele2.name.getText() === 'name';
1050
1074
  });
1051
- (0, assert_1.default)(ts.isStringLiteral(nameProperty.initializer));
1075
+ (0, assert_1.default)(ts.isStringLiteral(nameProperty.initializer), '「${filename}」中索引的name属性应该是字符串字面量');
1052
1076
  const nameText = nameProperty.initializer.text;
1053
1077
  if (indexNameDict[nameText]) {
1054
1078
  throw new Error(`「${filename}」索引定义重名「${nameText}」`);
@@ -1057,14 +1081,14 @@ function analyzeEntity(filename, path, program, relativePath) {
1057
1081
  [nameText]: true,
1058
1082
  });
1059
1083
  const configProperty = properties.find((ele2) => {
1060
- (0, assert_1.default)(ts.isPropertyAssignment(ele2));
1084
+ (0, assert_1.default)(ts.isPropertyAssignment(ele2), `「${filename}」中索引的属性不为PropertyAssignment`);
1061
1085
  return ele2.name.getText() === 'config';
1062
1086
  });
1063
1087
  if (configProperty) {
1064
- (0, assert_1.default)(ts.isObjectLiteralExpression(configProperty.initializer));
1088
+ (0, assert_1.default)(ts.isObjectLiteralExpression(configProperty.initializer), `「${filename}」中索引的config属性应该是对象字面量`);
1065
1089
  const { properties: properties2 } = configProperty.initializer;
1066
1090
  const typeProperty = properties2.find((ele2) => {
1067
- (0, assert_1.default)(ts.isPropertyAssignment(ele2));
1091
+ (0, assert_1.default)(ts.isPropertyAssignment(ele2), `「${filename}」中索引的属性不为PropertyAssignment`);
1068
1092
  return ele2.name.getText() === 'type';
1069
1093
  });
1070
1094
  if (typeProperty && typeProperty.initializer.text === 'fulltext') {
@@ -1179,21 +1203,21 @@ function analyzeEntity(filename, path, program, relativePath) {
1179
1203
  if (ts.isObjectLiteralExpression(declaration)) {
1180
1204
  const { properties } = declaration;
1181
1205
  const localesProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'locales');
1182
- (0, assert_1.default)(ts.isPropertyAssignment(localesProperty));
1206
+ (0, assert_1.default)(ts.isPropertyAssignment(localesProperty), `「${filename}」中entityDesc的locales应该是属性声明`);
1183
1207
  dealWithLocales(localesProperty.initializer);
1184
1208
  const indexesProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'indexes');
1185
1209
  if (indexesProperty) {
1186
- (0, assert_1.default)(ts.isPropertyAssignment(indexesProperty));
1210
+ (0, assert_1.default)(ts.isPropertyAssignment(indexesProperty), `「${filename}」中entityDesc的indexes应该是属性声明`);
1187
1211
  dealWithIndexes(indexesProperty.initializer);
1188
1212
  }
1189
1213
  const configurationProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'configuration');
1190
1214
  if (configurationProperty) {
1191
- (0, assert_1.default)(ts.isPropertyAssignment(configurationProperty));
1215
+ (0, assert_1.default)(ts.isPropertyAssignment(configurationProperty), `「${filename}」中entityDesc的configuration应该是属性声明`);
1192
1216
  dealWithConfiguration(configurationProperty.initializer);
1193
1217
  }
1194
1218
  const styleDescProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'style');
1195
1219
  if (styleDescProperty) {
1196
- (0, assert_1.default)(ts.isPropertyAssignment(styleDescProperty));
1220
+ (0, assert_1.default)(ts.isPropertyAssignment(styleDescProperty), `「${filename}」中entityDesc的style应该是属性声明`);
1197
1221
  dealWithStyleDesc(styleDescProperty.initializer);
1198
1222
  }
1199
1223
  }
@@ -1224,14 +1248,14 @@ function analyzeEntity(filename, path, program, relativePath) {
1224
1248
  && declaration.type.typeArguments[0].typeName.text === 'Index')) {
1225
1249
  // 对索引Index的定义
1226
1250
  console.log(`「${filename}」直接定义indexes的写法已经过时,请定义在entityDesc中`);
1227
- (0, assert_1.default)(ts.isArrayLiteralExpression(declaration.initializer));
1251
+ (0, assert_1.default)(ts.isArrayLiteralExpression(declaration.initializer), `「${filename}」中索引定义应该是数组字面量`);
1228
1252
  dealWithIndexes(declaration.initializer);
1229
1253
  }
1230
1254
  else if (declaration.type && ts.isTypeReferenceNode(declaration.type) && ts.isIdentifier(declaration.type.typeName) && declaration.type.typeName.text === 'LocaleDef') {
1231
1255
  // locale定义
1232
1256
  console.log(`「${filename}」直接定义locales的写法已经过时,请定义在entityDesc中`);
1233
1257
  const { type, initializer } = declaration;
1234
- (0, assert_1.default)(ts.isObjectLiteralExpression(initializer));
1258
+ (0, assert_1.default)(ts.isObjectLiteralExpression(initializer), `「${filename}」中locale定义应该是对象字面量`);
1235
1259
  const { properties } = initializer;
1236
1260
  (0, assert_1.default)(properties.length > 0, `${filename}至少需要有一种locale定义`);
1237
1261
  const allEnumStringAttrs = Object.keys(enumAttributes);
@@ -1268,12 +1292,12 @@ function analyzeEntity(filename, path, program, relativePath) {
1268
1292
  }
1269
1293
  else if (declaration.type && ts.isTypeReferenceNode(declaration.type) && ts.isIdentifier(declaration.type.typeName) && declaration.type.typeName.text === 'Configuration') {
1270
1294
  console.log(`「${filename}」直接定义configuration的写法已经过时,请定义在entityDesc中`);
1271
- (0, assert_1.default)(ts.isObjectLiteralExpression(declaration.initializer));
1295
+ (0, assert_1.default)(ts.isObjectLiteralExpression(declaration.initializer), `「${filename}」中configuration定义应该是对象字面量`);
1272
1296
  dealWithConfiguration(declaration.initializer);
1273
1297
  }
1274
1298
  else if (declaration.type && ts.isTypeReferenceNode(declaration.type) && ts.isIdentifier(declaration.type.typeName) && declaration.type.typeName.text === 'EntityDesc') {
1275
1299
  const { initializer } = declaration;
1276
- (0, assert_1.default)(initializer);
1300
+ (0, assert_1.default)(initializer, `「${filename}」中entityDesc的定义不应该为空`);
1277
1301
  dealWithEntityDesc(initializer);
1278
1302
  }
1279
1303
  else {
@@ -1617,7 +1641,7 @@ function constructFilter(statements, entity) {
1617
1641
  }
1618
1642
  else {
1619
1643
  // 此时应当是引用本地定义的shape
1620
- (0, assert_1.default)(type);
1644
+ (0, assert_1.default)(type, `${entity}中的属性${name.toString()}有非法的属性类型定义`);
1621
1645
  members.push(factory.createPropertySignature(undefined, name, undefined, factory.createTypeReferenceNode(factory.createIdentifier('JsonFilter'), [
1622
1646
  type
1623
1647
  ])));
@@ -3118,7 +3142,7 @@ function outputSchema(outputDir, printer) {
3118
3142
  const fromLocalActionSpecifiers = ['Action', 'ParticularAction'];
3119
3143
  const fromExtenalStates = {};
3120
3144
  for (const state in importStateFrom) {
3121
- (0, assert_1.default)(state.endsWith('State'));
3145
+ (0, assert_1.default)(state.endsWith('State'), `${state} should end with State`);
3122
3146
  if (importStateFrom[state][0] === './') {
3123
3147
  // 本地定义的State从 ./Action 中获取
3124
3148
  fromLocalActionSpecifiers.push(state);
@@ -3247,7 +3271,7 @@ function outputAction(outputDir, printer) {
3247
3271
  const importStatements = [];
3248
3272
  const fromExternalImports = {};
3249
3273
  for (const state in importStateFrom) {
3250
- (0, assert_1.default)(state.endsWith('State'));
3274
+ (0, assert_1.default)(state.endsWith('State'), `${state} should end with State`);
3251
3275
  const [from, propertyName] = importStateFrom[state];
3252
3276
  if (from !== './') {
3253
3277
  if (fromExternalImports[from]) {
@@ -3259,7 +3283,7 @@ function outputAction(outputDir, printer) {
3259
3283
  }
3260
3284
  }
3261
3285
  for (const action in importActionFrom) {
3262
- (0, assert_1.default)(action.endsWith('Action'));
3286
+ (0, assert_1.default)(action.endsWith('Action'), `${action} should end with Action`);
3263
3287
  const [from, propertyName] = importActionFrom[action];
3264
3288
  if (from !== './') {
3265
3289
  if (fromExternalImports[from]) {
@@ -3271,7 +3295,7 @@ function outputAction(outputDir, printer) {
3271
3295
  }
3272
3296
  }
3273
3297
  for (const def in importActionDefFrom) {
3274
- (0, assert_1.default)(def.endsWith('ActionDef'));
3298
+ (0, assert_1.default)(def.endsWith('ActionDef'), `${def} should end with ActionDef`);
3275
3299
  const [from, propertyName] = importActionDefFrom[def];
3276
3300
  if (from !== './') {
3277
3301
  if (fromExternalImports[from]) {
@@ -3413,11 +3437,11 @@ function constructAttributes(entity) {
3413
3437
  if (ts.isUnionTypeNode(type)) {
3414
3438
  if (ts.isLiteralTypeNode(type.types[0])) {
3415
3439
  if (ts.isStringLiteral(type.types[0].literal)) {
3416
- (0, assert_1.default)(enumAttributes && enumAttributes[name.text]);
3440
+ (0, assert_1.default)(enumAttributes && enumAttributes[name.text], `${entity}对象中的${name.text}属性没有定义enumAttributes`);
3417
3441
  attrAssignments.push(factory.createPropertyAssignment('type', factory.createStringLiteral("enum")), factory.createPropertyAssignment('enumeration', factory.createArrayLiteralExpression(enumAttributes[name.text].map(ele => factory.createStringLiteral(ele)))));
3418
3442
  }
3419
3443
  else {
3420
- (0, assert_1.default)(ts.isNumericLiteral(type.types[0].literal));
3444
+ (0, assert_1.default)(ts.isNumericLiteral(type.types[0].literal), `${entity}对象中的${type.types[0].literal.getText()}属性不是数字`);
3421
3445
  attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("int")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
3422
3446
  factory.createPropertyAssignment(factory.createIdentifier("width"), factory.createNumericLiteral(env_1.INT_LITERL_DEFAULT_WIDTH))
3423
3447
  ], true)));
@@ -3434,7 +3458,7 @@ function constructAttributes(entity) {
3434
3458
  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)));
3435
3459
  }
3436
3460
  else {
3437
- (0, assert_1.default)(ts.isNumericLiteral(type.literal));
3461
+ (0, assert_1.default)(ts.isNumericLiteral(type.literal), `${entity}对象中的${name.text}属性不是数字`);
3438
3462
  attrAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("type"), factory.createStringLiteral("precision")), factory.createPropertyAssignment(factory.createIdentifier("params"), factory.createObjectLiteralExpression([
3439
3463
  factory.createPropertyAssignment(factory.createIdentifier("precision"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_PRECISION)),
3440
3464
  factory.createPropertyAssignment(factory.createIdentifier("scale"), factory.createNumericLiteral(env_1.NUMERICAL_LITERL_DEFAULT_SCALE))
@@ -3459,7 +3483,7 @@ function outputLocale(outputDir, printer) {
3459
3483
  if (locale) {
3460
3484
  const { properties } = locale;
3461
3485
  properties.forEach((ele) => {
3462
- (0, assert_1.default)(ts.isPropertyAssignment(ele) && (ts.isIdentifier(ele.name) || ts.isStringLiteral(ele.name)) && ts.isObjectLiteralExpression(ele.initializer));
3486
+ (0, assert_1.default)(ts.isPropertyAssignment(ele) && (ts.isIdentifier(ele.name) || ts.isStringLiteral(ele.name)) && ts.isObjectLiteralExpression(ele.initializer), `${entity}对象中的locale属性定义不正确`);
3463
3487
  const lng = ele.name.text;
3464
3488
  const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray([
3465
3489
  factory.createReturnStatement(ele.initializer)
@@ -269,7 +269,7 @@ function cascadelyCheckUpdateFilters(entity, schema, data, filter, matrix, restA
269
269
  * 先找到能直接更新成功的属性
270
270
  */
271
271
  const legalAttrResult = restAttrs.map((attr) => {
272
- const { filter: f } = matrix[attr];
272
+ const { filter: f } = matrix[attr] || {};
273
273
  if (!f) {
274
274
  return true;
275
275
  }
@@ -1621,7 +1621,7 @@ function checkDeduceFilters(dfc, context) {
1621
1621
  * @returns
1622
1622
  */
1623
1623
  function checkFilterContains(entity, context, contained, filter, dataCompare, warningOnDataCompare) {
1624
- (0, assert_1.default)(filter);
1624
+ (0, assert_1.default)(filter, `对${entity}的访问必须有filter`);
1625
1625
  const schema = context.getSchema();
1626
1626
  const result = contains(entity, schema, filter, contained);
1627
1627
  if (typeof result === 'boolean') {
@@ -29,7 +29,7 @@ export type ServerConfiguration = {
29
29
  socketPath: string;
30
30
  };
31
31
  cors?: {
32
- origin: string;
32
+ origin: string | string[];
33
33
  headers?: string[];
34
34
  methods?: string[];
35
35
  };
@@ -42,10 +42,10 @@ export type AccessConfiguration = {
42
42
  routerPrefixes?: {
43
43
  aspect?: string;
44
44
  endpoint?: string;
45
- subscribe?: string;
46
45
  getSubscribePoint?: string;
47
46
  bridge?: string;
48
47
  };
48
+ socketPath?: string;
49
49
  http: {
50
50
  hostname: string;
51
51
  port?: number;
@@ -26,10 +26,11 @@ export interface Connector<ED extends EntityDict & BaseEntityDict, FrontCxt exte
26
26
  };
27
27
  headers?: Record<string, any>;
28
28
  };
29
- getSubscribeRouter: () => string;
30
- getSubscribePointRouter: () => string;
31
- getSubscribePoint: () => Promise<{
32
- url: string;
29
+ getSocketPath: () => string;
30
+ getSocketPointRouter: () => string;
31
+ getSocketPoint: () => Promise<{
32
+ socketUrl: string;
33
+ subscribeUrl: string;
33
34
  path: string;
34
35
  }>;
35
36
  getBridgeRouter: () => string;
@@ -1,18 +1,21 @@
1
1
  import { RecurrenceRule, RecurrenceSpecDateRange, RecurrenceSpecObjLit } from 'node-schedule';
2
- import { EntityDict } from './Entity';
2
+ import { EntityDict, OperationResult } from './Entity';
3
3
  import { EntityDict as BaseEntityDict } from '../base-app-domain';
4
4
  import { AsyncContext } from '../store/AsyncRowStore';
5
5
  import { Watcher } from './Watcher';
6
- import { OperationResult } from '.';
7
- type FreeOperateFn<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> = (context: Cxt) => Promise<OperationResult<ED>>;
6
+ import { Namespace } from 'socket.io';
7
+ type FreeRoutineFn<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> = (context: Cxt, env: {
8
+ socket: Namespace;
9
+ }) => Promise<OperationResult<ED>>;
10
+ type FreeTimerFn<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> = (context: Cxt) => Promise<OperationResult<ED>>;
8
11
  export type FreeRoutine<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> = {
9
12
  name: string;
10
- routine: FreeOperateFn<ED, Cxt>;
13
+ routine: FreeRoutineFn<ED, Cxt>;
11
14
  };
12
15
  export type FreeTimer<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> = {
13
16
  name: string;
14
17
  cron: RecurrenceRule | RecurrenceSpecDateRange | RecurrenceSpecObjLit | Date | string | number;
15
- timer: FreeOperateFn<ED, Cxt>;
18
+ timer: FreeTimerFn<ED, Cxt>;
16
19
  singleton?: true;
17
20
  };
18
21
  export type Routine<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>> = FreeRoutine<ED, Cxt> | Watcher<ED, T, Cxt>;
@@ -17,6 +17,7 @@ export interface WBWatcher<ED extends EntityDict & BaseEntityDict, T extends key
17
17
  filter: ED[T]['Selection']['filter'] | (() => Promise<ED[T]['Selection']['filter']>);
18
18
  projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>);
19
19
  fn: (context: Cxt, data: Partial<ED[T]['Schema']>[]) => Promise<OperationResult<ED>>;
20
+ forUpdate?: true;
20
21
  singleton?: true;
21
22
  }
22
23
  export type Watcher<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>> = BBWatcher<ED, T> | WBWatcher<ED, T, Cxt>;
@@ -7,8 +7,9 @@ import { AccessConfiguration } from '../types/Configuration';
7
7
  export default class SimpleConnector<ED extends EntityDict & BaseEntityDict, FrontCxt extends SyncContext<ED>> implements Connector<ED, FrontCxt> {
8
8
  static ASPECT_ROUTER: string;
9
9
  static BRIDGE_ROUTER: string;
10
- static SUBSCRIBE_ROUTER: string;
11
- static SUBSCRIBE_POINT_ROUTER: string;
10
+ static SUBSCRIBE_PATH: string;
11
+ static SOCKET_PATH: string;
12
+ static SOCKET_POINT_ROUTER: string;
12
13
  static ENDPOINT_ROUTER: string;
13
14
  private serverUrl;
14
15
  private serverAspectUrl;
@@ -47,11 +48,12 @@ export default class SimpleConnector<ED extends EntityDict & BaseEntityDict, Fro
47
48
  opRecords?: undefined;
48
49
  }>;
49
50
  getRouter(): string;
50
- getSubscribeRouter(): string;
51
- getSubscribePointRouter(): string;
52
- getSubscribePoint(): Promise<{
53
- url: any;
51
+ getSocketPath(): string;
52
+ getSocketPointRouter(): string;
53
+ getSocketPoint(): Promise<{
54
54
  path: any;
55
+ subscribeUrl: any;
56
+ socketUrl: any;
55
57
  }>;
56
58
  getEndpointRouter(): string;
57
59
  parseRequest(headers: IncomingHttpHeaders, body?: any, files?: any): {
@@ -8,8 +8,9 @@ const types_1 = require("../types");
8
8
  class SimpleConnector {
9
9
  static ASPECT_ROUTER = '/aspect';
10
10
  static BRIDGE_ROUTER = '/bridge';
11
- static SUBSCRIBE_ROUTER = process.env.OAK_SUBSCRIBE_ROUTER || '/subscribe';
12
- static SUBSCRIBE_POINT_ROUTER = '/subscribePoint';
11
+ static SUBSCRIBE_PATH = process.env.OAK_SUBSCRIBE_PATH || '/subscribe';
12
+ static SOCKET_PATH = process.env.OAK_SOCKET_PATH || '/socket';
13
+ static SOCKET_POINT_ROUTER = '/socketPoint';
13
14
  static ENDPOINT_ROUTER = '/endpoint';
14
15
  serverUrl;
15
16
  serverAspectUrl;
@@ -38,7 +39,7 @@ class SimpleConnector {
38
39
  this.serverAspectUrl = `${serverUrl}${routerPrefixes?.aspect || SimpleConnector.ASPECT_ROUTER}`;
39
40
  this.serverBridgeUrl = `${serverUrl}${routerPrefixes?.bridge || SimpleConnector.BRIDGE_ROUTER}`;
40
41
  this.serverSubscribePointUrl = `${serverUrl}${routerPrefixes?.getSubscribePoint ||
41
- SimpleConnector.SUBSCRIBE_POINT_ROUTER}`;
42
+ SimpleConnector.SOCKET_POINT_ROUTER}`;
42
43
  this.makeException = makeException;
43
44
  }
44
45
  getCorsHeader() {
@@ -122,13 +123,16 @@ class SimpleConnector {
122
123
  getRouter() {
123
124
  return this.configuration.routerPrefixes?.aspect || SimpleConnector.ASPECT_ROUTER;
124
125
  }
125
- getSubscribeRouter() {
126
- return this.configuration.routerPrefixes?.subscribe || SimpleConnector.SUBSCRIBE_ROUTER;
126
+ /* getSubscribePath(): string {
127
+ return this.configuration.socketPath?.subscribe || SimpleConnector.SUBSCRIBE_PATH;
128
+ } */
129
+ getSocketPath() {
130
+ return this.configuration.socketPath || SimpleConnector.SOCKET_PATH;
127
131
  }
128
- getSubscribePointRouter() {
129
- return this.configuration.routerPrefixes?.getSubscribePoint || SimpleConnector.SUBSCRIBE_POINT_ROUTER;
132
+ getSocketPointRouter() {
133
+ return this.configuration.routerPrefixes?.getSubscribePoint || SimpleConnector.SOCKET_POINT_ROUTER;
130
134
  }
131
- async getSubscribePoint() {
135
+ async getSocketPoint() {
132
136
  let response;
133
137
  try {
134
138
  response = await global.fetch(this.serverSubscribePointUrl);
@@ -144,10 +148,11 @@ class SimpleConnector {
144
148
  const responseType = response.headers.get('Content-Type') ||
145
149
  response.headers.get('content-type');
146
150
  if (responseType?.toLocaleLowerCase().match(/application\/json/i)) {
147
- const { url, path } = await response.json();
151
+ const { socketUrl, subscribeUrl, path } = await response.json();
148
152
  return {
149
- url,
150
153
  path,
154
+ subscribeUrl,
155
+ socketUrl,
151
156
  };
152
157
  }
153
158
  else {
package/lib/utils/row.js CHANGED
@@ -6,8 +6,8 @@ const lodash_1 = require("./lodash");
6
6
  const relation_1 = require("../store/relation");
7
7
  const assert_1 = tslib_1.__importDefault(require("assert"));
8
8
  function compareRow(schema, entity, row1, row2) {
9
- const attrs1 = Object.keys(row1).filter(ele => !ele.startsWith('$$'));
10
- const attrs2 = Object.keys(row2).filter(ele => !ele.startsWith('$$'));
9
+ const attrs1 = Object.keys(row1 || {}).filter(ele => !ele.startsWith('$$'));
10
+ const attrs2 = Object.keys(row2 || {}).filter(ele => !ele.startsWith('$$'));
11
11
  if ((0, lodash_1.difference)(attrs1, attrs2).length > 0) {
12
12
  return false;
13
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oak-domain",
3
- "version": "5.1.8",
3
+ "version": "5.1.9",
4
4
  "author": {
5
5
  "name": "XuChang"
6
6
  },
@@ -29,6 +29,7 @@
29
29
  "@types/node": "^20.6.1",
30
30
  "@types/node-schedule": "^2.1.0",
31
31
  "@types/react": "^17.0.2",
32
+ "@types/socket.io": "^3.0.2",
32
33
  "@types/uuid": "^8.3.0",
33
34
  "@types/wechat-miniprogram": "^3.4.1",
34
35
  "assert": "^2.0.0",
@@ -45,6 +46,7 @@
45
46
  "dependencies": {
46
47
  "dayjs": "^1.11.9",
47
48
  "node-schedule": "^2.1.1",
49
+ "socket.io": "^4.7.2",
48
50
  "uuid": "^9.0.0",
49
51
  "webidl-conversions": "^5.0.0"
50
52
  }