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.
- package/lib/base-app-domain/ActionAuth/Schema.d.ts +1 -2
- package/lib/base-app-domain/ActionDefDict.d.ts +2 -2
- package/lib/base-app-domain/I18n/Schema.d.ts +1 -2
- package/lib/base-app-domain/Modi/Schema.d.ts +1 -2
- package/lib/base-app-domain/ModiEntity/Schema.d.ts +1 -2
- package/lib/base-app-domain/Oper/Schema.d.ts +8 -3
- package/lib/base-app-domain/Oper/Storage.js +19 -1
- package/lib/base-app-domain/OperEntity/Schema.d.ts +1 -2
- package/lib/base-app-domain/Path/Schema.d.ts +1 -2
- package/lib/base-app-domain/Relation/Schema.d.ts +1 -2
- package/lib/base-app-domain/RelationAuth/Schema.d.ts +1 -2
- package/lib/base-app-domain/User/Action.d.ts +1 -0
- package/lib/base-app-domain/User/Action.js +3 -3
- package/lib/base-app-domain/User/Schema.d.ts +1 -2
- package/lib/base-app-domain/UserEntityClaim/Schema.d.ts +1 -2
- package/lib/base-app-domain/UserEntityGrant/Action.d.ts +5 -5
- package/lib/base-app-domain/UserEntityGrant/Action.js +5 -5
- package/lib/base-app-domain/UserEntityGrant/Schema.d.ts +1 -2
- package/lib/base-app-domain/UserRelation/Schema.d.ts +1 -2
- package/lib/compiler/localeBuilder.d.ts +27 -27
- package/lib/compiler/localeBuilder.js +215 -215
- package/lib/compiler/routerBuilder.js +263 -263
- package/lib/compiler/schemalBuilder.js +1058 -460
- package/lib/entities/Oper.d.ts +2 -1
- package/lib/entities/Oper.js +16 -1
- package/lib/entities/User.d.ts +10 -0
- package/lib/entities/User.js +3 -2
- package/lib/index.d.ts +0 -22
- package/lib/index.js +1 -35
- package/lib/store/AsyncRowStore.d.ts +2 -1
- package/lib/store/AsyncRowStore.js +180 -180
- package/lib/store/CascadeStore.js +7 -31
- package/lib/store/RelationAuth.d.ts +103 -103
- package/lib/store/RelationAuth.js +1209 -1343
- package/lib/store/SyncRowStore.d.ts +1 -1
- package/lib/store/TriggerExecutor.js +1 -1
- package/lib/store/actionDef.js +4 -4
- package/lib/store/checker.js +487 -487
- package/lib/triggers/index.d.ts +2 -2
- package/lib/triggers/index.js +21 -1
- package/lib/types/Aspect.d.ts +1 -1
- package/lib/types/Configuration.d.ts +42 -0
- package/lib/types/Configuration.js +3 -0
- package/lib/types/Connector.d.ts +1 -1
- package/lib/types/Context.d.ts +1 -1
- package/lib/types/Entity.d.ts +4 -4
- package/lib/types/Environment.d.ts +3 -0
- package/lib/types/Exception.d.ts +155 -155
- package/lib/types/Exception.js +436 -436
- package/lib/types/Sync.d.ts +48 -0
- package/lib/types/Sync.js +8 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +1 -0
- package/lib/utils/SimpleConnector.d.ts +1 -1
- package/lib/utils/SimpleConnector.js +1 -1
- package/lib/utils/assert.d.ts +0 -1
- package/lib/utils/projection.d.ts +1 -1
- package/lib/utils/relationPath.d.ts +31 -0
- package/lib/utils/relationPath.js +202 -0
- package/package.json +51 -51
- package/src/entities/ActionAuth.ts +41 -41
- package/src/entities/I18n.ts +45 -45
- package/src/entities/Modi.ts +69 -69
- package/src/entities/ModiEntity.ts +26 -26
- package/src/entities/Oper.ts +48 -32
- package/src/entities/OperEntity.ts +27 -27
- package/src/entities/Path.ts +43 -43
- package/src/entities/Relation.ts +43 -43
- package/src/entities/RelationAuth.ts +44 -44
- package/src/entities/User.ts +48 -48
- package/src/entities/UserEntityClaim.ts +29 -29
- package/src/entities/UserEntityGrant.ts +24 -24
- 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
|
-
|
|
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
|
|
172
|
+
function addImportedFrom(moduleName, name, node) {
|
|
168
173
|
const ast = ActionAsts[moduleName];
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
|
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
|
-
|
|
186
|
-
const
|
|
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
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
(0,
|
|
201
|
-
|
|
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.
|
|
205
|
-
const
|
|
206
|
-
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
|
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(
|
|
232
|
-
const actionNames =
|
|
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
|
-
|
|
317
|
+
actionTypeNode.types.forEach(ele => {
|
|
239
318
|
if (ts.isTypeReferenceNode(ele)) {
|
|
240
|
-
|
|
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(
|
|
249
|
-
if (ts.isIdentifier(
|
|
250
|
-
(0, assert_1.default)(!RESERVED_ACTION_NAMES.includes(
|
|
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
|
-
|
|
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(
|
|
256
|
-
actionTexts.push(
|
|
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(
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
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
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
647
|
-
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
862
|
-
|
|
863
|
-
|
|
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
|
-
|
|
1251
|
+
relations,
|
|
911
1252
|
enumAttributes,
|
|
912
|
-
|
|
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,
|
|
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].
|
|
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 {
|
|
2693
|
-
const
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
if (
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
//
|
|
2703
|
-
//
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
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
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
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].
|
|
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
|
-
|
|
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,
|
|
3165
|
+
const { sourceFile, statements, importActionFrom, importStateFrom, importActionDefFrom, actionDefNames } = ActionAsts[entity];
|
|
2821
3166
|
const importStatements = [];
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
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
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
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,
|
|
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].
|
|
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 (
|
|
3159
|
-
|
|
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
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
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 {
|
|
3504
|
-
if (
|
|
3505
|
-
|
|
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 = [
|