oak-domain 4.0.3 → 4.2.0

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.
Files changed (73) hide show
  1. package/lib/base-app-domain/ActionAuth/Schema.d.ts +1 -2
  2. package/lib/base-app-domain/ActionDefDict.d.ts +2 -2
  3. package/lib/base-app-domain/I18n/Schema.d.ts +1 -2
  4. package/lib/base-app-domain/Modi/Schema.d.ts +1 -2
  5. package/lib/base-app-domain/ModiEntity/Schema.d.ts +1 -2
  6. package/lib/base-app-domain/Oper/Schema.d.ts +8 -3
  7. package/lib/base-app-domain/Oper/Storage.js +19 -1
  8. package/lib/base-app-domain/OperEntity/Schema.d.ts +1 -2
  9. package/lib/base-app-domain/Path/Schema.d.ts +1 -2
  10. package/lib/base-app-domain/Relation/Schema.d.ts +1 -2
  11. package/lib/base-app-domain/RelationAuth/Schema.d.ts +1 -2
  12. package/lib/base-app-domain/User/Action.d.ts +1 -0
  13. package/lib/base-app-domain/User/Action.js +3 -3
  14. package/lib/base-app-domain/User/Schema.d.ts +1 -2
  15. package/lib/base-app-domain/UserEntityClaim/Schema.d.ts +1 -2
  16. package/lib/base-app-domain/UserEntityGrant/Action.d.ts +5 -5
  17. package/lib/base-app-domain/UserEntityGrant/Action.js +5 -5
  18. package/lib/base-app-domain/UserEntityGrant/Schema.d.ts +1 -2
  19. package/lib/base-app-domain/UserRelation/Schema.d.ts +1 -2
  20. package/lib/compiler/localeBuilder.d.ts +27 -27
  21. package/lib/compiler/localeBuilder.js +215 -215
  22. package/lib/compiler/routerBuilder.js +263 -263
  23. package/lib/compiler/schemalBuilder.js +1058 -460
  24. package/lib/entities/Oper.d.ts +2 -1
  25. package/lib/entities/Oper.js +16 -1
  26. package/lib/entities/User.d.ts +10 -0
  27. package/lib/entities/User.js +3 -2
  28. package/lib/index.d.ts +0 -22
  29. package/lib/index.js +1 -35
  30. package/lib/store/AsyncRowStore.d.ts +2 -1
  31. package/lib/store/AsyncRowStore.js +180 -180
  32. package/lib/store/CascadeStore.js +7 -31
  33. package/lib/store/RelationAuth.d.ts +103 -103
  34. package/lib/store/RelationAuth.js +1209 -1343
  35. package/lib/store/SyncRowStore.d.ts +1 -1
  36. package/lib/store/TriggerExecutor.js +1 -1
  37. package/lib/store/actionDef.js +4 -4
  38. package/lib/store/checker.js +487 -487
  39. package/lib/triggers/index.d.ts +2 -2
  40. package/lib/triggers/index.js +21 -1
  41. package/lib/types/Aspect.d.ts +1 -1
  42. package/lib/types/Configuration.d.ts +42 -0
  43. package/lib/types/Configuration.js +3 -0
  44. package/lib/types/Connector.d.ts +1 -1
  45. package/lib/types/Context.d.ts +1 -1
  46. package/lib/types/Entity.d.ts +4 -4
  47. package/lib/types/Environment.d.ts +3 -0
  48. package/lib/types/Exception.d.ts +155 -155
  49. package/lib/types/Exception.js +436 -436
  50. package/lib/types/Sync.d.ts +48 -0
  51. package/lib/types/Sync.js +8 -0
  52. package/lib/types/index.d.ts +1 -0
  53. package/lib/types/index.js +1 -0
  54. package/lib/utils/SimpleConnector.d.ts +1 -1
  55. package/lib/utils/SimpleConnector.js +1 -1
  56. package/lib/utils/assert.d.ts +0 -1
  57. package/lib/utils/projection.d.ts +1 -1
  58. package/lib/utils/relationPath.d.ts +31 -0
  59. package/lib/utils/relationPath.js +202 -0
  60. package/package.json +51 -51
  61. package/src/entities/ActionAuth.ts +41 -41
  62. package/src/entities/I18n.ts +45 -45
  63. package/src/entities/Modi.ts +69 -69
  64. package/src/entities/ModiEntity.ts +26 -26
  65. package/src/entities/Oper.ts +48 -32
  66. package/src/entities/OperEntity.ts +27 -27
  67. package/src/entities/Path.ts +43 -43
  68. package/src/entities/Relation.ts +43 -43
  69. package/src/entities/RelationAuth.ts +44 -44
  70. package/src/entities/User.ts +48 -48
  71. package/src/entities/UserEntityClaim.ts +29 -29
  72. package/src/entities/UserEntityGrant.ts +24 -24
  73. package/src/entities/UserRelation.ts +50 -50
@@ -115,7 +115,9 @@ function pushStatementIntoActionAst(moduleName, node, sourceFile) {
115
115
  [moduleName]: {
116
116
  statements: [...ActionImportStatements(), node],
117
117
  sourceFile,
118
- importedFrom: {},
118
+ importActionFrom: {},
119
+ importStateFrom: {},
120
+ importActionDefFrom: {},
119
121
  // actionNames,
120
122
  actionDefNames: actionDefName ? [actionDefName] : [],
121
123
  }
@@ -125,6 +127,9 @@ function pushStatementIntoActionAst(moduleName, node, sourceFile) {
125
127
  function pushStatementIntoSchemaAst(moduleName, statement, sourceFile) {
126
128
  if (SchemaAsts[moduleName]) {
127
129
  SchemaAsts[moduleName].statements.push(statement);
130
+ if (!SchemaAsts[moduleName].sourceFile && sourceFile) {
131
+ SchemaAsts[moduleName].sourceFile = sourceFile;
132
+ }
128
133
  }
129
134
  else {
130
135
  (0, lodash_1.assign)(SchemaAsts, {
@@ -164,52 +169,126 @@ function checkStringLiteralLegal(filename, obj, text, ele) {
164
169
  (0, assert_1.default)(ele.literal.text.length < env_1.STRING_LITERAL_MAX_LENGTH, `${filename}中引用的${obj} ${text}中的「${ele.literal.text}」长度过长`);
165
170
  return ele.literal.text;
166
171
  }
167
- function addActionSource(moduleName, name, node) {
172
+ function addImportedFrom(moduleName, name, node) {
168
173
  const ast = ActionAsts[moduleName];
169
- const { moduleSpecifier } = node;
170
- // todo 目前应该只会引用oak-domain/src/actions/action里的公共action,未来如果有交叉引用这里代码要修正(如果domain中也有引用action_constants这里应该也会错)
171
- (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text === (0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)());
172
- (0, lodash_1.assign)(ast.importedFrom, {
173
- [name.text]: node,
174
- });
174
+ let importFrom = typeof node === 'string' ? node : '';
175
+ let propertyName;
176
+ if (typeof node === 'object') {
177
+ const { moduleSpecifier, importClause } = node;
178
+ (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier));
179
+ (0, assert_1.default)(importClause);
180
+ const { namedBindings } = importClause;
181
+ (0, assert_1.default)(namedBindings);
182
+ (0, assert_1.default)(ts.isNamedImports(namedBindings));
183
+ const importSpecifier = namedBindings.elements.find((ele) => ele.name.text === name);
184
+ (0, assert_1.default)(importSpecifier);
185
+ propertyName = importSpecifier.propertyName && importSpecifier.propertyName.text;
186
+ importFrom = moduleSpecifier.text;
187
+ }
188
+ if (name.endsWith('Action')) {
189
+ (0, lodash_1.assign)(ast.importActionFrom, {
190
+ [name]: [importFrom, propertyName],
191
+ });
192
+ }
193
+ else if (name.endsWith('ActionDef')) {
194
+ (0, lodash_1.assign)(ast.importActionDefFrom, {
195
+ [name]: [importFrom, propertyName],
196
+ });
197
+ }
198
+ else {
199
+ (0, assert_1.default)(name.endsWith("State"));
200
+ (0, lodash_1.assign)(ast.importStateFrom, {
201
+ [name]: [importFrom, propertyName],
202
+ });
203
+ }
175
204
  }
176
- function getStringTextFromUnionStringLiterals(moduleName, filename, node, program) {
205
+ function analyzeExternalAttrImport(node, program, importAttrFrom, relativePath) {
177
206
  const checker = program.getTypeChecker();
178
207
  const symbol = checker.getSymbolAtLocation(node.typeName);
179
208
  let declaration = symbol?.getDeclarations()[0];
180
- let isImport = false;
181
209
  /* const typee = checker.getDeclaredTypeOfSymbol(symbol!);
182
-
210
+
183
211
  const declaration = typee.aliasSymbol!.getDeclarations()![0]; */
184
212
  if (ts.isImportSpecifier(declaration)) {
185
- isImport = true;
186
- const typee = checker.getDeclaredTypeOfSymbol(symbol);
187
- declaration = typee.aliasSymbol.getDeclarations()[0];
188
- }
189
- (0, assert_1.default)(ts.isTypeAliasDeclaration(declaration));
190
- const { type, name } = declaration;
191
- // assert(ts.isUnionTypeNode(type!) || ts.isLiteralTypeNode(type!), `${filename}中引用的action「${(<ts.Identifier>name).text}」的定义不是union和stringLiteral类型`);
192
- // 如果这个action是从外部导入的,在这里要记下来此entity和这个导入之间的关系
193
- if (isImport) {
194
- const importDeclartion = symbol.getDeclarations()[0].parent.parent.parent;
213
+ const name = declaration.name.text;
214
+ const importDeclartion = declaration.parent.parent.parent;
195
215
  (0, assert_1.default)(ts.isImportDeclaration(importDeclartion));
196
- addActionSource(moduleName, name, importDeclartion);
197
- }
198
- else {
199
- const ast = ActionAsts[moduleName];
200
- (0, lodash_1.assign)(ast.importedFrom, {
201
- [name.text]: 'local',
216
+ const { moduleSpecifier, importClause } = importDeclartion;
217
+ (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier));
218
+ (0, assert_1.default)(importClause);
219
+ const { namedBindings } = importClause;
220
+ (0, assert_1.default)(namedBindings);
221
+ (0, assert_1.default)(ts.isNamedImports(namedBindings));
222
+ const importSpecifier = namedBindings.elements.find((ele) => ele.name.text === name);
223
+ (0, assert_1.default)(importSpecifier);
224
+ const propertyName = importSpecifier.propertyName && importSpecifier.propertyName.text;
225
+ const importFrom = moduleSpecifier.text;
226
+ const importFromRelatively = importFrom.startsWith('.') ? (relativePath
227
+ ? path_1.default.join(relativePath, importFrom).replace(/\\/g, '/')
228
+ : path_1.default.join('..', importFrom).replace(/\\/g, '/')) : importFrom;
229
+ (0, lodash_1.assign)(importAttrFrom, {
230
+ [name]: [importFromRelatively, propertyName],
202
231
  });
203
232
  }
204
- if (ts.isUnionTypeNode(type)) {
205
- const actions = type.types.map(ele => checkStringLiteralLegal(filename, 'action', name.text, ele));
206
- return actions;
233
+ else if (ts.isTypeAliasDeclaration(declaration)) {
234
+ const traverseTsAst = (node) => {
235
+ // 递归遍历每个节点
236
+ ts.forEachChild(node, (child) => {
237
+ if (ts.isTypeReferenceNode(child)) {
238
+ analyzeExternalAttrImport(child, program, importAttrFrom, relativePath);
239
+ }
240
+ else {
241
+ traverseTsAst(child);
242
+ }
243
+ });
244
+ };
245
+ traverseTsAst(declaration);
207
246
  }
208
- else {
209
- (0, assert_1.default)(ts.isLiteralTypeNode(type), `${filename}中引用的action「${name.text}」的定义不是union和stringLiteral类型`);
210
- const action = checkStringLiteralLegal(filename, 'action', name.text, type);
211
- return [action];
247
+ }
248
+ function tryGetStringLiteralValues(moduleName, filename, obj, node, program) {
249
+ const checker = program.getTypeChecker();
250
+ const symbol = checker.getSymbolAtLocation(node.typeName);
251
+ let declaration = symbol?.getDeclarations()[0];
252
+ /* const typee = checker.getDeclaredTypeOfSymbol(symbol!);
253
+
254
+ const declaration = typee.aliasSymbol!.getDeclarations()![0]; */
255
+ const values = [];
256
+ if (ts.isImportSpecifier(declaration)) {
257
+ const typee = checker.getDeclaredTypeOfSymbol(symbol);
258
+ if (typee.isStringLiteral()) {
259
+ values.push(typee.value);
260
+ }
261
+ else if (typee.isUnion()) {
262
+ values.push(...typee.types.map(ele => {
263
+ if (ele.isStringLiteral()) {
264
+ return ele.value;
265
+ }
266
+ }).filter(ele => !!ele));
267
+ }
268
+ if (['state', 'action'].includes(obj)) {
269
+ (0, assert_1.default)(values.length > 0);
270
+ const importDeclartion = declaration.parent.parent.parent;
271
+ (0, assert_1.default)(ts.isImportDeclaration(importDeclartion));
272
+ addImportedFrom(moduleName, declaration.name.text, importDeclartion);
273
+ }
274
+ }
275
+ else if (ts.isTypeAliasDeclaration(declaration)) {
276
+ // 本地定义的type
277
+ const { name, type } = declaration;
278
+ if (ts.isUnionTypeNode(type)) {
279
+ values.push(...type.types.map(ele => checkStringLiteralLegal(filename, obj, name.text, ele)));
280
+ }
281
+ else if (ts.isLiteralTypeNode(type)) {
282
+ const action = checkStringLiteralLegal(filename, obj, name.text, type);
283
+ values.push(action);
284
+ }
285
+ if (['state', 'action'].includes(obj)) {
286
+ (0, assert_1.default)(values.length > 0);
287
+ const ast = ActionAsts[moduleName];
288
+ addImportedFrom(moduleName, declaration.name.text, './');
289
+ }
212
290
  }
291
+ return values;
213
292
  }
214
293
  const RESERVED_ACTION_NAMES = ['GenericAction', 'ParticularAction', 'ExcludeRemoveAction', 'ExcludeUpdateAction', 'ReadOnlyAction', 'AppendOnlyAction', 'RelationAction'];
215
294
  const action_1 = require("../actions/action");
@@ -223,21 +302,23 @@ const OriginActionDict = {
223
302
  'appendOnly': 'AppendOnlyAction',
224
303
  'readOnly': 'ReadOnlyAction',
225
304
  };
226
- function dealWithActions(moduleName, filename, node, program, sourceFile) {
305
+ function dealWithActionTypeNode(moduleName, filename, actionTypeNode, program, sourceFile) {
227
306
  const actionTexts = action_1.genericActions.map(ele => ele);
228
307
  if (moduleName === 'User') {
229
308
  actionTexts.push(...action_1.relationActions);
230
309
  }
231
- if (ts.isUnionTypeNode(node)) {
232
- const actionNames = node.types.map(ele => {
310
+ if (ts.isUnionTypeNode(actionTypeNode)) {
311
+ const actionNames = actionTypeNode.types.map(ele => {
233
312
  if (ts.isTypeReferenceNode(ele) && ts.isIdentifier(ele.typeName)) {
234
313
  return ele.typeName.text;
235
314
  }
236
315
  }).filter(ele => !!ele);
237
316
  (0, assert_1.default)((0, lodash_1.intersection)(actionNames, RESERVED_ACTION_NAMES).length === 0, `${filename}中的Action命名不能是「${RESERVED_ACTION_NAMES.join(',')}」之一`);
238
- node.types.forEach(ele => {
317
+ actionTypeNode.types.forEach(ele => {
239
318
  if (ts.isTypeReferenceNode(ele)) {
240
- actionTexts.push(...getStringTextFromUnionStringLiterals(moduleName, filename, ele, program));
319
+ const actionStrings = tryGetStringLiteralValues(moduleName, filename, 'action', ele, program);
320
+ (0, assert_1.default)(actionStrings.length > 0);
321
+ actionTexts.push(...actionStrings);
241
322
  }
242
323
  else {
243
324
  (0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal), `【${moduleName}】action的定义既非Type也不是string`);
@@ -245,15 +326,17 @@ function dealWithActions(moduleName, filename, node, program, sourceFile) {
245
326
  }
246
327
  });
247
328
  }
248
- else if (ts.isTypeReferenceNode(node)) {
249
- if (ts.isIdentifier(node.typeName)) {
250
- (0, assert_1.default)(!RESERVED_ACTION_NAMES.includes(node.typeName.text), `${filename}中的Action命名不能是「${RESERVED_ACTION_NAMES.join(',')}」之一`);
329
+ else if (ts.isTypeReferenceNode(actionTypeNode)) {
330
+ if (ts.isIdentifier(actionTypeNode.typeName)) {
331
+ (0, assert_1.default)(!RESERVED_ACTION_NAMES.includes(actionTypeNode.typeName.text), `${filename}中的Action命名不能是「${RESERVED_ACTION_NAMES.join(',')}」之一`);
251
332
  }
252
- actionTexts.push(...getStringTextFromUnionStringLiterals(moduleName, filename, node, program));
333
+ const actionStrings = tryGetStringLiteralValues(moduleName, filename, 'action', actionTypeNode, program);
334
+ (0, assert_1.default)(actionStrings.length > 0);
335
+ actionTexts.push(...actionStrings);
253
336
  }
254
337
  else {
255
- (0, assert_1.default)(ts.isLiteralTypeNode(node) && ts.isStringLiteral(node.literal), `【${moduleName}】action的定义既非Type也不是string`);
256
- actionTexts.push(node.literal.text);
338
+ (0, assert_1.default)(ts.isLiteralTypeNode(actionTypeNode) && ts.isStringLiteral(actionTypeNode.literal), `【${moduleName}】action的定义既非Type也不是string`);
339
+ actionTexts.push(actionTypeNode.literal.text);
257
340
  }
258
341
  // 所有的action定义不能有重名
259
342
  const ActionDict = {};
@@ -271,6 +354,23 @@ function dealWithActions(moduleName, filename, node, program, sourceFile) {
271
354
  });
272
355
  pushStatementIntoActionAst(moduleName, factory.createVariableStatement([factory.createModifier(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("actions"), undefined, undefined, factory.createArrayLiteralExpression(actionTexts.map(ele => factory.createStringLiteral(ele)), false))], ts.NodeFlags.Const)), sourceFile);
273
356
  }
357
+ function dealWithActionDefInitializer(moduleName, initializer, program) {
358
+ if (ts.isIdentifier(initializer) || ts.isCallExpression(initializer)) {
359
+ // 是从别处的引用,注入到mportActionDefFrom
360
+ const checker = program.getTypeChecker();
361
+ const identifier = ts.isIdentifier(initializer) ? initializer : initializer.expression;
362
+ (0, assert_1.default)(ts.isIdentifier(identifier));
363
+ const symbol = checker.getSymbolAtLocation(identifier);
364
+ const declaration = symbol?.getDeclarations()[0];
365
+ (0, assert_1.default)(ts.isImportSpecifier(declaration));
366
+ const importDeclartion = declaration.parent.parent.parent;
367
+ addImportedFrom(moduleName, identifier.text, importDeclartion);
368
+ }
369
+ else {
370
+ // 本地定义的actionDef,不用处理
371
+ (0, assert_1.default)(ts.isObjectLiteralExpression(initializer), moduleName);
372
+ }
373
+ }
274
374
  /**
275
375
  * entity的引用一定要以 import { Schema as XXX } from '..../XXX'这种形式
276
376
  * @param declaration
@@ -320,24 +420,27 @@ function checkLocaleExpressionPropertyExists(root, attr, exists, filename) {
320
420
  }
321
421
  });
322
422
  }
323
- function getStringEnumValues(filename, program, obj, node) {
423
+ /* function getStringEnumValues(filename: string, program: ts.Program, obj: string, node: ts.TypeReferenceNode) {
324
424
  const checker = program.getTypeChecker();
325
425
  const symbol = checker.getSymbolAtLocation(node.typeName);
326
- let declaration = symbol?.getDeclarations()[0];
426
+ let declaration = symbol?.getDeclarations()![0]!;
327
427
  if (ts.isImportSpecifier(declaration)) {
328
- const typee = checker.getDeclaredTypeOfSymbol(symbol);
329
- declaration = typee.aliasSymbol?.getDeclarations()[0];
428
+ const typee = checker.getDeclaredTypeOfSymbol(symbol!);
429
+ declaration = typee.aliasSymbol?.getDeclarations()![0]!;
330
430
  }
431
+
331
432
  if (declaration && ts.isTypeAliasDeclaration(declaration)) {
332
433
  if (ts.isUnionTypeNode(declaration.type) && ts.isLiteralTypeNode(declaration.type.types[0])) {
333
- return declaration.type.types.map(ele => checkStringLiteralLegal(filename, obj, declaration.name.text, ele));
434
+ return declaration.type.types.map(
435
+ ele => checkStringLiteralLegal(filename, obj, (<ts.TypeAliasDeclaration>declaration).name.text, ele)
436
+ )
334
437
  }
335
438
  if (ts.isLiteralTypeNode(declaration.type)) {
336
439
  const value = checkStringLiteralLegal(filename, obj, declaration.name.text, declaration.type);
337
440
  return [value];
338
441
  }
339
442
  }
340
- }
443
+ } */
341
444
  function checkNameLegal(filename, attrName, upperCase) {
342
445
  (0, assert_1.default)(attrName.length <= env_1.ENTITY_NAME_MAX_LENGTH, `文件「${filename}」:「${attrName}」的名称定义过长,不能超过「${env_1.ENTITY_NAME_MAX_LENGTH}」长度`);
343
446
  if (upperCase) {
@@ -350,9 +453,344 @@ function checkNameLegal(filename, attrName, upperCase) {
350
453
  (0, assert_1.default)(/[a-z|A-Z][a-z|A-Z|0-9]+/i.test(attrName), `文件「${filename}」:「${attrName}」的名称必须以字母开始,且只能包含字母和数字`);
351
454
  }
352
455
  }
456
+ /**
457
+ * 分析import语句,这里注意要去重
458
+ * @param node
459
+ * @param referencedSchemas
460
+ * @param additionalImports
461
+ * @param relativePath
462
+ */
463
+ function analyzeImportDeclaration(node, referencedSchemas, additionalImports, filename, relativePath) {
464
+ const entityImported = getEntityImported(node);
465
+ if (entityImported) {
466
+ referencedSchemas.push(entityImported);
467
+ }
468
+ else {
469
+ /* const { moduleSpecifier, importClause } = node;
470
+ assert(ts.isStringLiteral(moduleSpecifier), `${filename}中的import出现了非stringLiteral类型的import module specifier,无法处理`);
471
+
472
+ const { text } = moduleSpecifier;
473
+ // 和数据类型相关的会自动引入,这里忽略(见initialStatements)
474
+ // 如果是相对路径,编译后的路径默认要深一层
475
+ const moduleSpecifier2Text = text.startsWith('.') ? (relativePath
476
+ ? PathLib.join(
477
+ relativePath,
478
+ text
479
+ ).replace(/\\/g, '/')
480
+ : PathLib.join(
481
+ '..',
482
+ text
483
+ ).replace(/\\/g, '/')) : text;
484
+
485
+ // 去重
486
+ if (importClause) {
487
+ const { name, namedBindings } = importClause;
488
+ assert(namedBindings && ts.isNamedImports(namedBindings));
489
+ assert(!name, `「${filename}」schema定义中出现了import NAME from,请避免`);
490
+
491
+ const unrepeatedSpecifiers: ts.ImportSpecifier[] = [];
492
+ for (const ele2 of namedBindings.elements) {
493
+ let repeated = false;
494
+ for (const imports of additionalImports) {
495
+ const { moduleSpecifier: ms, importClause: ic } = imports;
496
+ assert(ts.isStringLiteral(ms));
497
+ if (ic && ic.namedBindings) {
498
+ assert(ts.isNamedImports(ic.namedBindings));
499
+ const { elements } = ic.namedBindings;
500
+
501
+ for (const ele of elements) {
502
+ const { name: n, propertyName: pn } = ele;
503
+ if (n.text === ele2.name.text || (pn?.text && pn?.text === ele2.propertyName?.text)) {
504
+ assert(n.text === ele2.name.text && pn?.text === ele2.propertyName?.text, `解析「${filename}」时发现了name和propertyName不全等的import语句。${[n.text, pn?.text, ele2.name.text, ele2.propertyName?.text].filter(ele => !!ele).join(',')},可能是在Schema的继承链上出现,请修正`);
505
+ assert(moduleSpecifier.text === ms.text, `解析「${filename}」时发现了name和propertyName完全相等的import语句,但它们的from目标不完全相同。${[moduleSpecifier.text, ms.text].join(',')},可能是在Schema的继承链上出现,请修正`);
506
+ repeated = true;
507
+ break;
508
+ }
509
+ }
510
+ }
511
+ if (repeated) {
512
+ break;
513
+ }
514
+ }
515
+ if (!repeated) {
516
+ unrepeatedSpecifiers.push(ele2);
517
+ }
518
+ }
519
+ if (unrepeatedSpecifiers.length > 0) {
520
+ additionalImports.push(
521
+ factory.updateImportDeclaration(
522
+ node,
523
+ undefined,
524
+ factory.createImportClause(false, undefined, factory.createNamedImports(unrepeatedSpecifiers)),
525
+ factory.createStringLiteral(moduleSpecifier2Text),
526
+ undefined
527
+ )
528
+ );
529
+ }
530
+ }
531
+ else {
532
+ additionalImports.push(
533
+ factory.updateImportDeclaration(
534
+ node,
535
+ undefined,
536
+ undefined,
537
+ factory.createStringLiteral(moduleSpecifier2Text),
538
+ undefined
539
+ )
540
+ );
541
+ } */
542
+ }
543
+ }
544
+ /**
545
+ * 在path下的filename文件中import了fileSpecifierPath,要找到其对应的引用路径
546
+ * 这里关键是要处理形如file:的依赖声明
547
+ * @param path
548
+ * @param fileSpecifierPath
549
+ * @param filename
550
+ * @returns
551
+ */
552
+ function searchImportedPath(path, fileSpecifierPath, filename) {
553
+ const cwd = process.cwd();
554
+ const fileSpecifierPaths = fileSpecifierPath.split('/');
555
+ const moduleName = fileSpecifierPaths[0] || fileSpecifierPaths[1];
556
+ (0, assert_1.default)(moduleName);
557
+ // 找到path路径对应的最近package.json
558
+ const paths = path.split('/');
559
+ for (let iter = paths.length; iter >= 0; iter--) {
560
+ const paths2 = paths.slice(0, iter);
561
+ const pkgJsonPath = path_1.default.join(cwd, ...paths2, 'package.json');
562
+ if ((0, fs_1.existsSync)(pkgJsonPath)) {
563
+ const pkgJson = require(pkgJsonPath);
564
+ if (pkgJson.dependencies?.hasOwnProperty(moduleName)) {
565
+ const dependentPath = pkgJson.dependencies[moduleName];
566
+ if (dependentPath.trimStart().startsWith('file:')) {
567
+ const dependentFilePath = dependentPath.trimStart().slice(5);
568
+ return path_1.default.join(pkgJsonPath, '..', dependentFilePath, ...(fileSpecifierPaths[0] ? fileSpecifierPaths.slice(1) : (fileSpecifierPaths.slice(2))));
569
+ }
570
+ else {
571
+ return path_1.default.join(pkgJsonPath, '..', 'node_modules', fileSpecifierPath);
572
+ }
573
+ }
574
+ }
575
+ }
576
+ (0, assert_1.default)(false, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
577
+ }
578
+ /**
579
+ * 获得import的某个文件的绝对路径
580
+ * @param path
581
+ * @param fileSpecifierPath
582
+ * @returns
583
+ */
584
+ function getImportedFilePath(path, fileSpecifierPath, filename) {
585
+ let importedFilename = fileSpecifierPath.startsWith('.') ? path_1.default.join(process.cwd(), path, fileSpecifierPath) : searchImportedPath(path, fileSpecifierPath, filename);
586
+ if ((0, fs_1.existsSync)(`${importedFilename}.ts`)) {
587
+ return `${importedFilename}.ts`;
588
+ }
589
+ else if ((0, fs_1.existsSync)(`${importedFilename}.d.ts`)) {
590
+ return `${importedFilename}.d.ts`;
591
+ }
592
+ else {
593
+ // 目前不可能引用js文件
594
+ (0, assert_1.default)(false, `「${filename}」import路径${fileSpecifierPath}找不到对应的文件`);
595
+ }
596
+ }
597
+ function analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, relativePath) {
598
+ let hasEntityAttr = false;
599
+ let hasEntityIdAttr = false;
600
+ let toModi = false;
601
+ const extendsFrom = [];
602
+ const { members, heritageClauses } = node;
603
+ (0, assert_1.default)(heritageClauses);
604
+ const heritagedResult = heritageClauses.map((clause) => {
605
+ const { expression } = clause.types[0];
606
+ (0, assert_1.default)(ts.isIdentifier(expression));
607
+ if (expression.text === 'EntityShape') {
608
+ // import { EntityShape } from 'oak-domain/lib/types/Entities; 所有schema的公共祖先类型,不用处理
609
+ return;
610
+ }
611
+ // 从其它文件的Schema类继承,这里需要将所继承的对象的属性进行访问并展开
612
+ (0, assert_1.default)(referencedSchemas.includes(expression.text));
613
+ const checker = program.getTypeChecker();
614
+ const symbol = checker.getSymbolAtLocation(expression);
615
+ let declaration = symbol?.getDeclarations()[0];
616
+ (0, assert_1.default)(ts.isImportSpecifier(declaration));
617
+ const importDeclaration = declaration.parent.parent.parent;
618
+ (0, assert_1.default)(ts.isImportDeclaration(importDeclaration));
619
+ const { moduleSpecifier } = importDeclaration;
620
+ (0, assert_1.default)(ts.isStringLiteral(moduleSpecifier));
621
+ const { text: from } = moduleSpecifier;
622
+ extendsFrom.push(from);
623
+ const importedFilename = getImportedFilePath(path, from, filename);
624
+ const sourceFile = program.getSourceFile(importedFilename);
625
+ (0, assert_1.default)(sourceFile, `「${filename}」找不到相应的sourceFile:${importedFilename}`);
626
+ const relativeFilename = path_1.default.relative(process.cwd(), importedFilename);
627
+ 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, '..'));
628
+ return result;
629
+ }).filter(ele => !!ele);
630
+ // assert(['EntityShape'].includes((<ts.Identifier>heritageClauses![0].types![0].expression).text), moduleName);
631
+ members.forEach((attrNode) => {
632
+ const { type, name, questionToken } = attrNode;
633
+ const attrName = name.text;
634
+ checkNameLegal(filename, attrName, false);
635
+ if (ts.isTypeReferenceNode(type)
636
+ && ts.isIdentifier(type.typeName)) {
637
+ if ((referencedSchemas.includes(type.typeName.text) || type.typeName.text === 'Schema')) {
638
+ addRelationship(moduleName, type.typeName.text, attrName, !!questionToken);
639
+ schemaAttrs.push(attrNode);
640
+ }
641
+ else if (type.typeName.text === 'Array') {
642
+ // 这是一对多的反向指针的引用,需要特殊处理
643
+ const { typeArguments } = type;
644
+ (0, assert_1.default)(typeArguments.length === 1
645
+ && ts.isTypeReferenceNode(typeArguments[0])
646
+ && ts.isIdentifier(typeArguments[0].typeName)
647
+ && referencedSchemas.includes(typeArguments[0].typeName.text), `「${filename}」非法的属性定义「${attrName}」`);
648
+ const reverseEntity = typeArguments[0].typeName.text;
649
+ if (ReversePointerRelations[reverseEntity]) {
650
+ if (!ReversePointerRelations[reverseEntity].includes(moduleName)) {
651
+ ReversePointerRelations[reverseEntity].push(moduleName);
652
+ }
653
+ }
654
+ else {
655
+ (0, lodash_1.assign)(ReversePointerRelations, {
656
+ [reverseEntity]: [moduleName],
657
+ });
658
+ }
659
+ if (reverseEntity === 'Modi') {
660
+ toModi = true;
661
+ }
662
+ }
663
+ else {
664
+ schemaAttrs.push(attrNode);
665
+ const enumStringValues = tryGetStringLiteralValues(moduleName, filename, `attr-${attrName}`, type, program);
666
+ if (enumStringValues.length > 0) {
667
+ enumAttributes[attrName] = enumStringValues;
668
+ }
669
+ analyzeExternalAttrImport(type, program, importAttrFrom, relativePath);
670
+ }
671
+ }
672
+ else if (ts.isArrayTypeNode(type) && ts.isTypeReferenceNode(type.elementType) && ts.isIdentifier(type.elementType.typeName)) {
673
+ const { typeName } = type.elementType;
674
+ if (referencedSchemas.includes(typeName.text)) {
675
+ // 这也是一对多的反指定义
676
+ const reverseEntity = typeName.text;
677
+ if (ReversePointerRelations[reverseEntity]) {
678
+ ReversePointerRelations[reverseEntity].push(moduleName);
679
+ }
680
+ else {
681
+ (0, lodash_1.assign)(ReversePointerRelations, {
682
+ [reverseEntity]: [moduleName],
683
+ });
684
+ }
685
+ if (reverseEntity === 'Modi') {
686
+ toModi = true;
687
+ }
688
+ }
689
+ else {
690
+ throw new Error(`对象${moduleName}中定义的属性${attrName}是不可识别的数组类别`);
691
+ }
692
+ }
693
+ else {
694
+ schemaAttrs.push(attrNode);
695
+ if (ts.isUnionTypeNode(type) && ts.isLiteralTypeNode(type.types[0]) && ts.isStringLiteral(type.types[0].literal)) {
696
+ (0, assert_1.default)(ts.isIdentifier(name));
697
+ const { types } = type;
698
+ const enumValues = types.map((ele) => checkStringLiteralLegal(filename, '属性', name.text, ele));
699
+ enumAttributes[name.text] = enumValues;
700
+ }
701
+ else if (ts.isLiteralTypeNode(type) && ts.isStringLiteral(type.literal)) {
702
+ // 单个字符串的情形,目前应该没有,没测试过,先写着 by Xc 20230221
703
+ (0, assert_1.default)(ts.isIdentifier(name));
704
+ const enumValues = [
705
+ checkStringLiteralLegal(filename, '属性', name.text, type)
706
+ ];
707
+ enumAttributes[name.text] = enumValues;
708
+ }
709
+ }
710
+ if (attrName === 'entity') {
711
+ (0, assert_1.default)(ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName), `「${moduleName}」中entity属性的定义不是String<32>类型,entity是系统用于表示反指指针的保留属性,请勿他用`);
712
+ const { typeArguments } = type;
713
+ (0, assert_1.default)(type.typeName.text === 'String'
714
+ && typeArguments
715
+ && typeArguments.length === 1, `「${moduleName}」中entity属性的定义不是String<32>类型,entity是系统用于表示反指指针的保留属性,请勿他用`);
716
+ const [node] = typeArguments;
717
+ if (ts.isLiteralTypeNode(node) && ts.isNumericLiteral(node.literal)) {
718
+ if (parseInt(node.literal.text) > 32) {
719
+ (0, assert_1.default)(false, `「${moduleName}」中entity属性的定义不是String<32>类型,entity是系统用于表示反指指针的保留属性,请勿他用`);
720
+ }
721
+ else {
722
+ hasEntityAttr = true;
723
+ }
724
+ }
725
+ }
726
+ if (attrName === 'entityId') {
727
+ (0, assert_1.default)(ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName), `「${moduleName}」中entityId属性的定义不是String<64>类型,entityId是系统用于表示反指指针的保留属性,请勿他用`);
728
+ const { typeArguments } = type;
729
+ (0, assert_1.default)(type.typeName.text === 'String' && typeArguments && typeArguments.length === 1, `「${moduleName}」中entityId属性的定义不是String<64>类型,entityId是系统用于表示反指指针的保留属性,请勿他用`);
730
+ const [node] = typeArguments;
731
+ if (ts.isLiteralTypeNode(node) && ts.isNumericLiteral(node.literal)) {
732
+ if (parseInt(node.literal.text) !== 64) {
733
+ (0, assert_1.default)(false, `「${moduleName}」中entityId属性的定义不是String<64>类型,entityId是系统用于表示反指指针的保留属性,请勿他用`);
734
+ }
735
+ else {
736
+ hasEntityIdAttr = true;
737
+ }
738
+ }
739
+ }
740
+ });
741
+ // 如果继承的对象属性中有相应的定义,一样起效
742
+ heritagedResult.forEach(ele => {
743
+ if (ele?.hasEntityAttr) {
744
+ (0, assert_1.default)(!hasEntityAttr && !hasEntityIdAttr, `「${filename}」继承的对象中已经声明了entity和entityId,不可重复声明`);
745
+ (0, assert_1.default)(ele.hasEntityIdAttr);
746
+ hasEntityAttr = true;
747
+ hasEntityIdAttr = true;
748
+ }
749
+ else if (ele?.hasEntityIdAttr) {
750
+ (0, assert_1.default)(false, `「${filename}」所继承的对象中的entity和entityId没有成对出现`);
751
+ }
752
+ if (ele?.toModi) {
753
+ (0, assert_1.default)(!hasEntityAttr && !hasEntityIdAttr, `「${filename}」继承的对象中已经声明了modi,不可重复声明`);
754
+ toModi = true;
755
+ }
756
+ });
757
+ return {
758
+ hasEntityAttr,
759
+ hasEntityIdAttr,
760
+ toModi,
761
+ extendsFrom,
762
+ };
763
+ }
764
+ function analyzeReferenceSchemaFile(moduleName, filename, path, sourceFile, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, relativePath) {
765
+ let result;
766
+ ts.forEachChild(sourceFile, (node) => {
767
+ if (ts.isImportDeclaration(node)) {
768
+ analyzeImportDeclaration(node, referencedSchemas, [], filename, relativePath);
769
+ }
770
+ if (ts.isInterfaceDeclaration(node)) {
771
+ // schema 定义
772
+ if (node.name.text === 'Schema') {
773
+ result = analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, relativePath);
774
+ }
775
+ else if (!node.name.text.endsWith('Relation') && !node.name.text.endsWith('Action') && !node.name.text.endsWith('State')) {
776
+ // 本地规定的一些形状定义,直接使用
777
+ pushStatementIntoSchemaAst(moduleName, node);
778
+ }
779
+ }
780
+ if (ts.isTypeAliasDeclaration(node)) {
781
+ if (!node.name.text.endsWith('Relation') && !node.name.text.endsWith('Action') && !node.name.text.endsWith('State')) {
782
+ // 本地规定的一些形状定义,直接使用
783
+ pushStatementIntoSchemaAst(moduleName, node);
784
+ }
785
+ }
786
+ });
787
+ (0, assert_1.default)(result);
788
+ return result;
789
+ }
353
790
  function analyzeEntity(filename, path, program, relativePath) {
354
791
  const fullPath = `${path}/${filename}`;
355
792
  const sourceFile = program.getSourceFile(fullPath);
793
+ (0, assert_1.default)(sourceFile);
356
794
  const moduleName = filename.split('.')[0];
357
795
  if (Schema.hasOwnProperty(moduleName)) {
358
796
  delete ActionAsts[moduleName];
@@ -367,164 +805,37 @@ function analyzeEntity(filename, path, program, relativePath) {
367
805
  let indexes;
368
806
  let beforeSchema = true;
369
807
  let hasActionDef = false;
370
- let hasRelationDef = false;
808
+ let relations = false;
371
809
  let hasActionOrStateDef = false;
372
- let toModi = false;
373
810
  let actionType = 'crud';
374
811
  let _static = false;
375
812
  const enumAttributes = {};
376
- const additionalImports = [];
813
+ const importAttrFrom = {};
377
814
  let localeDef = undefined;
815
+ let extendsFrom;
378
816
  // let relationHierarchy: ts.ObjectLiteralExpression | undefined = undefined;
379
817
  // let reverseCascadeRelationHierarchy: ts.ObjectLiteralExpression | undefined = undefined;
818
+ let toModi = false;
380
819
  ts.forEachChild(sourceFile, (node) => {
381
820
  if (ts.isImportDeclaration(node)) {
382
- const entityImported = getEntityImported(node);
383
- if (entityImported) {
384
- referencedSchemas.push(entityImported);
385
- }
386
- else {
387
- const { moduleSpecifier, importClause } = node;
388
- if (ts.isStringLiteral(moduleSpecifier)) {
389
- const { text } = moduleSpecifier;
390
- // 和数据类型相关的会自动引入,这里忽略(见initialStatements)
391
- // 如果是相对路径,编译后的路径默认要深一层
392
- const moduleSpecifier2Text = text.startsWith('.') ? (relativePath
393
- ? path_1.default.join(relativePath, text).replace(/\\/g, '/')
394
- : path_1.default.join('..', text).replace(/\\/g, '/')) : text;
395
- additionalImports.push(factory.updateImportDeclaration(node, undefined, importClause, factory.createStringLiteral(moduleSpecifier2Text), undefined));
396
- }
397
- else {
398
- (0, assert_1.default)(false, '未处理的import方式');
399
- }
400
- }
821
+ analyzeImportDeclaration(node, referencedSchemas, [], filename, relativePath);
401
822
  }
402
823
  if (ts.isInterfaceDeclaration(node)) {
403
824
  // schema 定义
404
825
  if (node.name.text === 'Schema') {
405
- (0, assert_1.default)(!localeDef, `【${filename}】locale定义须在Schema之后`);
406
- let hasEntityAttr = false;
407
- let hasEntityIdAttr = false;
408
- const { members, heritageClauses } = node;
409
- (0, assert_1.default)(['EntityShape'].includes(heritageClauses[0].types[0].expression.text), moduleName);
410
- members.forEach((attrNode) => {
411
- const { type, name, questionToken } = attrNode;
412
- const attrName = name.text;
413
- checkNameLegal(filename, attrName, false);
414
- if (ts.isTypeReferenceNode(type)
415
- && ts.isIdentifier(type.typeName)) {
416
- if ((referencedSchemas.includes(type.typeName.text) || type.typeName.text === 'Schema')) {
417
- addRelationship(moduleName, type.typeName.text, attrName, !!questionToken);
418
- schemaAttrs.push(attrNode);
419
- }
420
- else if (type.typeName.text === 'Array') {
421
- // 这是一对多的反向指针的引用,需要特殊处理
422
- const { typeArguments } = type;
423
- (0, assert_1.default)(typeArguments.length === 1
424
- && ts.isTypeReferenceNode(typeArguments[0])
425
- && ts.isIdentifier(typeArguments[0].typeName)
426
- && referencedSchemas.includes(typeArguments[0].typeName.text), `「${filename}」非法的属性定义「${attrName}」`);
427
- const reverseEntity = typeArguments[0].typeName.text;
428
- if (ReversePointerRelations[reverseEntity]) {
429
- if (!ReversePointerRelations[reverseEntity].includes(moduleName)) {
430
- ReversePointerRelations[reverseEntity].push(moduleName);
431
- }
432
- }
433
- else {
434
- (0, lodash_1.assign)(ReversePointerRelations, {
435
- [reverseEntity]: [moduleName],
436
- });
437
- }
438
- if (reverseEntity === 'Modi') {
439
- toModi = true;
440
- }
441
- }
442
- else {
443
- schemaAttrs.push(attrNode);
444
- const enumStringValues = getStringEnumValues(filename, program, '属性', type);
445
- if (enumStringValues) {
446
- enumAttributes[attrName] = enumStringValues;
447
- }
448
- }
449
- }
450
- else if (ts.isArrayTypeNode(type) && ts.isTypeReferenceNode(type.elementType) && ts.isIdentifier(type.elementType.typeName)) {
451
- const { typeName } = type.elementType;
452
- if (referencedSchemas.includes(typeName.text)) {
453
- // 这也是一对多的反指定义
454
- const reverseEntity = typeName.text;
455
- if (ReversePointerRelations[reverseEntity]) {
456
- ReversePointerRelations[reverseEntity].push(moduleName);
457
- }
458
- else {
459
- (0, lodash_1.assign)(ReversePointerRelations, {
460
- [reverseEntity]: [moduleName],
461
- });
462
- }
463
- if (reverseEntity === 'Modi') {
464
- toModi = true;
465
- }
466
- }
467
- else {
468
- throw new Error(`对象${moduleName}中定义的属性${attrName}是不可识别的数组类别`);
469
- }
470
- }
471
- else {
472
- schemaAttrs.push(attrNode);
473
- if (ts.isUnionTypeNode(type) && ts.isLiteralTypeNode(type.types[0]) && ts.isStringLiteral(type.types[0].literal)) {
474
- (0, assert_1.default)(ts.isIdentifier(name));
475
- const { types } = type;
476
- const enumValues = types.map((ele) => checkStringLiteralLegal(filename, '属性', name.text, ele));
477
- enumAttributes[name.text] = enumValues;
478
- }
479
- else if (ts.isLiteralTypeNode(type) && ts.isStringLiteral(type.literal)) {
480
- // 单个字符串的情形,目前应该没有,没测试过,先写着 by Xc 20230221
481
- (0, assert_1.default)(ts.isIdentifier(name));
482
- const enumValues = [
483
- checkStringLiteralLegal(filename, '属性', name.text, type)
484
- ];
485
- enumAttributes[name.text] = enumValues;
486
- }
487
- }
488
- if (attrName === 'entity') {
489
- (0, assert_1.default)(ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName), `「${moduleName}」中entity属性的定义不是String<32>类型,entity是系统用于表示反指指针的保留属性,请勿他用`);
490
- const { typeArguments } = type;
491
- (0, assert_1.default)(type.typeName.text === 'String'
492
- && typeArguments
493
- && typeArguments.length === 1, `「${moduleName}」中entity属性的定义不是String<32>类型,entity是系统用于表示反指指针的保留属性,请勿他用`);
494
- const [node] = typeArguments;
495
- if (ts.isLiteralTypeNode(node) && ts.isNumericLiteral(node.literal)) {
496
- if (parseInt(node.literal.text) > 32) {
497
- (0, assert_1.default)(false, `「${moduleName}」中entity属性的定义不是String<32>类型,entity是系统用于表示反指指针的保留属性,请勿他用`);
498
- }
499
- else {
500
- hasEntityAttr = true;
501
- }
502
- }
503
- }
504
- if (attrName === 'entityId') {
505
- (0, assert_1.default)(ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName), `「${moduleName}」中entityId属性的定义不是String<64>类型,entityId是系统用于表示反指指针的保留属性,请勿他用`);
506
- const { typeArguments } = type;
507
- (0, assert_1.default)(type.typeName.text === 'String' && typeArguments && typeArguments.length === 1, `「${moduleName}」中entityId属性的定义不是String<64>类型,entityId是系统用于表示反指指针的保留属性,请勿他用`);
508
- const [node] = typeArguments;
509
- if (ts.isLiteralTypeNode(node) && ts.isNumericLiteral(node.literal)) {
510
- if (parseInt(node.literal.text) !== 64) {
511
- (0, assert_1.default)(false, `「${moduleName}」中entityId属性的定义不是String<64>类型,entityId是系统用于表示反指指针的保留属性,请勿他用`);
512
- }
513
- else {
514
- hasEntityIdAttr = true;
515
- }
516
- }
517
- }
518
- });
519
- if (hasEntityAttr && hasEntityIdAttr) {
826
+ beforeSchema = false;
827
+ const result = analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, relativePath);
828
+ if (result.hasEntityAttr && result.hasEntityIdAttr) {
520
829
  (0, lodash_1.assign)(ReversePointerEntities, {
521
830
  [moduleName]: 1,
522
831
  });
523
832
  }
524
- else if (hasEntityAttr || hasEntityIdAttr) {
525
- throw new Error(`文件「${filename}」:属性 定义中只包含${hasEntityAttr ? 'entity' : 'entityId'},不符合定义规范。entity/entityId必须联合出现,代表不定对象的反向指针`);
833
+ else if (result.hasEntityAttr || result.hasEntityIdAttr) {
834
+ throw new Error(`文件「${filename}」:属性 定义中只包含${result.hasEntityAttr ? 'entity' : 'entityId'},不符合定义规范。entity/entityId必须联合出现,代表不定对象的反向指针`);
526
835
  }
527
836
  beforeSchema = false;
837
+ toModi = result.toModi;
838
+ extendsFrom = result.extendsFrom;
528
839
  // 对于不是Modi和Oper的对象,全部建立和ModiEntity的反指关系
529
840
  if (!['Modi', 'Oper', 'OperEntity', 'ModiEntity'].includes(moduleName) && !toModi) {
530
841
  if (ReversePointerRelations['ModiEntity'] && !ReversePointerRelations['ModiEntity'].includes(moduleName)) {
@@ -557,7 +868,7 @@ function analyzeEntity(filename, path, program, relativePath) {
557
868
  hasActionDef = true;
558
869
  const modifiers = [factory.createModifier(ts.SyntaxKind.ExportKeyword)];
559
870
  pushStatementIntoActionAst(moduleName, factory.updateTypeAliasDeclaration(node, modifiers, factory.createIdentifier('ParticularAction'), node.typeParameters, node.type), sourceFile);
560
- dealWithActions(moduleName, filename, node.type, program, sourceFile);
871
+ dealWithActionTypeNode(moduleName, filename, node.type, program, sourceFile);
561
872
  }
562
873
  else if (node.name.text === 'Relation') {
563
874
  (0, assert_1.default)(!localeDef, `【${filename}】locale定义须在Relation之后`);
@@ -567,13 +878,26 @@ function analyzeEntity(filename, path, program, relativePath) {
567
878
  (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})`);
568
879
  relationValues.push(node.type.literal.text);
569
880
  }
881
+ else if (ts.isTypeReferenceNode(node.type)) {
882
+ const relationStrings = tryGetStringLiteralValues(moduleName, filename, 'relation', node.type, program);
883
+ (0, assert_1.default)(relationStrings.length > 0);
884
+ relationValues.push(...relationStrings);
885
+ }
570
886
  else {
571
- (0, assert_1.default)(ts.isUnionTypeNode(node.type), `Relation的定义只能是string类型(${filename})`);
572
- relationValues.push(...node.type.types.map((ele) => {
573
- (0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal), `Relation的定义只能是string类型(${filename})`);
574
- (0, assert_1.default)(ele.literal.text.length < env_1.STRING_LITERAL_MAX_LENGTH, `Relation定义的字符串长度不长于${env_1.STRING_LITERAL_MAX_LENGTH}(${filename},${ele.literal.text})`);
575
- return ele.literal.text;
576
- }));
887
+ (0, assert_1.default)(ts.isUnionTypeNode(node.type), `Relation的定义只能是string类型,或者string union类型,或者两者的union(${filename})`);
888
+ node.type.types.forEach((ele) => {
889
+ if (ts.isLiteralTypeNode(ele)) {
890
+ (0, assert_1.default)(ts.isStringLiteral(ele.literal), `Relation的定义只能是string类型(${filename})`);
891
+ (0, assert_1.default)(ele.literal.text.length < env_1.STRING_LITERAL_MAX_LENGTH, `Relation定义的字符串长度不长于${env_1.STRING_LITERAL_MAX_LENGTH}(${filename},${ele.literal.text})`);
892
+ relationValues.push(ele.literal.text);
893
+ }
894
+ else {
895
+ (0, assert_1.default)(ts.isTypeReferenceNode(ele), `Relation的定义只能是string类型,或者string union类型,或者两者的union(${filename})`);
896
+ const relationStrings = tryGetStringLiteralValues(moduleName, filename, 'relation', ele, program);
897
+ (0, assert_1.default)(relationStrings.length > 0);
898
+ relationValues.push(...relationStrings);
899
+ }
900
+ });
577
901
  }
578
902
  // 对UserEntityGrant对象,建立相应的反指关系
579
903
  // UserEntityGrant结构改变,不再建立,by Xc 20231101
@@ -609,7 +933,7 @@ function analyzeEntity(filename, path, program, relativePath) {
609
933
  ['UserRelation']: [moduleName],
610
934
  });
611
935
  }
612
- hasRelationDef = node;
936
+ relations = relationValues;
613
937
  }
614
938
  else if (node.name.text.endsWith('Action') || node.name.text.endsWith('State')) {
615
939
  (0, assert_1.default)(!localeDef, `【${filename}】locale定义须在Action/State之后`);
@@ -643,10 +967,10 @@ function analyzeEntity(filename, path, program, relativePath) {
643
967
  const [actionNode, stateNode] = typeArguments;
644
968
  (0, assert_1.default)(ts.isTypeReferenceNode(actionNode));
645
969
  (0, assert_1.default)(ts.isTypeReferenceNode(stateNode));
646
- (0, assert_1.default)(getStringEnumValues(filename, program, 'action', actionNode), `文件${filename}中的action${actionNode.typeName.text}定义不是字符串类型`);
647
- const enumStateValues = getStringEnumValues(filename, program, 'state', stateNode);
648
- (0, assert_1.default)(enumStateValues, `文件${filename}中的state${stateNode.typeName.text}定义不是字符串类型`);
970
+ const enumStateValues = tryGetStringLiteralValues(moduleName, filename, 'state', stateNode, program);
971
+ (0, assert_1.default)(enumStateValues.length > 0, `文件${filename}中的state${stateNode.typeName.text}定义不是字符串类型`);
649
972
  pushStatementIntoActionAst(moduleName, node, sourceFile);
973
+ dealWithActionDefInitializer(moduleName, declaration.initializer, program);
650
974
  (0, assert_1.default)(ts.isIdentifier(declaration.name));
651
975
  const adName = declaration.name.text.slice(0, declaration.name.text.length - 9);
652
976
  const attr = adName.concat('State');
@@ -764,7 +1088,7 @@ function analyzeEntity(filename, path, program, relativePath) {
764
1088
  else {
765
1089
  checkLocaleExpressionPropertyExists(declaration, 'action', false, filename);
766
1090
  }
767
- if (hasRelationDef) {
1091
+ if (relations) {
768
1092
  // 检查每种locale定义中都应该有'r'域
769
1093
  checkLocaleExpressionPropertyExists(declaration, 'r', true, filename);
770
1094
  }
@@ -794,6 +1118,35 @@ function analyzeEntity(filename, path, program, relativePath) {
794
1118
  _static = true; // static如果有值只能为true
795
1119
  }
796
1120
  };
1121
+ const dealWithEntityDesc = (declaration) => {
1122
+ if (ts.isObjectLiteralExpression(declaration)) {
1123
+ const { properties } = declaration;
1124
+ const localesProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'locales');
1125
+ (0, assert_1.default)(ts.isPropertyAssignment(localesProperty));
1126
+ dealWithLocales(localesProperty.initializer);
1127
+ const indexesProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'indexes');
1128
+ if (indexesProperty) {
1129
+ (0, assert_1.default)(ts.isPropertyAssignment(indexesProperty));
1130
+ dealWithIndexes(indexesProperty.initializer);
1131
+ }
1132
+ const configurationProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'configuration');
1133
+ if (configurationProperty) {
1134
+ (0, assert_1.default)(ts.isPropertyAssignment(configurationProperty));
1135
+ dealWithConfiguration(configurationProperty.initializer);
1136
+ }
1137
+ }
1138
+ else if (ts.isIdentifier(declaration)) {
1139
+ const checker = program.getTypeChecker();
1140
+ const symbol = checker.getSymbolAtLocation(declaration);
1141
+ const original = checker.getAliasedSymbol(symbol);
1142
+ /**
1143
+ * 目前只研究出来怎么得到originSymbol,但只能拿到其类型定义(在d.ts中)
1144
+ * 拿不到数据定义(在js中)(original.declaration.initializer是undefined)
1145
+ */
1146
+ (0, assert_1.default)(false, '用变量赋值给entityDesc暂时还解析不了');
1147
+ console.log(original);
1148
+ }
1149
+ };
797
1150
  declarations.forEach((declaration) => {
798
1151
  if (declaration.type && ts.isTypeReferenceNode(declaration.type) && ts.isIdentifier(declaration.type.typeName) && declaration.type.typeName.text === 'ActionDef') {
799
1152
  dealWithActionDef(declaration);
@@ -833,7 +1186,7 @@ function analyzeEntity(filename, path, program, relativePath) {
833
1186
  (0, assert_1.default)(ts.isLiteralTypeNode(typeArguments[1])
834
1187
  && ts.isStringLiteral(typeArguments[1].literal), `${filename}中locale类型定义的第二个参数不是字符串`);
835
1188
  }
836
- if (hasRelationDef) {
1189
+ if (relations) {
837
1190
  (0, assert_1.default)(ts.isTypeReferenceNode(typeArguments[2])
838
1191
  && ts.isIdentifier(typeArguments[2].typeName)
839
1192
  && typeArguments[2].typeName.text === 'Relation', `${filename}中的locale类型定义的第三个参数不是Relation`);
@@ -858,21 +1211,9 @@ function analyzeEntity(filename, path, program, relativePath) {
858
1211
  dealWithConfiguration(declaration.initializer);
859
1212
  }
860
1213
  else if (declaration.type && ts.isTypeReferenceNode(declaration.type) && ts.isIdentifier(declaration.type.typeName) && declaration.type.typeName.text === 'EntityDesc') {
861
- (0, assert_1.default)(ts.isObjectLiteralExpression(declaration.initializer));
862
- const { properties } = declaration.initializer;
863
- const localesProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'locales');
864
- (0, assert_1.default)(ts.isPropertyAssignment(localesProperty));
865
- dealWithLocales(localesProperty.initializer);
866
- const indexesProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'indexes');
867
- if (indexesProperty) {
868
- (0, assert_1.default)(ts.isPropertyAssignment(indexesProperty));
869
- dealWithIndexes(indexesProperty.initializer);
870
- }
871
- const configurationProperty = properties.find(ele => ts.isPropertyAssignment(ele) && ts.isIdentifier(ele.name) && ele.name.text === 'configuration');
872
- if (configurationProperty) {
873
- (0, assert_1.default)(ts.isPropertyAssignment(configurationProperty));
874
- dealWithConfiguration(configurationProperty.initializer);
875
- }
1214
+ const { initializer } = declaration;
1215
+ (0, assert_1.default)(initializer);
1216
+ dealWithEntityDesc(initializer);
876
1217
  }
877
1218
  else {
878
1219
  throw new Error(`${moduleName}:不能理解的定义内容${declaration.name.text}`);
@@ -907,9 +1248,10 @@ function analyzeEntity(filename, path, program, relativePath) {
907
1248
  toModi,
908
1249
  actionType,
909
1250
  static: _static,
910
- hasRelationDef,
1251
+ relations,
911
1252
  enumAttributes,
912
- additionalImports,
1253
+ importAttrFrom,
1254
+ extendsFrom,
913
1255
  };
914
1256
  if (hasFulltextIndex) {
915
1257
  (0, lodash_1.assign)(schema, {
@@ -973,7 +1315,7 @@ function constructSchema(statements, entity) {
973
1315
  if (ts.isIdentifier(typeName)) {
974
1316
  const { text } = typeName;
975
1317
  const text2 = text === 'Schema' ? entity : text;
976
- const manyToOneItem = manyToOneSet && manyToOneSet.find(([refEntity, attrName]) => refEntity === text2 && attrName === attrName);
1318
+ const manyToOneItem = manyToOneSet && manyToOneSet.find(([refEntity, attrName2]) => refEntity === text2 && attrName2 === attrName);
977
1319
  if (manyToOneItem) {
978
1320
  referenceEntities.push(text2);
979
1321
  members2.push(factory.createPropertySignature(undefined, name, questionToken, questionToken ? factory.createUnionTypeNode([
@@ -2373,7 +2715,7 @@ function constructOperations(statements, entity) {
2373
2715
  if (ActionAsts[entity]) {
2374
2716
  actionTypeNodes.push(factory.createTypeReferenceNode('ParticularAction'));
2375
2717
  }
2376
- if (Schema[entity].hasRelationDef || entity === 'User') {
2718
+ if (Schema[entity].relations || entity === 'User') {
2377
2719
  actionTypeNodes.push(factory.createTypeReferenceNode('RelationAction'));
2378
2720
  }
2379
2721
  if (process.env.COMPLING_AS_LIB) {
@@ -2623,6 +2965,7 @@ const initialStatements = () => [
2623
2965
  factory.createImportSpecifier(false, factory.createIdentifier("Selection"), factory.createIdentifier("OakSelection")),
2624
2966
  factory.createImportSpecifier(false, factory.createIdentifier("MakeAction"), factory.createIdentifier("OakMakeAction")),
2625
2967
  factory.createImportSpecifier(false, undefined, factory.createIdentifier("AggregationResult")),
2968
+ factory.createImportSpecifier(false, undefined, factory.createIdentifier("EntityShape")),
2626
2969
  ])), factory.createStringLiteral(`${(0, env_1.TYPE_PATH_IN_OAK_DOMAIN)()}Entity`), undefined)
2627
2970
  ];
2628
2971
  function outputSubQuery(outputDir, printer) {
@@ -2687,45 +3030,36 @@ function outputEntityDict(outputDir, printer) {
2687
3030
  }
2688
3031
  function outputSchema(outputDir, printer) {
2689
3032
  for (const entity in Schema) {
3033
+ const { importAttrFrom } = Schema[entity];
2690
3034
  const statements = initialStatements();
2691
3035
  if (ActionAsts[entity]) {
2692
- const { importedFrom, actionDefNames } = ActionAsts[entity];
2693
- const localActions = ['Action', 'ParticularAction'];
2694
- for (const a in importedFrom) {
2695
- (0, assert_1.default)(a.endsWith('Action'));
2696
- const s = a.slice(0, a.length - 6).concat('State');
2697
- if (importedFrom[a] === 'local' && actionDefNames.includes((0, string_1.firstLetterLowerCase)(a.slice(0, a.length - 6)))) {
2698
- localActions.push(s);
2699
- }
2700
- else if (actionDefNames.includes((0, string_1.firstLetterLowerCase)(a.slice(0, a.length - 6)))) {
2701
- // 现在源文件中的import语句保留下来了
2702
- // const { moduleSpecifier } = importedFrom[a] as ts.ImportDeclaration;
2703
- // statements.push(
2704
- // factory.createImportDeclaration(
2705
- // undefined,
2706
- // undefined,
2707
- // factory.createImportClause(
2708
- // false,
2709
- // undefined,
2710
- // factory.createNamedImports(
2711
- // [
2712
- // factory.createImportSpecifier(
2713
- // false,
2714
- // undefined,
2715
- // factory.createIdentifier(s)
2716
- // )
2717
- // ]
2718
- // )
2719
- // ),
2720
- // moduleSpecifier,
2721
- // undefined
2722
- // )
2723
- // );
2724
- }
2725
- }
2726
- statements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports(localActions.map(ele => factory.createImportSpecifier(false, undefined, factory.createIdentifier(ele))))), factory.createStringLiteral('./Action'), undefined), factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
3036
+ const { importStateFrom } = ActionAsts[entity];
3037
+ const fromLocalActionSpecifiers = ['Action', 'ParticularAction'];
3038
+ const fromExtenalStates = {};
3039
+ for (const state in importStateFrom) {
3040
+ (0, assert_1.default)(state.endsWith('State'));
3041
+ if (importStateFrom[state][0] === './') {
3042
+ // 本地定义的State从 ./Action 中获取
3043
+ fromLocalActionSpecifiers.push(state);
3044
+ }
3045
+ else {
3046
+ // 否则从原来的import specifiers当中获取
3047
+ // todo 在additionalImports中如果有则去重
3048
+ const [from, propertyName] = importStateFrom[state];
3049
+ if (fromExtenalStates[from]) {
3050
+ fromExtenalStates[from].push([state, propertyName]);
3051
+ }
3052
+ else {
3053
+ fromExtenalStates[from] = [[state, propertyName]];
3054
+ }
3055
+ }
3056
+ }
3057
+ statements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports(fromLocalActionSpecifiers.map(ele => factory.createImportSpecifier(false, undefined, factory.createIdentifier(ele))))), factory.createStringLiteral('./Action'), undefined), factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
2727
3058
  factory.createImportSpecifier(false, undefined, factory.createIdentifier("RelationAction")),
2728
3059
  ])), factory.createStringLiteral((0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)()), undefined));
3060
+ for (const external in fromExtenalStates) {
3061
+ statements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports(fromExtenalStates[external].map(ele => factory.createImportSpecifier(false, ele[1] === undefined ? undefined : factory.createIdentifier(ele[1]), factory.createIdentifier(ele[0]))))), factory.createStringLiteral(external), undefined));
3062
+ }
2729
3063
  }
2730
3064
  else {
2731
3065
  statements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
@@ -2737,9 +3071,19 @@ function outputSchema(outputDir, printer) {
2737
3071
  factory.createImportSpecifier(false, undefined, factory.createIdentifier("RelationAction")),
2738
3072
  ])), factory.createStringLiteral((0, env_1.ACTION_CONSTANT_IN_OAK_DOMAIN)()), undefined));
2739
3073
  }
2740
- const { additionalImports } = Schema[entity];
2741
- if (additionalImports?.length > 0) {
2742
- statements.push(...additionalImports);
3074
+ // 从外部引入的属性
3075
+ const fromExternalImportAttrs = {};
3076
+ for (const attr in importAttrFrom) {
3077
+ const [from, propertyName] = importAttrFrom[attr];
3078
+ if (fromExternalImportAttrs[from]) {
3079
+ fromExternalImportAttrs[from].push([attr, propertyName]);
3080
+ }
3081
+ else {
3082
+ fromExternalImportAttrs[from] = [[attr, propertyName]];
3083
+ }
3084
+ }
3085
+ for (const external in fromExternalImportAttrs) {
3086
+ statements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports(fromExternalImportAttrs[external].map(ele => factory.createImportSpecifier(false, ele[1] === undefined ? undefined : factory.createIdentifier(ele[1]), factory.createIdentifier(ele[0]))))), factory.createStringLiteral(external), undefined));
2743
3087
  }
2744
3088
  // Relation定义加入
2745
3089
  /* if (typeof Schema[entity].hasRelationDef === 'object' && ts.isTypeAliasDeclaration(Schema[entity].hasRelationDef as ts.Node)) {
@@ -2770,7 +3114,7 @@ function outputSchema(outputDir, printer) {
2770
3114
  else {
2771
3115
  makeActionArguments.push(factory.createTypeReferenceNode(OriginActionDict[Schema[entity].actionType]));
2772
3116
  }
2773
- if (Schema[entity].hasRelationDef || entity === 'User') {
3117
+ if (Schema[entity].relations || entity === 'User') {
2774
3118
  makeActionArguments.push(factory.createTypeReferenceNode('RelationAction'));
2775
3119
  }
2776
3120
  const actionTypeNode = factory.createTypeReferenceNode(factory.createIdentifier('OakMakeAction'), makeActionArguments.length === 1 ? makeActionArguments : [factory.createUnionTypeNode(makeActionArguments)]);
@@ -2808,7 +3152,8 @@ function outputSchema(outputDir, printer) {
2808
3152
  );
2809
3153
  } */
2810
3154
  statements.push(factory.createTypeAliasDeclaration([factory.createModifier(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier("EntityDef"), undefined, factory.createTypeLiteralNode(EntityDefAttrs)));
2811
- const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements), Schema[entity].sourceFile);
3155
+ // 现在支持Schema extends,其继承的对象解析来自另一个文件,故不能再用原sourceFile来生成,否则printer会用sourceFile中的originText去取stringLiteral
3156
+ const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements), undefined);
2812
3157
  const fileName = path_1.default.join(outputDir, entity, 'Schema.ts');
2813
3158
  (0, fs_1.writeFileSync)(fileName, result, { flag: 'w' });
2814
3159
  }
@@ -2817,18 +3162,48 @@ function outputAction(outputDir, printer) {
2817
3162
  const actionDictStatements = [];
2818
3163
  const propertyAssignments = [];
2819
3164
  for (const entity in ActionAsts) {
2820
- const { sourceFile, statements, importedFrom, actionDefNames } = ActionAsts[entity];
3165
+ const { sourceFile, statements, importActionFrom, importStateFrom, importActionDefFrom, actionDefNames } = ActionAsts[entity];
2821
3166
  const importStatements = [];
2822
- for (const k in importedFrom) {
2823
- (0, assert_1.default)(k.endsWith('Action'));
2824
- if (importedFrom[k] !== 'local') {
2825
- importStatements.push(importedFrom[k]);
3167
+ const fromExternalImports = {};
3168
+ for (const state in importStateFrom) {
3169
+ (0, assert_1.default)(state.endsWith('State'));
3170
+ const [from, propertyName] = importStateFrom[state];
3171
+ if (from !== './') {
3172
+ if (fromExternalImports[from]) {
3173
+ fromExternalImports[from].push([state, propertyName]);
3174
+ }
3175
+ else {
3176
+ fromExternalImports[from] = [[state, propertyName]];
3177
+ }
2826
3178
  }
2827
3179
  }
2828
- /* const actionDiff = difference(actionNames, actionDefNames);
2829
- if (actionDiff.length > 0) {
2830
- throw new Error(`action not conform to actionDef: ${actionDiff.join(',')}, entity: ${entity}`);
2831
- } */
3180
+ for (const action in importActionFrom) {
3181
+ (0, assert_1.default)(action.endsWith('Action'));
3182
+ const [from, propertyName] = importActionFrom[action];
3183
+ if (from !== './') {
3184
+ if (fromExternalImports[from]) {
3185
+ fromExternalImports[from].push([action, propertyName]);
3186
+ }
3187
+ else {
3188
+ fromExternalImports[from] = [[action, propertyName]];
3189
+ }
3190
+ }
3191
+ }
3192
+ for (const def in importActionDefFrom) {
3193
+ (0, assert_1.default)(def.endsWith('ActionDef'));
3194
+ const [from, propertyName] = importActionDefFrom[def];
3195
+ if (from !== './') {
3196
+ if (fromExternalImports[from]) {
3197
+ fromExternalImports[from].push([def, propertyName]);
3198
+ }
3199
+ else {
3200
+ fromExternalImports[from] = [[def, propertyName]];
3201
+ }
3202
+ }
3203
+ }
3204
+ for (const external in fromExternalImports) {
3205
+ statements.splice(0, 0, factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports(fromExternalImports[external].map(ele => factory.createImportSpecifier(false, ele[1] === undefined ? undefined : factory.createIdentifier(ele[1]), factory.createIdentifier(ele[0]))))), factory.createStringLiteral(external), undefined));
3206
+ }
2832
3207
  statements.push(factory.createVariableStatement([factory.createModifier(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("ActionDefDict"), undefined, undefined, factory.createObjectLiteralExpression(actionDefNames.map(ele => factory.createPropertyAssignment(factory.createIdentifier(`${ele}State`), factory.createIdentifier(`${(0, string_1.firstLetterUpperCase)(ele)}ActionDef`))), true))], ts.NodeFlags.Const)));
2833
3208
  /* const result = printer.printNode(
2834
3209
  ts.EmitHint.Unspecified,
@@ -3073,7 +3448,7 @@ function outputStorage(outputDir, printer) {
3073
3448
  const entityAssignments = [];
3074
3449
  for (const entity in Schema) {
3075
3450
  const indexExpressions = [];
3076
- const { sourceFile, inModi, indexes, toModi, actionType, static: _static, hasRelationDef } = Schema[entity];
3451
+ const { sourceFile, inModi, indexes, toModi, actionType, static: _static, relations } = Schema[entity];
3077
3452
  const fromSchemaSpecifiers = [
3078
3453
  factory.createImportSpecifier(false, undefined, factory.createIdentifier("OpSchema"))
3079
3454
  ];
@@ -3113,7 +3488,7 @@ function outputStorage(outputDir, printer) {
3113
3488
  }
3114
3489
  }
3115
3490
  }
3116
- if (Schema[entity].hasRelationDef || entity === 'User') {
3491
+ if (Schema[entity].relations || entity === 'User') {
3117
3492
  needImportActions.push(factory.createImportSpecifier(false, undefined, factory.createIdentifier("relationActions")));
3118
3493
  }
3119
3494
  if (needImportActions.length > 0) {
@@ -3155,23 +3530,8 @@ function outputStorage(outputDir, printer) {
3155
3530
  )
3156
3531
  );
3157
3532
  } */
3158
- if (hasRelationDef) {
3159
- const { type } = hasRelationDef;
3160
- if (ts.isUnionTypeNode(type)) {
3161
- const { types } = type;
3162
- const relationTexts = types.map(ele => {
3163
- (0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
3164
- return ele.literal.text;
3165
- });
3166
- propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("relation"), factory.createArrayLiteralExpression(relationTexts.map(ele => factory.createStringLiteral(ele)))));
3167
- }
3168
- else {
3169
- (0, assert_1.default)(ts.isLiteralTypeNode(type));
3170
- (0, assert_1.default)(ts.isStringLiteral(type.literal));
3171
- propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("relation"), factory.createArrayLiteralExpression([
3172
- type.literal
3173
- ])));
3174
- }
3533
+ if (relations) {
3534
+ propertyAssignments.push(factory.createPropertyAssignment(factory.createIdentifier("relation"), factory.createArrayLiteralExpression(relations.map(ele => factory.createStringLiteral(ele)))));
3175
3535
  }
3176
3536
  const sdTypeArguments = [
3177
3537
  factory.createTypeReferenceNode(factory.createIdentifier("OpSchema"), undefined)
@@ -3211,10 +3571,10 @@ function addReverseRelationship() {
3211
3571
  }
3212
3572
  }
3213
3573
  function outputIndexTs(outputDir) {
3214
- const indexTs = `export * from './EntityDict';
3215
- export * from './Storage';
3216
- export * from './ActionDefDict';
3217
- export * from './Relation';
3574
+ const indexTs = `export * from './EntityDict';
3575
+ export * from './Storage';
3576
+ export * from './ActionDefDict';
3577
+ export * from './Relation';
3218
3578
  `;
3219
3579
  const filename = path_1.default.join(outputDir, 'index.ts');
3220
3580
  (0, fs_1.writeFileSync)(filename, indexTs, { flag: 'w' });
@@ -3342,155 +3702,407 @@ exports.registerDeducedRelationMap = registerDeducedRelationMap;
3342
3702
  * 输出所有和User相关的对象的后继
3343
3703
  * 此函数不再使用
3344
3704
  */
3345
- function outputRelation(outputDir, printer) {
3346
- const ExcludedEntities = ['Oper', 'User', 'OperEntity', 'Modi', 'ModiEntity', 'UserRelation', 'Relation', 'RelationAuth', 'ActionAuth'];
3347
- const actionPath = [];
3348
- const relationPath = [];
3349
- const outputRecursively = (root, entity, path, paths, isRelation) => {
3350
- if (ExcludedEntities.includes(entity)) {
3351
- return;
3352
- }
3353
- if (IGNORED_RELATION_PATH_MAP[entity]?.find((ele) => path.includes(ele))) {
3354
- return;
3355
- }
3356
- if (paths.length > 12) {
3357
- throw new Error('对象之间的关系深度过长,请优化设计加以避免');
3358
- }
3359
- actionPath.push([(0, string_1.firstLetterLowerCase)(entity), path, root, isRelation, paths]);
3360
- if (Schema[entity].hasRelationDef) {
3361
- // assert(!DEDUCED_RELATION_MAP[entity], `${entity}对象定义了deducedRelationMap,但它有relation`);
3362
- relationPath.push([(0, string_1.firstLetterLowerCase)(entity), path, root, isRelation]);
3363
- }
3364
- const { [entity]: parent } = OneToMany;
3365
- if (parent) {
3366
- parent.forEach(([child, foreignKey]) => {
3367
- const child2 = (0, string_1.firstLetterLowerCase)(child);
3368
- if (child === entity) {
3369
- // 如果有层级关系对象,最多找3层。同时这里只找本身存在relation关系的对象,因为如果对象上没有relation,则其上的公共路径应当可以维护住层级关系
3370
- // 例如在jichuang项目中,house上没有relation,通过其park外键所维护的路径不需要遍历其父亲。而parkCluster因为有relation,所以必须构造以之为根的所有的可能路径
3371
- // 如果不是以之为根的,同样可以根据其上的公共路径去查找,parkCluster.system和parkCluster.parent.system必然是一样的
3372
- if (!Schema[entity].hasRelationDef) {
3373
- return;
3374
- }
3375
- if (paths.find(ele => ele !== child2) || paths.length > 2) {
3376
- return;
3377
- }
3378
- }
3379
- else if (paths.indexOf(child2) >= 0) {
3380
- // 除了层级之外的递归直接忽略
3381
- return;
3382
- }
3383
- if (IGNORED_FOREIGN_KEY_MAP[child2]?.includes(foreignKey)) {
3384
- // 忽略的路径放弃
3385
- return;
3386
- }
3387
- if (DEDUCED_RELATION_MAP[child] === foreignKey) {
3388
- // 如果子对象本身由父对象推定,也放弃
3389
- return;
3390
- }
3391
- const fk = foreignKey === 'entity' ? (0, string_1.firstLetterLowerCase)(entity) : foreignKey;
3392
- const path2 = path ? `${fk}.${path}` : fk;
3393
- outputRecursively(root, child, path2, paths.concat([(0, string_1.firstLetterLowerCase)(entity)]), isRelation);
3394
- });
3395
- }
3396
- };
3397
- // 所有属性中有指向user的对象
3398
- const { User } = OneToMany;
3399
- User.forEach(([entity3, foreignKey]) => {
3400
- const fk = foreignKey === 'entity' ? 'user' : foreignKey;
3401
- if (!IGNORED_FOREIGN_KEY_MAP[(0, string_1.firstLetterLowerCase)(entity3)]?.includes(foreignKey)) {
3402
- outputRecursively((0, string_1.firstLetterLowerCase)(entity3), entity3, fk, [fk], false);
3403
- }
3404
- });
3405
- // 所有带relation的对象
3406
- const hasRelationEntities = Object.keys(Schema).filter((entity) => Schema[entity].hasRelationDef);
3407
- hasRelationEntities.forEach((entity3) => {
3408
- outputRecursively((0, string_1.firstLetterLowerCase)(entity3), entity3, '', [], true);
3409
- });
3410
- actionPath.sort((ele1, ele2) => {
3411
- // 先按sourceEntity来排序
3412
- if (ele1[0] > ele2[0]) {
3413
- return 1;
3414
- }
3415
- else if (ele1[0] < ele2[0]) {
3416
- return -1;
3417
- }
3418
- else {
3419
- // 再按destEntity
3420
- if (ele1[2] > ele2[2]) {
3421
- return 1;
3422
- }
3423
- else if (ele1[2] < ele2[2]) {
3424
- return -1;
3425
- }
3426
- else {
3427
- // 最后按paths的长度倒排
3428
- return ele1[4].length - ele2[4].length;
3429
- }
3430
- }
3431
- });
3432
- const entityRelations = [];
3433
- for (const entity in Schema) {
3434
- const { hasRelationDef } = Schema[entity];
3435
- if (hasRelationDef) {
3436
- const { type } = hasRelationDef;
3437
- if (ts.isUnionTypeNode(type)) {
3438
- const { types } = type;
3439
- const relations = types.map(ele => {
3440
- (0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
3441
- return ele.literal.text;
3442
- });
3443
- entityRelations.push([(0, string_1.firstLetterLowerCase)(entity), relations]);
3444
- }
3445
- else {
3446
- (0, assert_1.default)(ts.isLiteralTypeNode(type));
3447
- (0, assert_1.default)(ts.isStringLiteral(type.literal));
3448
- const relations = [type.literal.text];
3449
- entityRelations.push([(0, string_1.firstLetterLowerCase)(entity), relations]);
3450
- }
3451
- }
3452
- }
3453
- const stmts = [
3454
- factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([
3455
- factory.createImportSpecifier(false, undefined, factory.createIdentifier("AuthCascadePath")),
3456
- factory.createImportSpecifier(false, undefined, factory.createIdentifier("AuthDeduceRelationMap"))
3457
- ])), factory.createStringLiteral(`${(0, env_1.TYPE_PATH_IN_OAK_DOMAIN)(1)}Entity`), undefined),
3458
- factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, undefined, factory.createIdentifier("EntityDict"))])), factory.createStringLiteral("./EntityDict"), undefined),
3459
- factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("CreateOperationData"), factory.createIdentifier("Relation"))])), factory.createStringLiteral("./Relation/Schema"), undefined),
3460
- factory.createVariableStatement([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("ActionCascadePathGraph"), undefined, factory.createArrayTypeNode(factory.createTypeReferenceNode(factory.createIdentifier("AuthCascadePath"), [factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)])), factory.createArrayLiteralExpression(actionPath.map(([entity, path, root, isRelation]) => factory.createArrayLiteralExpression([
3461
- factory.createStringLiteral(entity),
3462
- factory.createStringLiteral(path),
3463
- factory.createStringLiteral(root),
3464
- isRelation ? factory.createTrue() : factory.createFalse()
3465
- ], false)), true))], ts.NodeFlags.Const)),
3466
- factory.createVariableStatement([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("RelationCascadePathGraph"), undefined, factory.createArrayTypeNode(factory.createTypeReferenceNode(factory.createIdentifier("AuthCascadePath"), [factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)])), factory.createArrayLiteralExpression(relationPath.map(([entity, path, root, isRelation]) => factory.createArrayLiteralExpression([
3467
- factory.createStringLiteral(entity),
3468
- factory.createStringLiteral(path),
3469
- factory.createStringLiteral(root),
3470
- isRelation ? factory.createTrue() : factory.createFalse()
3471
- ], false)), true))], ts.NodeFlags.Const)),
3472
- factory.createVariableStatement([factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("relations"), undefined, factory.createArrayTypeNode(factory.createTypeReferenceNode(factory.createIdentifier("Relation"), undefined)), factory.createArrayLiteralExpression((0, lodash_1.flatten)(entityRelations.map(([entity, relations]) => relations.map((relation) => factory.createObjectLiteralExpression([
3473
- factory.createPropertyAssignment(factory.createIdentifier("id"), factory.createStringLiteral((0, uuid_1.formUuid)(entity, relation))),
3474
- factory.createPropertyAssignment(factory.createIdentifier("entity"), factory.createStringLiteral(entity)),
3475
- factory.createPropertyAssignment(factory.createIdentifier("name"), factory.createStringLiteral(relation))
3476
- ], true)))), true))], ts.NodeFlags.Const))
3477
- ];
3478
- stmts.push(factory.createVariableStatement([
3479
- factory.createToken(ts.SyntaxKind.ExportKeyword)
3480
- ], factory.createVariableDeclarationList([
3481
- factory.createVariableDeclaration(factory.createIdentifier("deducedRelationMap"), undefined, factory.createTypeReferenceNode(factory.createIdentifier("AuthDeduceRelationMap"), [factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)]), factory.createObjectLiteralExpression(Object.keys(DEDUCED_RELATION_MAP).map(ele => factory.createPropertyAssignment(factory.createIdentifier((0, string_1.firstLetterLowerCase)(ele)), factory.createStringLiteral(DEDUCED_RELATION_MAP[ele]))), true))
3482
- ], ts.NodeFlags.Const)));
3483
- stmts.push(factory.createVariableStatement([
3484
- factory.createToken(ts.SyntaxKind.ExportKeyword)
3485
- ], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("selectFreeEntities"), undefined, factory.createArrayTypeNode(factory.createParenthesizedType(factory.createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)))), factory.createArrayLiteralExpression(SELECT_FREE_ENTITIES.map(ele => factory.createStringLiteral(ele)), false))], ts.NodeFlags.Const)), factory.createVariableStatement([
3486
- factory.createToken(ts.SyntaxKind.ExportKeyword)
3487
- ], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("updateFreeEntities"), undefined, factory.createArrayTypeNode(factory.createParenthesizedType(factory.createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)))), factory.createArrayLiteralExpression(UPDATE_FREE_ENTITIES.map(ele => factory.createStringLiteral(ele)), false))], ts.NodeFlags.Const)), factory.createVariableStatement([
3488
- factory.createToken(ts.SyntaxKind.ExportKeyword)
3489
- ], factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("createFreeEntities"), undefined, factory.createArrayTypeNode(factory.createParenthesizedType(factory.createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, factory.createTypeReferenceNode(factory.createIdentifier("EntityDict"), undefined)))), factory.createArrayLiteralExpression(CREATE_FREE_ENTITIES.map(ele => factory.createStringLiteral(ele)), false))], ts.NodeFlags.Const)));
3490
- const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(stmts), ts.createSourceFile("someFileName.ts", "", ts.ScriptTarget.Latest, /*setParentNodes*/ false, ts.ScriptKind.TS));
3491
- const filename = path_1.default.join(outputDir, 'Relation.ts');
3492
- (0, fs_1.writeFileSync)(filename, result, { flag: 'w' });
3493
- }
3705
+ // function outputRelation(outputDir: string, printer: ts.Printer) {
3706
+ // const ExcludedEntities = ['Oper', 'User', 'OperEntity', 'Modi', 'ModiEntity', 'UserRelation', 'Relation', 'RelationAuth', 'ActionAuth'];
3707
+ // const actionPath: [string, string, string, boolean, string[]][] = [];
3708
+ // const relationPath: [string, string, string, boolean][] = [];
3709
+ // const outputRecursively = (root: string, entity: string, path: string, paths: string[], isRelation: boolean) => {
3710
+ // if (ExcludedEntities.includes(entity)) {
3711
+ // return;
3712
+ // }
3713
+ // if (IGNORED_RELATION_PATH_MAP[entity]?.find(
3714
+ // (ele) => path.includes(ele)
3715
+ // )) {
3716
+ // return;
3717
+ // }
3718
+ // if (paths.length > 12) {
3719
+ // throw new Error('对象之间的关系深度过长,请优化设计加以避免');
3720
+ // }
3721
+ // actionPath.push([firstLetterLowerCase(entity), path, root, isRelation, paths]);
3722
+ // if (Schema[entity].hasRelationDef) {
3723
+ // // assert(!DEDUCED_RELATION_MAP[entity], `${entity}对象定义了deducedRelationMap,但它有relation`);
3724
+ // relationPath.push([firstLetterLowerCase(entity), path, root, isRelation]);
3725
+ // }
3726
+ // const { [entity]: parent } = OneToMany;
3727
+ // if (parent) {
3728
+ // parent.forEach(
3729
+ // ([child, foreignKey]) => {
3730
+ // const child2 = firstLetterLowerCase(child);
3731
+ // if (child === entity) {
3732
+ // // 如果有层级关系对象,最多找3层。同时这里只找本身存在relation关系的对象,因为如果对象上没有relation,则其上的公共路径应当可以维护住层级关系
3733
+ // // 例如在jichuang项目中,house上没有relation,通过其park外键所维护的路径不需要遍历其父亲。而parkCluster因为有relation,所以必须构造以之为根的所有的可能路径
3734
+ // // 如果不是以之为根的,同样可以根据其上的公共路径去查找,parkCluster.system和parkCluster.parent.system必然是一样的
3735
+ // if (!Schema[entity].hasRelationDef) {
3736
+ // return;
3737
+ // }
3738
+ // if (paths.find(ele => ele !== child2) || paths.length > 2) {
3739
+ // return;
3740
+ // }
3741
+ // }
3742
+ // else if (paths.indexOf(child2) >= 0) {
3743
+ // // 除了层级之外的递归直接忽略
3744
+ // return;
3745
+ // }
3746
+ // if (IGNORED_FOREIGN_KEY_MAP[child2]?.includes(foreignKey)) {
3747
+ // // 忽略的路径放弃
3748
+ // return;
3749
+ // }
3750
+ // if (DEDUCED_RELATION_MAP[child] === foreignKey) {
3751
+ // // 如果子对象本身由父对象推定,也放弃
3752
+ // return;
3753
+ // }
3754
+ // const fk = foreignKey === 'entity' ? firstLetterLowerCase(entity) : foreignKey;
3755
+ // const path2 = path ? `${fk}.${path}` : fk;
3756
+ // outputRecursively(root, child, path2, paths.concat([firstLetterLowerCase(entity)]), isRelation);
3757
+ // }
3758
+ // );
3759
+ // }
3760
+ // };
3761
+ // // 所有属性中有指向user的对象
3762
+ // const { User } = OneToMany;
3763
+ // User.forEach(
3764
+ // ([entity3, foreignKey]) => {
3765
+ // const fk = foreignKey === 'entity' ? 'user' : foreignKey;
3766
+ // if (!IGNORED_FOREIGN_KEY_MAP[firstLetterLowerCase(entity3)]?.includes(foreignKey)) {
3767
+ // outputRecursively(firstLetterLowerCase(entity3), entity3, fk, [fk], false);
3768
+ // }
3769
+ // }
3770
+ // );
3771
+ // // 所有带relation的对象
3772
+ // const hasRelationEntities = Object.keys(Schema).filter(
3773
+ // (entity) => Schema[entity].hasRelationDef
3774
+ // );
3775
+ // hasRelationEntities.forEach(
3776
+ // (entity3) => {
3777
+ // outputRecursively(firstLetterLowerCase(entity3), entity3, '', [], true);
3778
+ // }
3779
+ // );
3780
+ // actionPath.sort(
3781
+ // (ele1, ele2) => {
3782
+ // // 先按sourceEntity来排序
3783
+ // if (ele1[0] > ele2[0]) {
3784
+ // return 1;
3785
+ // }
3786
+ // else if (ele1[0] < ele2[0]) {
3787
+ // return -1;
3788
+ // }
3789
+ // else {
3790
+ // // 再按destEntity
3791
+ // if (ele1[2] > ele2[2]) {
3792
+ // return 1;
3793
+ // }
3794
+ // else if (ele1[2] < ele2[2]) {
3795
+ // return -1;
3796
+ // }
3797
+ // else {
3798
+ // // 最后按paths的长度倒排
3799
+ // return ele1[4].length - ele2[4].length;
3800
+ // }
3801
+ // }
3802
+ // }
3803
+ // );
3804
+ // const entityRelations: [string, string[]][] = [];
3805
+ // for (const entity in Schema) {
3806
+ // const { hasRelationDef } = Schema[entity];
3807
+ // if (hasRelationDef) {
3808
+ // const { type } = hasRelationDef;
3809
+ // if (ts.isUnionTypeNode(type)) {
3810
+ // const { types } = type;
3811
+ // const relations = types.map(
3812
+ // ele => {
3813
+ // assert(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
3814
+ // return ele.literal.text;
3815
+ // }
3816
+ // );
3817
+ // entityRelations.push([firstLetterLowerCase(entity), relations]);
3818
+ // }
3819
+ // else {
3820
+ // assert(ts.isLiteralTypeNode(type));
3821
+ // assert(ts.isStringLiteral(type.literal));
3822
+ // const relations = [type.literal.text];
3823
+ // entityRelations.push([firstLetterLowerCase(entity), relations]);
3824
+ // }
3825
+ // }
3826
+ // }
3827
+ // const stmts: ts.Statement[] = [
3828
+ // factory.createImportDeclaration(
3829
+ // undefined,
3830
+ // factory.createImportClause(
3831
+ // false,
3832
+ // undefined,
3833
+ // factory.createNamedImports([
3834
+ // factory.createImportSpecifier(
3835
+ // false,
3836
+ // undefined,
3837
+ // factory.createIdentifier("AuthCascadePath")
3838
+ // ),
3839
+ // factory.createImportSpecifier(
3840
+ // false,
3841
+ // undefined,
3842
+ // factory.createIdentifier("AuthDeduceRelationMap")
3843
+ // )
3844
+ // ])
3845
+ // ),
3846
+ // factory.createStringLiteral(`${TYPE_PATH_IN_OAK_DOMAIN(1)}Entity`),
3847
+ // undefined
3848
+ // ),
3849
+ // factory.createImportDeclaration(
3850
+ // undefined,
3851
+ // factory.createImportClause(
3852
+ // false,
3853
+ // undefined,
3854
+ // factory.createNamedImports([factory.createImportSpecifier(
3855
+ // false,
3856
+ // undefined,
3857
+ // factory.createIdentifier("EntityDict")
3858
+ // )])
3859
+ // ),
3860
+ // factory.createStringLiteral("./EntityDict"),
3861
+ // undefined
3862
+ // ),
3863
+ // factory.createImportDeclaration(
3864
+ // undefined,
3865
+ // factory.createImportClause(
3866
+ // false,
3867
+ // undefined,
3868
+ // factory.createNamedImports([factory.createImportSpecifier(
3869
+ // false,
3870
+ // factory.createIdentifier("CreateOperationData"),
3871
+ // factory.createIdentifier("Relation")
3872
+ // )])
3873
+ // ),
3874
+ // factory.createStringLiteral("./Relation/Schema"),
3875
+ // undefined
3876
+ // ),
3877
+ // factory.createVariableStatement(
3878
+ // [factory.createToken(ts.SyntaxKind.ExportKeyword)],
3879
+ // factory.createVariableDeclarationList(
3880
+ // [factory.createVariableDeclaration(
3881
+ // factory.createIdentifier("ActionCascadePathGraph"),
3882
+ // undefined,
3883
+ // factory.createArrayTypeNode(factory.createTypeReferenceNode(
3884
+ // factory.createIdentifier("AuthCascadePath"),
3885
+ // [factory.createTypeReferenceNode(
3886
+ // factory.createIdentifier("EntityDict"),
3887
+ // undefined
3888
+ // )]
3889
+ // )),
3890
+ // factory.createArrayLiteralExpression(
3891
+ // actionPath.map(
3892
+ // ([entity, path, root, isRelation]) => factory.createArrayLiteralExpression(
3893
+ // [
3894
+ // factory.createStringLiteral(entity),
3895
+ // factory.createStringLiteral(path),
3896
+ // factory.createStringLiteral(root),
3897
+ // isRelation ? factory.createTrue() : factory.createFalse()
3898
+ // ],
3899
+ // false
3900
+ // )
3901
+ // ),
3902
+ // true
3903
+ // )
3904
+ // )],
3905
+ // ts.NodeFlags.Const
3906
+ // )
3907
+ // ),
3908
+ // factory.createVariableStatement(
3909
+ // [factory.createToken(ts.SyntaxKind.ExportKeyword)],
3910
+ // factory.createVariableDeclarationList(
3911
+ // [factory.createVariableDeclaration(
3912
+ // factory.createIdentifier("RelationCascadePathGraph"),
3913
+ // undefined,
3914
+ // factory.createArrayTypeNode(factory.createTypeReferenceNode(
3915
+ // factory.createIdentifier("AuthCascadePath"),
3916
+ // [factory.createTypeReferenceNode(
3917
+ // factory.createIdentifier("EntityDict"),
3918
+ // undefined
3919
+ // )]
3920
+ // )),
3921
+ // factory.createArrayLiteralExpression(
3922
+ // relationPath.map(
3923
+ // ([entity, path, root, isRelation]) => factory.createArrayLiteralExpression(
3924
+ // [
3925
+ // factory.createStringLiteral(entity),
3926
+ // factory.createStringLiteral(path),
3927
+ // factory.createStringLiteral(root),
3928
+ // isRelation ? factory.createTrue() : factory.createFalse()
3929
+ // ],
3930
+ // false
3931
+ // )
3932
+ // ),
3933
+ // true
3934
+ // )
3935
+ // )],
3936
+ // ts.NodeFlags.Const
3937
+ // )
3938
+ // ),
3939
+ // factory.createVariableStatement(
3940
+ // [factory.createToken(ts.SyntaxKind.ExportKeyword)],
3941
+ // factory.createVariableDeclarationList(
3942
+ // [factory.createVariableDeclaration(
3943
+ // factory.createIdentifier("relations"),
3944
+ // undefined,
3945
+ // factory.createArrayTypeNode(factory.createTypeReferenceNode(
3946
+ // factory.createIdentifier("Relation"),
3947
+ // undefined
3948
+ // )),
3949
+ // factory.createArrayLiteralExpression(
3950
+ // flatten(entityRelations.map(
3951
+ // ([entity, relations]) => relations.map(
3952
+ // (relation) => factory.createObjectLiteralExpression(
3953
+ // [
3954
+ // factory.createPropertyAssignment(
3955
+ // factory.createIdentifier("id"),
3956
+ // factory.createStringLiteral(formUuid(entity, relation))
3957
+ // ),
3958
+ // factory.createPropertyAssignment(
3959
+ // factory.createIdentifier("entity"),
3960
+ // factory.createStringLiteral(entity)
3961
+ // ),
3962
+ // factory.createPropertyAssignment(
3963
+ // factory.createIdentifier("name"),
3964
+ // factory.createStringLiteral(relation)
3965
+ // )
3966
+ // ],
3967
+ // true
3968
+ // )
3969
+ // )
3970
+ // )),
3971
+ // true
3972
+ // )
3973
+ // )],
3974
+ // ts.NodeFlags.Const
3975
+ // )
3976
+ // )
3977
+ // ];
3978
+ // stmts.push(
3979
+ // factory.createVariableStatement(
3980
+ // [
3981
+ // factory.createToken(ts.SyntaxKind.ExportKeyword)
3982
+ // ],
3983
+ // factory.createVariableDeclarationList(
3984
+ // [
3985
+ // factory.createVariableDeclaration(
3986
+ // factory.createIdentifier("deducedRelationMap"),
3987
+ // undefined,
3988
+ // factory.createTypeReferenceNode(
3989
+ // factory.createIdentifier("AuthDeduceRelationMap"),
3990
+ // [factory.createTypeReferenceNode(
3991
+ // factory.createIdentifier("EntityDict"),
3992
+ // undefined
3993
+ // )]
3994
+ // ),
3995
+ // factory.createObjectLiteralExpression(
3996
+ // Object.keys(DEDUCED_RELATION_MAP).map(
3997
+ // ele => factory.createPropertyAssignment(
3998
+ // factory.createIdentifier(firstLetterLowerCase(ele)),
3999
+ // factory.createStringLiteral(DEDUCED_RELATION_MAP[ele])
4000
+ // )
4001
+ // ),
4002
+ // true
4003
+ // )
4004
+ // )
4005
+ // ],
4006
+ // ts.NodeFlags.Const
4007
+ // )
4008
+ // )
4009
+ // );
4010
+ // stmts.push(
4011
+ // factory.createVariableStatement(
4012
+ // [
4013
+ // factory.createToken(ts.SyntaxKind.ExportKeyword)
4014
+ // ],
4015
+ // factory.createVariableDeclarationList(
4016
+ // [factory.createVariableDeclaration(
4017
+ // factory.createIdentifier("selectFreeEntities"),
4018
+ // undefined,
4019
+ // factory.createArrayTypeNode(
4020
+ // factory.createParenthesizedType(
4021
+ // factory.createTypeOperatorNode(
4022
+ // ts.SyntaxKind.KeyOfKeyword,
4023
+ // factory.createTypeReferenceNode(
4024
+ // factory.createIdentifier("EntityDict"),
4025
+ // undefined
4026
+ // )
4027
+ // )
4028
+ // )
4029
+ // ),
4030
+ // factory.createArrayLiteralExpression(
4031
+ // SELECT_FREE_ENTITIES.map(
4032
+ // ele => factory.createStringLiteral(ele)
4033
+ // ),
4034
+ // false
4035
+ // )
4036
+ // )],
4037
+ // ts.NodeFlags.Const
4038
+ // )
4039
+ // ),
4040
+ // factory.createVariableStatement(
4041
+ // [
4042
+ // factory.createToken(ts.SyntaxKind.ExportKeyword)
4043
+ // ],
4044
+ // factory.createVariableDeclarationList(
4045
+ // [factory.createVariableDeclaration(
4046
+ // factory.createIdentifier("updateFreeEntities"),
4047
+ // undefined,
4048
+ // factory.createArrayTypeNode(
4049
+ // factory.createParenthesizedType(
4050
+ // factory.createTypeOperatorNode(
4051
+ // ts.SyntaxKind.KeyOfKeyword,
4052
+ // factory.createTypeReferenceNode(
4053
+ // factory.createIdentifier("EntityDict"),
4054
+ // undefined
4055
+ // )
4056
+ // )
4057
+ // )
4058
+ // ),
4059
+ // factory.createArrayLiteralExpression(
4060
+ // UPDATE_FREE_ENTITIES.map(
4061
+ // ele => factory.createStringLiteral(ele)
4062
+ // ),
4063
+ // false
4064
+ // )
4065
+ // )],
4066
+ // ts.NodeFlags.Const
4067
+ // )
4068
+ // ),
4069
+ // factory.createVariableStatement(
4070
+ // [
4071
+ // factory.createToken(ts.SyntaxKind.ExportKeyword)
4072
+ // ],
4073
+ // factory.createVariableDeclarationList(
4074
+ // [factory.createVariableDeclaration(
4075
+ // factory.createIdentifier("createFreeEntities"),
4076
+ // undefined,
4077
+ // factory.createArrayTypeNode(
4078
+ // factory.createParenthesizedType(
4079
+ // factory.createTypeOperatorNode(
4080
+ // ts.SyntaxKind.KeyOfKeyword,
4081
+ // factory.createTypeReferenceNode(
4082
+ // factory.createIdentifier("EntityDict"),
4083
+ // undefined
4084
+ // )
4085
+ // )
4086
+ // )
4087
+ // ),
4088
+ // factory.createArrayLiteralExpression(
4089
+ // CREATE_FREE_ENTITIES.map(
4090
+ // ele => factory.createStringLiteral(ele)
4091
+ // ),
4092
+ // false
4093
+ // )
4094
+ // )],
4095
+ // ts.NodeFlags.Const
4096
+ // )
4097
+ // )
4098
+ // );
4099
+ // const result = printer.printList(
4100
+ // ts.ListFormat.SourceFileStatements,
4101
+ // factory.createNodeArray(stmts),
4102
+ // ts.createSourceFile("someFileName.ts", "", ts.ScriptTarget.Latest, /*setParentNodes*/ false, ts.ScriptKind.TS));
4103
+ // const filename = PathLib.join(outputDir, 'Relation.ts');
4104
+ // writeFileSync(filename, result, { flag: 'w' });
4105
+ // }
3494
4106
  /**
3495
4107
  * 输出oak-app-domain中的Relation.ts文件
3496
4108
  * 不再输出actionAuthGraph和relationAuthGraph两个复杂的对象
@@ -3500,23 +4112,9 @@ function outputRelation(outputDir, printer) {
3500
4112
  function outputRelation2(outputDir, printer) {
3501
4113
  const entityRelations = [];
3502
4114
  for (const entity in Schema) {
3503
- const { hasRelationDef } = Schema[entity];
3504
- if (hasRelationDef) {
3505
- const { type } = hasRelationDef;
3506
- if (ts.isUnionTypeNode(type)) {
3507
- const { types } = type;
3508
- const relations = types.map(ele => {
3509
- (0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal));
3510
- return ele.literal.text;
3511
- });
3512
- entityRelations.push([(0, string_1.firstLetterLowerCase)(entity), relations]);
3513
- }
3514
- else {
3515
- (0, assert_1.default)(ts.isLiteralTypeNode(type));
3516
- (0, assert_1.default)(ts.isStringLiteral(type.literal));
3517
- const relations = [type.literal.text];
3518
- entityRelations.push([(0, string_1.firstLetterLowerCase)(entity), relations]);
3519
- }
4115
+ const { relations } = Schema[entity];
4116
+ if (relations) {
4117
+ entityRelations.push([(0, string_1.firstLetterLowerCase)(entity), relations]);
3520
4118
  }
3521
4119
  }
3522
4120
  const stmts = [