新增了一些辅助函数,用于assistant插件分析entity使用

This commit is contained in:
Pan Qiancheng 2025-05-07 17:15:37 +08:00
parent f131bf4440
commit a1e61136f5
3 changed files with 310 additions and 1 deletions

View File

@ -15,6 +15,8 @@ declare const Schema: Record<string, {
extendsFrom: string[]; extendsFrom: string[];
importAttrFrom: Record<string, [string, string | undefined]>; importAttrFrom: Record<string, [string, string | undefined]>;
}>; }>;
export declare function constructAttributes(entity: string): ts.PropertyAssignment[];
export declare function translateLocaleObject(locale: ts.ObjectLiteralExpression): Record<string, any>;
/** /**
* 使 * 使
* @param map * @param map
@ -43,5 +45,6 @@ export declare function registerDeducedRelationMap(map: Record<string, string>):
export declare const getAnalizedSchema: () => typeof Schema; export declare const getAnalizedSchema: () => typeof Schema;
export declare function analyzeEntities(inputDir: string, relativePath?: string): void; export declare function analyzeEntities(inputDir: string, relativePath?: string): void;
export declare function buildSchemaBackup(outputDir: string): void; export declare function buildSchemaBackup(outputDir: string): void;
export declare function getProjectionKeys(entity: string): string[];
export declare function buildSchema(outputDir: string): void; export declare function buildSchema(outputDir: string): void;
export {}; export {};

View File

@ -1,6 +1,8 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.getAnalizedSchema = void 0; exports.getAnalizedSchema = void 0;
exports.constructAttributes = constructAttributes;
exports.translateLocaleObject = translateLocaleObject;
exports.registerIgnoredForeignKeyMap = registerIgnoredForeignKeyMap; exports.registerIgnoredForeignKeyMap = registerIgnoredForeignKeyMap;
exports.registerFreeEntities = registerFreeEntities; exports.registerFreeEntities = registerFreeEntities;
exports.registerIgnoredRelationPathMap = registerIgnoredRelationPathMap; exports.registerIgnoredRelationPathMap = registerIgnoredRelationPathMap;
@ -8,6 +10,7 @@ exports.registerFixedDestinationPathMap = registerFixedDestinationPathMap;
exports.registerDeducedRelationMap = registerDeducedRelationMap; exports.registerDeducedRelationMap = registerDeducedRelationMap;
exports.analyzeEntities = analyzeEntities; exports.analyzeEntities = analyzeEntities;
exports.buildSchemaBackup = buildSchemaBackup; exports.buildSchemaBackup = buildSchemaBackup;
exports.getProjectionKeys = getProjectionKeys;
exports.buildSchema = buildSchema; exports.buildSchema = buildSchema;
const tslib_1 = require("tslib"); const tslib_1 = require("tslib");
const path_1 = tslib_1.__importDefault(require("path")); const path_1 = tslib_1.__importDefault(require("path"));
@ -2264,6 +2267,64 @@ function _constructOpProjection(statements, entity) {
exprNode, exprNode,
]))); ])));
} }
function getOpProjectionKeys(entity) {
const { schemaAttrs, enumAttributes } = Schema[entity];
const { [entity]: manyToOneSet } = ManyToOne;
const result = [
'id',
'$$createAt$$',
'$$updateAt$$',
'$$seq$$',
];
for (const attr of schemaAttrs) {
const { type, name } = attr;
const attrName = name.text;
if (ts.isTypeReferenceNode(type)) {
const { typeName } = type;
if (ts.isIdentifier(typeName)) {
const typeStr = typeName.text;
switch (typeStr) {
case 'String':
case 'Text':
case 'Int':
case 'Uint':
case 'Float':
case 'Double':
case 'Boolean':
case 'Datetime':
case 'Image':
case 'File':
case 'SingleGeo':
case 'Geo':
case 'Price':
case 'Decimal':
result.push(attrName);
break;
case 'Object':
result.push(attrName);
break;
default: {
const refEntity = typeStr === 'Schema' ? entity : typeStr;
const isManyToOne = manyToOneSet?.some(([e]) => e === refEntity);
if (isManyToOne) {
result.push(`${attrName}Id`);
}
else if (!enumAttributes?.[attrName]) {
result.push(attrName);
}
else {
result.push(attrName);
}
}
}
}
}
else {
result.push(attrName);
}
}
return result;
}
/** /**
* 构造Query * 构造Query
* @param statements * @param statements
@ -3959,6 +4020,24 @@ function constructAttributes(entity) {
}); });
return result; return result;
} }
function translateLocaleObject(locale) {
const result = {};
locale.properties.forEach((ele) => {
(0, assert_1.default)(ts.isPropertyAssignment(ele) && (ts.isIdentifier(ele.name) || ts.isStringLiteral(ele.name)), `locale对象中的属性定义不正确`);
const name = ele.name.text;
if (ts.isStringLiteral(ele.initializer)) {
result[name] = ele.initializer.text;
}
else if (ts.isObjectLiteralExpression(ele.initializer)) {
const subObj = translateLocaleObject(ele.initializer);
result[name] = subObj;
}
else {
throw new Error(`locale对象中的属性${name}的定义不正确`);
}
});
return result;
}
function outputLocale(outputDir, printer) { function outputLocale(outputDir, printer) {
const locales = {}; const locales = {};
const entities = []; const entities = [];
@ -5479,6 +5558,75 @@ function _outputEntityDict(outputDir, printer) {
const fileName = path_1.default.join(outputDir, 'EntityDict.ts'); const fileName = path_1.default.join(outputDir, 'EntityDict.ts');
(0, fs_1.writeFileSync)(fileName, result, { flag: 'w' }); (0, fs_1.writeFileSync)(fileName, result, { flag: 'w' });
} }
function getProjectionKeys(entity) {
const keys = [];
const { schemaAttrs } = Schema[entity];
const { [entity]: manyToOneSet = [] } = ManyToOne;
for (const attr of schemaAttrs) {
const { type, name } = attr;
const attrName = name.text;
if (ts.isTypeReferenceNode(type)) {
const typeName = type.typeName;
if (ts.isIdentifier(typeName)) {
const text = typeName.text;
switch (text) {
case 'String':
case 'Text':
case 'Int':
case 'Uint':
case 'Float':
case 'Double':
case 'Boolean':
case 'Datetime':
case 'Image':
case 'File':
case 'SingleGeo':
case 'Geo':
case 'Price':
case 'Decimal':
case 'Object':
break;
default:
const text2 = text === 'Schema' ? entity : text;
const manyToOneItem = manyToOneSet.find(([refEntity]) => refEntity === text2);
if (manyToOneItem) {
keys.push(attrName); // 外键属性
}
}
}
}
}
if (ReversePointerRelations[entity]) {
for (const one of ReversePointerRelations[entity]) {
const text2 = one === 'Schema' ? entity : one;
keys.push((0, string_1.firstLetterLowerCase)(one));
}
}
const { [entity]: oneToManySet = [] } = OneToMany;
const foreignKeySet = {};
for (const [entityName, foreignKey] of oneToManySet) {
if (!foreignKeySet[entityName]) {
foreignKeySet[entityName] = [];
}
foreignKeySet[entityName].push(foreignKey);
}
for (const entityName in foreignKeySet) {
const entityNameLc = (0, string_1.firstLetterLowerCase)(entityName);
for (const foreignKey of foreignKeySet[entityName]) {
const identifier = `${entityNameLc}$${foreignKey}`;
keys.push(identifier);
const aggrKey = _getAggrKey(entityNameLc, foreignKey);
if (typeof aggrKey === 'string') {
keys.push(aggrKey);
}
else {
// 如果是 union 类型,用映射表达式模拟(如 ["xxx$$aggr", `xxx$$${number}$$aggr`]
keys.push(`${identifier}$$aggr`);
}
}
}
return [...new Set([...keys, ...getOpProjectionKeys(entity)])];
}
function _outputSchema(outputDir, printer) { function _outputSchema(outputDir, printer) {
for (const entity in Schema) { for (const entity in Schema) {
const statements = [ const statements = [

View File

@ -3545,6 +3545,66 @@ function _constructOpProjection(statements: Array<ts.Statement>, entity: string)
); );
} }
function getOpProjectionKeys(entity: string): string[] {
const { schemaAttrs, enumAttributes } = Schema[entity];
const { [entity]: manyToOneSet } = ManyToOne;
const result = [
'id',
'$$createAt$$',
'$$updateAt$$',
'$$seq$$',
];
for (const attr of schemaAttrs) {
const { type, name } = attr as ts.PropertySignature;
const attrName = (name as ts.Identifier).text;
if (ts.isTypeReferenceNode(type!)) {
const { typeName } = type;
if (ts.isIdentifier(typeName)) {
const typeStr = typeName.text;
switch (typeStr) {
case 'String':
case 'Text':
case 'Int':
case 'Uint':
case 'Float':
case 'Double':
case 'Boolean':
case 'Datetime':
case 'Image':
case 'File':
case 'SingleGeo':
case 'Geo':
case 'Price':
case 'Decimal':
result.push(attrName);
break;
case 'Object':
result.push(attrName);
break;
default: {
const refEntity = typeStr === 'Schema' ? entity : typeStr;
const isManyToOne = manyToOneSet?.some(([e]) => e === refEntity);
if (isManyToOne) {
result.push(`${attrName}Id`);
} else if (!enumAttributes?.[attrName]) {
result.push(attrName);
} else {
result.push(attrName);
}
}
}
}
} else {
result.push(attrName);
}
}
return result;
}
/** /**
* Query * Query
* @param statements * @param statements
@ -7117,7 +7177,7 @@ function outputAction(outputDir: string, printer: ts.Printer) {
writeFileSync(fileName, result, { flag: 'w' }); writeFileSync(fileName, result, { flag: 'w' });
} }
function constructAttributes(entity: string): ts.PropertyAssignment[] { export function constructAttributes(entity: string): ts.PropertyAssignment[] {
const { schemaAttrs, enumAttributes } = Schema[entity]; const { schemaAttrs, enumAttributes } = Schema[entity];
const { [entity]: manyToOneSet } = ManyToOne; const { [entity]: manyToOneSet } = ManyToOne;
const result: ts.PropertyAssignment[] = []; const result: ts.PropertyAssignment[] = [];
@ -7480,6 +7540,27 @@ function constructAttributes(entity: string): ts.PropertyAssignment[] {
return result; return result;
} }
export function translateLocaleObject(locale: ts.ObjectLiteralExpression): Record<string, any> {
const result: Record<string, string | Record<string, string>> = {};
locale.properties.forEach(
(ele) => {
assert(ts.isPropertyAssignment(ele) && (ts.isIdentifier(ele.name) || ts.isStringLiteral(ele.name)), `locale对象中的属性定义不正确`);
const name = ele.name.text;
if (ts.isStringLiteral(ele.initializer)) {
result[name] = ele.initializer.text;
}
else if (ts.isObjectLiteralExpression(ele.initializer)) {
const subObj = translateLocaleObject(ele.initializer);
result[name] = subObj;
}
else {
throw new Error(`locale对象中的属性${name}的定义不正确`);
}
}
);
return result;
}
function outputLocale(outputDir: string, printer: ts.Printer) { function outputLocale(outputDir: string, printer: ts.Printer) {
const locales: Record<string, string[]> = {}; const locales: Record<string, string[]> = {};
const entities: string[] = []; const entities: string[] = [];
@ -10229,6 +10310,83 @@ function _outputEntityDict(outputDir: string, printer: ts.Printer) {
writeFileSync(fileName, result, { flag: 'w' }); writeFileSync(fileName, result, { flag: 'w' });
} }
export function getProjectionKeys(
entity: string,
): string[] {
const keys: string[] = [];
const { schemaAttrs } = Schema[entity];
const { [entity]: manyToOneSet = [] } = ManyToOne;
for (const attr of schemaAttrs) {
const { type, name } = attr;
const attrName = (name as ts.Identifier).text;
if (ts.isTypeReferenceNode(type!)) {
const typeName = type.typeName;
if (ts.isIdentifier(typeName)) {
const text = typeName.text;
switch (text) {
case 'String':
case 'Text':
case 'Int':
case 'Uint':
case 'Float':
case 'Double':
case 'Boolean':
case 'Datetime':
case 'Image':
case 'File':
case 'SingleGeo':
case 'Geo':
case 'Price':
case 'Decimal':
case 'Object':
break;
default:
const text2 = text === 'Schema' ? entity : text;
const manyToOneItem = manyToOneSet.find(([refEntity]) => refEntity === text2);
if (manyToOneItem) {
keys.push(attrName); // 外键属性
}
}
}
}
}
if (ReversePointerRelations[entity]) {
for (const one of ReversePointerRelations[entity]) {
const text2 = one === 'Schema' ? entity : one;
keys.push(firstLetterLowerCase(one));
}
}
const { [entity]: oneToManySet = [] } = OneToMany;
const foreignKeySet: Record<string, string[]> = {};
for (const [entityName, foreignKey] of oneToManySet) {
if (!foreignKeySet[entityName]) {
foreignKeySet[entityName] = [];
}
foreignKeySet[entityName].push(foreignKey);
}
for (const entityName in foreignKeySet) {
const entityNameLc = firstLetterLowerCase(entityName);
for (const foreignKey of foreignKeySet[entityName]) {
const identifier = `${entityNameLc}$${foreignKey}`;
keys.push(identifier);
const aggrKey = _getAggrKey(entityNameLc, foreignKey);
if (typeof aggrKey === 'string') {
keys.push(aggrKey);
} else {
// 如果是 union 类型,用映射表达式模拟(如 ["xxx$$aggr", `xxx$$${number}$$aggr`]
keys.push(`${identifier}$$aggr`);
}
}
}
return [...new Set([...keys, ...getOpProjectionKeys(entity)])];
}
function _outputSchema(outputDir: string, printer: ts.Printer) { function _outputSchema(outputDir: string, printer: ts.Printer) {
for (const entity in Schema) { for (const entity in Schema) {
const statements: ts.Statement[] = [ const statements: ts.Statement[] = [