oak-domain 5.1.31 → 5.1.33

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.
@@ -43,6 +43,7 @@ exports.desc = {
43
43
  type: "object"
44
44
  },
45
45
  iState: {
46
+ notNull: true,
46
47
  type: "enum",
47
48
  enumeration: ["active", "applied", "abandoned"]
48
49
  }
@@ -10,7 +10,7 @@ export type OpSchema = EntityShape & {
10
10
  data: Object;
11
11
  filter?: Object | null;
12
12
  extra?: Object | null;
13
- iState?: IState | null;
13
+ iState: IState;
14
14
  } & {
15
15
  [A in ExpressionKey]?: any;
16
16
  };
@@ -43,6 +43,7 @@ exports.desc = {
43
43
  type: "object"
44
44
  },
45
45
  iState: {
46
+ notNull: true,
46
47
  type: "enum",
47
48
  enumeration: ["normal", "rollbacked"]
48
49
  }
@@ -13,7 +13,7 @@ export type OpSchema = EntityShape & {
13
13
  bornAt?: Datetime | null;
14
14
  logId?: ForeignKey<"log"> | null;
15
15
  undoData?: Object | null;
16
- iState?: IState | null;
16
+ iState: IState;
17
17
  } & {
18
18
  [A in ExpressionKey]?: any;
19
19
  };
@@ -0,0 +1,9 @@
1
+ import * as ts from 'typescript';
2
+ /**
3
+ * 判断节点是否为 t 函数调用
4
+ * @param node ts.Node
5
+ * @param typeChecker ts.TypeChecker
6
+ * @returns boolean
7
+ * t: (key: string, params?: object | undefined) => string
8
+ */
9
+ export declare const isTCall: (node: ts.Node, typeChecker: ts.TypeChecker, modules: string[]) => boolean;
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isTCall = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const ts = tslib_1.__importStar(require("typescript"));
6
+ // 缓存结构:WeakMap<Node, Map<modulesKey, boolean>>
7
+ const isTCallCache = new WeakMap();
8
+ /**
9
+ * 生成 modules 的缓存 key
10
+ */
11
+ function getModulesCacheKey(modules) {
12
+ return modules.sort().join('|');
13
+ }
14
+ /**
15
+ * 判断节点是否为 t 函数调用
16
+ * @param node ts.Node
17
+ * @param typeChecker ts.TypeChecker
18
+ * @returns boolean
19
+ * t: (key: string, params?: object | undefined) => string
20
+ */
21
+ const isTCall = (node, typeChecker, modules) => {
22
+ // 缓存查询
23
+ const modulesCacheKey = getModulesCacheKey(modules);
24
+ let nodeCache = isTCallCache.get(node);
25
+ if (nodeCache) {
26
+ const cachedResult = nodeCache.get(modulesCacheKey);
27
+ if (cachedResult !== undefined) {
28
+ return cachedResult;
29
+ }
30
+ }
31
+ if (!(ts.isCallExpression(node) && ts.isIdentifier(node.expression))) {
32
+ // 缓存 false 结果
33
+ if (!nodeCache) {
34
+ nodeCache = new Map();
35
+ isTCallCache.set(node, nodeCache);
36
+ }
37
+ nodeCache.set(modulesCacheKey, false);
38
+ return false;
39
+ }
40
+ const result = doIsTCallDirect(node, typeChecker, modules);
41
+ // 缓存结果
42
+ if (!nodeCache) {
43
+ nodeCache = new Map();
44
+ isTCallCache.set(node, nodeCache);
45
+ }
46
+ nodeCache.set(modulesCacheKey, result);
47
+ return result;
48
+ };
49
+ exports.isTCall = isTCall;
50
+ const doIsTCallDirect = (node, typeChecker, modules) => {
51
+ if (!(ts.isCallExpression(node) && ts.isIdentifier(node.expression))) {
52
+ return false;
53
+ }
54
+ const symbol = typeChecker.getSymbolAtLocation(node.expression);
55
+ if (!symbol) {
56
+ return false;
57
+ }
58
+ const declarations = symbol.getDeclarations();
59
+ if (!declarations || declarations.length === 0) {
60
+ return false;
61
+ }
62
+ for (const decl of declarations) {
63
+ const declType = typeChecker.getTypeAtLocation(decl);
64
+ const signatures = declType.getCallSignatures();
65
+ for (const sig of signatures) {
66
+ // 检查这个类型是否来自指定模块
67
+ if (!isTypeFromModules(declType, modules)) {
68
+ continue;
69
+ }
70
+ // 检查返回类型是否为 string
71
+ const returnType = typeChecker.getReturnTypeOfSignature(sig);
72
+ if ((returnType.flags & ts.TypeFlags.String) === 0) {
73
+ continue;
74
+ }
75
+ const params = sig.getParameters();
76
+ if (params.length === 0) {
77
+ continue;
78
+ }
79
+ // 检查第一个参数是否为 string
80
+ const firstParamType = typeChecker.getTypeOfSymbolAtLocation(params[0], decl);
81
+ if ((firstParamType.flags & ts.TypeFlags.String) === 0) {
82
+ continue;
83
+ }
84
+ // 如果只有一个参数,符合 (key: string) => string
85
+ if (params.length === 1) {
86
+ return true;
87
+ }
88
+ // 检查第二个参数
89
+ if (params.length >= 2) {
90
+ const secondParam = params[1];
91
+ const secondParamType = typeChecker.getTypeOfSymbolAtLocation(secondParam, decl);
92
+ // 检查第二个参数是否为 object 或 object | undefined
93
+ if (isObjectOrObjectUnion(secondParamType)) {
94
+ return true;
95
+ }
96
+ }
97
+ }
98
+ }
99
+ return false;
100
+ };
101
+ /**
102
+ * 检查类型是否为 object 或 object | undefined
103
+ * @param type ts.Type
104
+ * @returns boolean
105
+ */
106
+ function isObjectOrObjectUnion(type) {
107
+ // 如果是联合类型
108
+ if (type.isUnion()) {
109
+ // 检查联合类型中是否包含 object 类型
110
+ // 允许 object | undefined 的组合
111
+ let hasObject = false;
112
+ let hasOnlyObjectAndUndefined = true;
113
+ for (const t of type.types) {
114
+ if ((t.flags & ts.TypeFlags.Object) !== 0 || (t.flags & ts.TypeFlags.NonPrimitive) !== 0) {
115
+ hasObject = true;
116
+ }
117
+ else if ((t.flags & ts.TypeFlags.Undefined) === 0) {
118
+ // 如果既不是 object 也不是 undefined,则不符合
119
+ hasOnlyObjectAndUndefined = false;
120
+ }
121
+ }
122
+ return hasObject && hasOnlyObjectAndUndefined;
123
+ }
124
+ // 如果是单一类型,检查是否为 object
125
+ return (type.flags & ts.TypeFlags.Object) !== 0 || (type.flags & ts.TypeFlags.NonPrimitive) !== 0;
126
+ }
127
+ /**
128
+ * 检查声明是否来自指定的模块
129
+ * @param decl ts.Declaration
130
+ * @param modules 模块名称列表
131
+ * @returns boolean
132
+ */
133
+ function isFromModules(decl, modules) {
134
+ const sourceFile = decl.getSourceFile();
135
+ if (!sourceFile) {
136
+ return false;
137
+ }
138
+ const fileName = sourceFile.fileName;
139
+ // 检查文件路径是否包含指定的模块
140
+ return modules.some(moduleName => {
141
+ return fileName.includes(moduleName);
142
+ });
143
+ }
144
+ /**
145
+ * 检查类型是否来自指定模块
146
+ * @param type ts.Type
147
+ * @param modules 模块名称列表
148
+ * @returns boolean
149
+ */
150
+ function isTypeFromModules(type, modules) {
151
+ const symbol = type.getSymbol();
152
+ if (!symbol) {
153
+ return false;
154
+ }
155
+ const declarations = symbol.getDeclarations();
156
+ if (!declarations || declarations.length === 0) {
157
+ return false;
158
+ }
159
+ return declarations.some(decl => isFromModules(decl, modules));
160
+ }
@@ -44,7 +44,6 @@ export declare function registerFixedDestinationPathMap(map: Record<string, stri
44
44
  export declare function registerDeducedRelationMap(map: Record<string, string>): void;
45
45
  export declare const getAnalizedSchema: () => typeof Schema;
46
46
  export declare function analyzeEntities(inputDir: string, relativePath?: string): void;
47
- export declare function buildSchemaBackup(outputDir: string): void;
48
47
  export declare function getProjectionKeys(entity: string): string[];
49
48
  export declare function buildSchema(outputDir: string): void;
50
49
  export {};
@@ -9,7 +9,6 @@ exports.registerIgnoredRelationPathMap = registerIgnoredRelationPathMap;
9
9
  exports.registerFixedDestinationPathMap = registerFixedDestinationPathMap;
10
10
  exports.registerDeducedRelationMap = registerDeducedRelationMap;
11
11
  exports.analyzeEntities = analyzeEntities;
12
- exports.buildSchemaBackup = buildSchemaBackup;
13
12
  exports.getProjectionKeys = getProjectionKeys;
14
13
  exports.buildSchema = buildSchema;
15
14
  const tslib_1 = require("tslib");
@@ -440,7 +439,7 @@ function dealWithActionTypeNode(moduleName, filename, actionTypeNode, program, s
440
439
  }
441
440
  function dealWithActionDefInitializer(moduleName, initializer, program) {
442
441
  if (ts.isIdentifier(initializer) || ts.isCallExpression(initializer)) {
443
- // 是从别处的引用,注入到mportActionDefFrom
442
+ // 是从别处的引用,注入到importActionDefFrom
444
443
  const checker = program.getTypeChecker();
445
444
  const identifier = ts.isIdentifier(initializer) ? initializer : initializer.expression;
446
445
  (0, assert_1.default)(ts.isIdentifier(identifier), "ActionDef的initializer不是一个Identifier");
@@ -449,12 +448,131 @@ function dealWithActionDefInitializer(moduleName, initializer, program) {
449
448
  (0, assert_1.default)(ts.isImportSpecifier(declaration), "ActionDef的initializer不是一个ImportSpecifier");
450
449
  const importDeclartion = declaration.parent.parent.parent;
451
450
  addImportedFrom(moduleName, identifier.text, importDeclartion);
451
+ // 如果是函数调用(CallExpression),无法在编译时确定is,直接返回false
452
+ if (ts.isCallExpression(initializer)) {
453
+ return false;
454
+ }
455
+ // 如果是直接引用(Identifier),尝试分析外部引用的actionDef中的is
456
+ const aliasedSymbol = checker.getAliasedSymbol(symbol);
457
+ const aliasedDeclaration = aliasedSymbol?.getDeclarations()?.[0];
458
+ // 如果无法获取到声明,返回false(可能是第三方库)
459
+ if (!aliasedDeclaration || !ts.isVariableDeclaration(aliasedDeclaration)) {
460
+ return false;
461
+ }
462
+ const { initializer: aliDecInit } = aliasedDeclaration;
463
+ // 如果没有初始化器,可能是.d.ts声明文件,尝试从对应的.js文件读取
464
+ if (!aliDecInit) {
465
+ const sourceFile = aliasedDeclaration.getSourceFile();
466
+ const sourceFileName = sourceFile.fileName;
467
+ // 检查是否是.d.ts文件
468
+ if (sourceFileName.endsWith('.d.ts')) {
469
+ const jsFileName = sourceFileName.replace(/\.d\.ts$/, '.js');
470
+ // 尝试读取对应的.js文件
471
+ if ((0, fs_1.existsSync)(jsFileName)) {
472
+ try {
473
+ const jsContent = require('fs').readFileSync(jsFileName, 'utf-8');
474
+ // 获取原始的导出名称(处理 as 别名的情况)
475
+ // 如果有 propertyName,说明使用了 as,应该使用 propertyName
476
+ // 否则使用 name
477
+ const exportName = declaration.propertyName?.text || declaration.name.text;
478
+ // 尝试从JS文件中解析is属性
479
+ const hasIs = tryParseIsFromJsFile(jsContent, exportName);
480
+ return hasIs;
481
+ }
482
+ catch (error) {
483
+ console.warn(`无法解析JS文件 ${jsFileName}:`, error);
484
+ return false;
485
+ }
486
+ }
487
+ }
488
+ return false;
489
+ }
490
+ // 如果是对象字面量,检查is属性
491
+ if (ts.isObjectLiteralExpression(aliDecInit)) {
492
+ const { properties } = aliDecInit;
493
+ const isProp = properties.find((ele) => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'is' && ts.isStringLiteral(ele.initializer));
494
+ return !!isProp;
495
+ }
496
+ // 其他情况返回false
497
+ return false;
452
498
  }
453
499
  else {
454
500
  // 本地定义的actionDef,不用处理
455
501
  (0, assert_1.default)(ts.isObjectLiteralExpression(initializer), moduleName);
502
+ if (ts.isObjectLiteralExpression(initializer)) {
503
+ const { properties } = initializer;
504
+ // 检查is属性是否存在,并且是string literal
505
+ const isProp = properties.find((ele) => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'is' && ts.isStringLiteral(ele.initializer));
506
+ return !!isProp;
507
+ }
508
+ return false;
456
509
  }
457
510
  }
511
+ /**
512
+ * 尝试从JavaScript文件内容中解析导出对象的is属性
513
+ * @param jsContent JavaScript文件内容
514
+ * @param exportName 导出的变量名
515
+ * @returns 是否包含is属性
516
+ */
517
+ function tryParseIsFromJsFile(jsContent, exportName) {
518
+ // 创建一个临时的SourceFile来解析JavaScript
519
+ const jsSourceFile = ts.createSourceFile('temp.js', jsContent, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
520
+ let hasIs = false;
521
+ // 遍历AST查找导出
522
+ const visit = (node) => {
523
+ // 处理 exports.xxx = {...} 或 module.exports.xxx = {...}
524
+ if (ts.isExpressionStatement(node)) {
525
+ const expr = node.expression;
526
+ if (ts.isBinaryExpression(expr) && expr.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
527
+ const left = expr.left;
528
+ const right = expr.right;
529
+ // 检查是否是 exports.exportName 或 module.exports.exportName
530
+ if (ts.isPropertyAccessExpression(left)) {
531
+ const propertyName = left.name.text;
532
+ if (propertyName === exportName) {
533
+ // 检查右侧是否是对象字面量
534
+ if (ts.isObjectLiteralExpression(right)) {
535
+ hasIs = checkObjectHasIsProperty(right);
536
+ return;
537
+ }
538
+ }
539
+ }
540
+ }
541
+ }
542
+ // 处理 const xxx = {...}; exports.xxx = xxx;
543
+ if (ts.isVariableStatement(node)) {
544
+ const declarations = node.declarationList.declarations;
545
+ for (const decl of declarations) {
546
+ if (ts.isIdentifier(decl.name) && decl.name.text === exportName) {
547
+ if (decl.initializer && ts.isObjectLiteralExpression(decl.initializer)) {
548
+ hasIs = checkObjectHasIsProperty(decl.initializer);
549
+ return;
550
+ }
551
+ }
552
+ }
553
+ }
554
+ ts.forEachChild(node, visit);
555
+ };
556
+ visit(jsSourceFile);
557
+ return hasIs;
558
+ }
559
+ /**
560
+ * 检查对象字面量是否包含is属性
561
+ */
562
+ function checkObjectHasIsProperty(objLiteral) {
563
+ const { properties } = objLiteral;
564
+ const isProp = properties.find((ele) => {
565
+ if (ts.isPropertyAssignment(ele)) {
566
+ const name = ele.name;
567
+ if (ts.isIdentifier(name) && name.text === 'is') {
568
+ // 检查值是否是字符串字面量
569
+ return ts.isStringLiteral(ele.initializer);
570
+ }
571
+ }
572
+ return false;
573
+ });
574
+ return !!isProp;
575
+ }
458
576
  /**
459
577
  * entity的引用一定要以 import { Schema as XXX } from '..../XXX'这种形式
460
578
  * @param declaration
@@ -713,7 +831,7 @@ function dealImportedFile(path, fileSpecifierPath, filename, program) {
713
831
  // }
714
832
  // assert(false, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
715
833
  // }
716
- function analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, relativePath) {
834
+ function analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrDict, enumAttributes, importAttrFrom, relativePath) {
717
835
  let hasEntityAttr = false;
718
836
  let hasEntityIdAttr = false;
719
837
  let toModi = false;
@@ -742,7 +860,7 @@ function analyzeSchemaDefinition(node, moduleName, filename, path, program, refe
742
860
  extendsFrom.push(from);
743
861
  const [sourceFile, pathName] = dealImportedFile(path, from, filename, program);
744
862
  const relativeFilename = path_1.default.relative(process.cwd(), pathName);
745
- 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, '..'));
863
+ const result = analyzeReferenceSchemaFile(moduleName, path_1.default.basename(relativeFilename), path_1.default.dirname(relativeFilename), sourceFile, program, referencedSchemas, schemaAttrDict, enumAttributes, importAttrFrom, path_1.default.join(from, '..'));
746
864
  return result;
747
865
  }).filter(ele => !!ele);
748
866
  // assert(['EntityShape'].includes((<ts.Identifier>heritageClauses![0].types![0].expression).text), moduleName);
@@ -754,7 +872,9 @@ function analyzeSchemaDefinition(node, moduleName, filename, path, program, refe
754
872
  && ts.isIdentifier(type.typeName)) {
755
873
  if ((referencedSchemas.includes(type.typeName.text) || type.typeName.text === 'Schema')) {
756
874
  addRelationship(moduleName, type.typeName.text, attrName, !!questionToken);
757
- schemaAttrs.push(attrNode);
875
+ // schemaAttrs.push(attrNode);
876
+ (0, assert_1.default)(!schemaAttrDict[attrName], `「${filename}」的属性定义「${attrName}」发生了重复`);
877
+ schemaAttrDict[attrName] = attrNode;
758
878
  }
759
879
  else if (type.typeName.text === 'Array') {
760
880
  // 这是一对多的反向指针的引用,需要特殊处理
@@ -782,7 +902,9 @@ function analyzeSchemaDefinition(node, moduleName, filename, path, program, refe
782
902
  }
783
903
  }
784
904
  else {
785
- schemaAttrs.push(attrNode);
905
+ // schemaAttrs.push(attrNode);
906
+ (0, assert_1.default)(!schemaAttrDict[attrName], `「${filename}」的属性定义「${attrName}」发生了重复`);
907
+ schemaAttrDict[attrName] = attrNode;
786
908
  const enumStringValues = tryGetStringLiteralValues(moduleName, filename, `attr-${attrName}`, type, program);
787
909
  if (enumStringValues.length > 0) {
788
910
  enumAttributes[attrName] = enumStringValues;
@@ -813,13 +935,17 @@ function analyzeSchemaDefinition(node, moduleName, filename, path, program, refe
813
935
  }
814
936
  }
815
937
  else {
816
- schemaAttrs.push(attrNode);
938
+ // schemaAttrs.push(attrNode);
939
+ (0, assert_1.default)(!schemaAttrDict[attrName], `「${filename}」的属性定义「${attrName}」发生了重复`);
940
+ schemaAttrDict[attrName] = attrNode;
817
941
  analyzeExternalAttrImport(type.elementType, program, importAttrFrom, relativePath);
818
942
  // throw new Error(`对象${moduleName}中定义的属性${attrName}是不可识别的数组类别`);
819
943
  }
820
944
  }
821
945
  else {
822
- schemaAttrs.push(attrNode);
946
+ // schemaAttrs.push(attrNode);
947
+ (0, assert_1.default)(!schemaAttrDict[attrName], `「${filename}」的属性定义「${attrName}」发生了重复`);
948
+ schemaAttrDict[attrName] = attrNode;
823
949
  if (ts.isUnionTypeNode(type) && ts.isLiteralTypeNode(type.types[0]) && ts.isStringLiteral(type.types[0].literal)) {
824
950
  (0, assert_1.default)(ts.isIdentifier(name), `「${filename}」中的属性定义不是String类型`);
825
951
  const { types } = type;
@@ -893,7 +1019,7 @@ function analyzeSchemaDefinition(node, moduleName, filename, path, program, refe
893
1019
  extendsFrom,
894
1020
  };
895
1021
  }
896
- function analyzeReferenceSchemaFile(moduleName, filename, path, sourceFile, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, relativePath) {
1022
+ function analyzeReferenceSchemaFile(moduleName, filename, path, sourceFile, program, referencedSchemas, schemaAttrDict, enumAttributes, importAttrFrom, relativePath) {
897
1023
  let result;
898
1024
  ts.forEachChild(sourceFile, (node) => {
899
1025
  if (ts.isImportDeclaration(node)) {
@@ -902,7 +1028,7 @@ function analyzeReferenceSchemaFile(moduleName, filename, path, sourceFile, prog
902
1028
  if (ts.isInterfaceDeclaration(node)) {
903
1029
  // schema 定义
904
1030
  if (node.name.text === 'Schema') {
905
- result = analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, relativePath);
1031
+ result = analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrDict, enumAttributes, importAttrFrom, relativePath);
906
1032
  }
907
1033
  else if (!node.name.text.endsWith('Relation') && !node.name.text.endsWith('Action') && !node.name.text.endsWith('State')) {
908
1034
  // 本地规定的一些形状定义,直接使用
@@ -933,7 +1059,8 @@ function analyzeEntity(filename, path, program, relativePath) {
933
1059
  }
934
1060
  checkNameLegal(filename, moduleName, true);
935
1061
  const referencedSchemas = [];
936
- const schemaAttrs = [];
1062
+ // const schemaAttrs: ts.TypeElement[] = [];
1063
+ const schemaAttrDict = {};
937
1064
  let hasFulltextIndex = false;
938
1065
  let indexes;
939
1066
  let beforeSchema = true;
@@ -958,7 +1085,7 @@ function analyzeEntity(filename, path, program, relativePath) {
958
1085
  // schema 定义
959
1086
  if (node.name.text === 'Schema') {
960
1087
  beforeSchema = false;
961
- const result = analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, relativePath);
1088
+ const result = analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrDict, enumAttributes, importAttrFrom, relativePath);
962
1089
  if (result.hasEntityAttr && result.hasEntityIdAttr) {
963
1090
  (0, lodash_1.assign)(ReversePointerEntities, {
964
1091
  [moduleName]: 1,
@@ -1112,11 +1239,12 @@ function analyzeEntity(filename, path, program, relativePath) {
1112
1239
  const enumStateValues = tryGetStringLiteralValues(moduleName, filename, 'state', stateNode, program);
1113
1240
  (0, assert_1.default)(enumStateValues.length > 0, `文件${filename}中的state${stateNode.typeName.text}定义不是字符串类型`);
1114
1241
  pushStatementIntoActionAst(moduleName, node, sourceFile);
1115
- dealWithActionDefInitializer(moduleName, declaration.initializer, program);
1242
+ const isDefined = dealWithActionDefInitializer(moduleName, declaration.initializer, program);
1116
1243
  (0, assert_1.default)(ts.isIdentifier(declaration.name));
1117
1244
  const adName = declaration.name.text.slice(0, declaration.name.text.length - 9);
1118
1245
  const attr = adName.concat('State');
1119
- schemaAttrs.push(factory.createPropertySignature(undefined, (0, string_1.firstLetterLowerCase)(attr), factory.createToken(ts.SyntaxKind.QuestionToken), factory.createTypeReferenceNode(attr)));
1246
+ (0, assert_1.default)(!schemaAttrDict[attr], `文件${filename}中的${attr}有显式定义,与ActionDef需要生成的属性冲突`);
1247
+ schemaAttrDict[attr] = factory.createPropertySignature(undefined, (0, string_1.firstLetterLowerCase)(attr), isDefined ? undefined : factory.createToken(ts.SyntaxKind.QuestionToken), factory.createTypeReferenceNode(attr));
1120
1248
  enumAttributes[(0, string_1.firstLetterLowerCase)(attr)] = enumStateValues;
1121
1249
  };
1122
1250
  const dealWithIndexes = (declaration) => {
@@ -1175,7 +1303,7 @@ function analyzeEntity(filename, path, program, relativePath) {
1175
1303
  });
1176
1304
  const indexAttrName = nameProperty.initializer.text;
1177
1305
  if (!Entity_1.initinctiveAttributes.includes(indexAttrName)) {
1178
- const schemaNode = schemaAttrs.find((ele3) => {
1306
+ const schemaNode = Object.values(schemaAttrDict).find((ele3) => {
1179
1307
  (0, assert_1.default)(ts.isPropertySignature(ele3));
1180
1308
  return ele3.name.text === indexAttrName;
1181
1309
  });
@@ -1390,6 +1518,7 @@ function analyzeEntity(filename, path, program, relativePath) {
1390
1518
  if (hasActionDef && actionType !== 'crud') {
1391
1519
  throw new Error(`${filename}中有Action定义,但却定义了actionType不是crud`);
1392
1520
  }
1521
+ const schemaAttrs = Object.values(schemaAttrDict);
1393
1522
  (0, assert_1.default)(schemaAttrs.length > 0, `对象${moduleName}没有任何属性定义`);
1394
1523
  const schema = {
1395
1524
  schemaAttrs,
@@ -4933,24 +5062,6 @@ function analyzeEntities(inputDir, relativePath) {
4933
5062
  analyzeInModi();
4934
5063
  uniqRelationships();
4935
5064
  }
4936
- function buildSchemaBackup(outputDir) {
4937
- addReverseRelationship();
4938
- // setRelationEntities();
4939
- const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
4940
- resetOutputDir(outputDir);
4941
- outputSchema(outputDir, printer);
4942
- outputLocale(outputDir, printer);
4943
- outputSubQuery(outputDir, printer);
4944
- outputAction(outputDir, printer);
4945
- outputEntityDict(outputDir, printer);
4946
- outputStorage(outputDir, printer);
4947
- outputRelation2(outputDir, printer);
4948
- outputStyleDict(outputDir, printer);
4949
- outputIndexTs(outputDir);
4950
- if (!process.env.COMPLING_AS_LIB) {
4951
- outputPackageJson(outputDir);
4952
- }
4953
- }
4954
5065
  function _getAggrKey(entity, foreignKey) {
4955
5066
  const aggrKey = `${entity}$${foreignKey}`;
4956
5067
  if (process.env.COMPLING_AS_LIB) {
@@ -0,0 +1,47 @@
1
+ import * as ts from 'typescript';
2
+ export declare const OAK_IGNORE_TAGS: string[];
3
+ interface OakBuildChecksConfig {
4
+ context?: {
5
+ checkAsyncContext?: boolean;
6
+ targetModules?: string[];
7
+ filePatterns?: string[];
8
+ };
9
+ locale?: {
10
+ checkI18nKeys?: boolean;
11
+ tFunctionModules?: string[];
12
+ checkTemplateLiterals?: boolean;
13
+ warnStringKeys?: boolean;
14
+ };
15
+ }
16
+ interface CustomDiagnostic {
17
+ file: ts.SourceFile;
18
+ start: number;
19
+ length: number;
20
+ messageText: string;
21
+ category: ts.DiagnosticCategory;
22
+ code: number;
23
+ callChain?: string[];
24
+ contextCallNode?: ts.CallExpression;
25
+ reason?: string;
26
+ reasonDetails?: string[];
27
+ relatedInfo?: Array<{
28
+ file: ts.SourceFile;
29
+ start: number;
30
+ length: number;
31
+ message: string;
32
+ }>;
33
+ }
34
+ export type CompileOptions = {
35
+ project?: string;
36
+ noEmit?: boolean;
37
+ };
38
+ /**
39
+ * 执行自定义检查
40
+ * @param program ts.Program
41
+ * @param typeChecker ts.TypeChecker
42
+ * @param customConfig 自定义配置
43
+ * @returns CustomDiagnostic[] 自定义诊断列表
44
+ */
45
+ export declare function performCustomChecks(pwd: string, program: ts.Program, typeChecker: ts.TypeChecker, customConfig: OakBuildChecksConfig): CustomDiagnostic[];
46
+ export declare const build: (pwd: string, args: any[]) => void;
47
+ export {};