vona-module-a-orm 5.0.87 → 5.0.89
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/dist/.metadata/index.d.ts +3 -19
- package/dist/.metadata/locales.d.ts +20 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +27 -25
- package/dist-cli/entity/metadata/generate.d.ts +2 -0
- package/dist-cli/entity/metadata/generate.js +52 -0
- package/dist-cli/model/metadata/generate.d.ts +2 -0
- package/dist-cli/model/metadata/generate.js +296 -0
- package/dist-cli/model/metadata/magic.d.ts +4 -0
- package/dist-cli/model/metadata/magic.js +105 -0
- package/package.json +10 -9
|
@@ -211,24 +211,9 @@ declare module 'vona-module-a-orm' {
|
|
|
211
211
|
/** config: begin */
|
|
212
212
|
export * from '../config/config.ts';
|
|
213
213
|
import type { config } from '../config/config.ts';
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
CreatedAt: string;
|
|
218
|
-
UpdatedAt: string;
|
|
219
|
-
Deleted: string;
|
|
220
|
-
InstanceId: string;
|
|
221
|
-
ShouldSpecifyTable: string;
|
|
222
|
-
};
|
|
223
|
-
'zh-cn': {
|
|
224
|
-
TableIdentity: string;
|
|
225
|
-
CreatedAt: string;
|
|
226
|
-
UpdatedAt: string;
|
|
227
|
-
Deleted: string;
|
|
228
|
-
InstanceId: string;
|
|
229
|
-
ShouldSpecifyTable: string;
|
|
230
|
-
};
|
|
231
|
-
};
|
|
214
|
+
/** config: end */
|
|
215
|
+
/** locale: begin */
|
|
216
|
+
import { locales } from './locales.ts';
|
|
232
217
|
/** locale: end */
|
|
233
218
|
/** error: begin */
|
|
234
219
|
export * from '../config/errors.ts';
|
|
@@ -269,5 +254,4 @@ declare module 'vona' {
|
|
|
269
254
|
'a-orm': typeof errors;
|
|
270
255
|
}
|
|
271
256
|
}
|
|
272
|
-
export declare function $locale<K extends keyof (typeof locales)[TypeLocaleBase]>(key: K): `a-orm::${K}`;
|
|
273
257
|
/** scope: end */
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { TypeLocaleBase } from 'vona';
|
|
2
|
+
export declare const locales: {
|
|
3
|
+
'en-us': {
|
|
4
|
+
TableIdentity: string;
|
|
5
|
+
CreatedAt: string;
|
|
6
|
+
UpdatedAt: string;
|
|
7
|
+
Deleted: string;
|
|
8
|
+
InstanceId: string;
|
|
9
|
+
ShouldSpecifyTable: string;
|
|
10
|
+
};
|
|
11
|
+
'zh-cn': {
|
|
12
|
+
TableIdentity: string;
|
|
13
|
+
CreatedAt: string;
|
|
14
|
+
UpdatedAt: string;
|
|
15
|
+
Deleted: string;
|
|
16
|
+
InstanceId: string;
|
|
17
|
+
ShouldSpecifyTable: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare function $locale<K extends keyof (typeof locales)[TypeLocaleBase]>(key: K): `a-orm::${K}`;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1335,6 +1335,32 @@ let DtoQueryPageBase = (_dec$h = Api.field(z.number().min(1).default(1)), _dec2$
|
|
|
1335
1335
|
|
|
1336
1336
|
const SymbolKeyFieldsMore = Symbol('$fieldsMore');
|
|
1337
1337
|
|
|
1338
|
+
var locale_en_us = {
|
|
1339
|
+
TableIdentity: 'ID',
|
|
1340
|
+
CreatedAt: 'Created At',
|
|
1341
|
+
UpdatedAt: 'Updated At',
|
|
1342
|
+
Deleted: 'Deleted',
|
|
1343
|
+
InstanceId: 'Instance ID',
|
|
1344
|
+
ShouldSpecifyTable: 'should specify the table name'
|
|
1345
|
+
};
|
|
1346
|
+
|
|
1347
|
+
var locale_zh_cn = {
|
|
1348
|
+
TableIdentity: '标识',
|
|
1349
|
+
CreatedAt: '创建时间',
|
|
1350
|
+
UpdatedAt: '修改时间',
|
|
1351
|
+
Deleted: '已删除',
|
|
1352
|
+
InstanceId: '实例标识',
|
|
1353
|
+
ShouldSpecifyTable: '应该指定表名'
|
|
1354
|
+
};
|
|
1355
|
+
|
|
1356
|
+
const locales = {
|
|
1357
|
+
'en-us': locale_en_us,
|
|
1358
|
+
'zh-cn': locale_zh_cn
|
|
1359
|
+
};
|
|
1360
|
+
function $locale(key) {
|
|
1361
|
+
return `a-orm::${key}`;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1338
1364
|
class EntityBaseEmpty {}
|
|
1339
1365
|
|
|
1340
1366
|
var _dec$g, _dec2$g, _dec3$4, _dec4$2, _dec5, _dec6, _dec7, _dec8, _class$g, _descriptor$2, _descriptor2, _descriptor3, _descriptor4;
|
|
@@ -3836,24 +3862,6 @@ function config(_app) {
|
|
|
3836
3862
|
};
|
|
3837
3863
|
}
|
|
3838
3864
|
|
|
3839
|
-
var locale_en_us = {
|
|
3840
|
-
TableIdentity: 'ID',
|
|
3841
|
-
CreatedAt: 'Created At',
|
|
3842
|
-
UpdatedAt: 'Updated At',
|
|
3843
|
-
Deleted: 'Deleted',
|
|
3844
|
-
InstanceId: 'Instance ID',
|
|
3845
|
-
ShouldSpecifyTable: 'should specify the table name'
|
|
3846
|
-
};
|
|
3847
|
-
|
|
3848
|
-
var locale_zh_cn = {
|
|
3849
|
-
TableIdentity: '标识',
|
|
3850
|
-
CreatedAt: '创建时间',
|
|
3851
|
-
UpdatedAt: '修改时间',
|
|
3852
|
-
Deleted: '已删除',
|
|
3853
|
-
InstanceId: '实例标识',
|
|
3854
|
-
ShouldSpecifyTable: '应该指定表名'
|
|
3855
|
-
};
|
|
3856
|
-
|
|
3857
3865
|
const errors = {
|
|
3858
3866
|
ShouldSpecifyTable: 1001
|
|
3859
3867
|
};
|
|
@@ -3998,16 +4006,10 @@ async function configTest(_app) {
|
|
|
3998
4006
|
}
|
|
3999
4007
|
|
|
4000
4008
|
var _dec, _dec2, _class;
|
|
4001
|
-
const locales = {
|
|
4002
|
-
'en-us': locale_en_us,
|
|
4003
|
-
'zh-cn': locale_zh_cn
|
|
4004
|
-
};
|
|
4005
4009
|
let ScopeModuleAOrm = (_dec = Scope(), _dec2 = BeanInfo({
|
|
4006
4010
|
module: "a-orm"
|
|
4007
4011
|
}), _dec(_class = _dec2(_class = class ScopeModuleAOrm extends BeanScopeBase {}) || _class) || _class);
|
|
4008
|
-
|
|
4009
|
-
return `a-orm::${key}`;
|
|
4010
|
-
}
|
|
4012
|
+
|
|
4011
4013
|
/** scope: end */
|
|
4012
4014
|
|
|
4013
4015
|
function DatabaseDialect(options) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { toUpperCaseFirstChar } from '@cabloy/word-utils';
|
|
2
|
+
export default async function (options) {
|
|
3
|
+
const { sceneName, moduleName, globFiles } = options;
|
|
4
|
+
const contentColumns = [];
|
|
5
|
+
const contentEntityMetas = [];
|
|
6
|
+
const contentRecords = [];
|
|
7
|
+
const contentFields = [];
|
|
8
|
+
for (const globFile of globFiles) {
|
|
9
|
+
const { className, beanName, fileContent } = globFile;
|
|
10
|
+
const opionsName = `IEntityOptions${toUpperCaseFirstChar(beanName)}`;
|
|
11
|
+
const tableName = __parseTableName(fileContent);
|
|
12
|
+
contentColumns.push(`export type ${className}TableName = '${tableName}';`);
|
|
13
|
+
contentEntityMetas.push(`export type ${className}Meta=TypeEntityMeta<${className},${className}TableName>;`);
|
|
14
|
+
const contentRecordItem = `'${tableName}': never;`;
|
|
15
|
+
if (!contentRecords.includes(contentRecordItem)) {
|
|
16
|
+
contentRecords.push(contentRecordItem);
|
|
17
|
+
}
|
|
18
|
+
contentFields.push(`
|
|
19
|
+
export interface ${opionsName} {
|
|
20
|
+
fields?: TypeEntityOptionsFields<${className}, ${opionsName}[TypeSymbolKeyFieldsMore]>;
|
|
21
|
+
}`);
|
|
22
|
+
}
|
|
23
|
+
if (contentColumns.length === 0 && contentEntityMetas.length === 0 && contentRecords.length === 0 && contentFields.length === 0)
|
|
24
|
+
return '';
|
|
25
|
+
// combine
|
|
26
|
+
const content = `/** ${sceneName}: begin */
|
|
27
|
+
${contentColumns.join('\n')}
|
|
28
|
+
${contentEntityMetas.join('\n')}
|
|
29
|
+
declare module 'vona-module-a-orm' {
|
|
30
|
+
export interface ITableRecord {
|
|
31
|
+
${contentRecords.join('\n')}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
declare module 'vona-module-${moduleName}' {
|
|
35
|
+
${contentFields.join('\n')}
|
|
36
|
+
}
|
|
37
|
+
/** ${sceneName}: end */
|
|
38
|
+
`;
|
|
39
|
+
return content;
|
|
40
|
+
}
|
|
41
|
+
function __parseTableName(fileContent) {
|
|
42
|
+
let matched = fileContent.match(/@Entity<.*?>\(\{[\s\S]*?table: ('[^']*')[\s\S]*?\}[\s\S]*?\)\s*export class/);
|
|
43
|
+
if (!matched) {
|
|
44
|
+
matched = fileContent.match(/@Entity<.*?>\(([^)]*)\)/);
|
|
45
|
+
}
|
|
46
|
+
if (!matched)
|
|
47
|
+
return false;
|
|
48
|
+
const tableName = matched[1];
|
|
49
|
+
if (tableName === '')
|
|
50
|
+
return '';
|
|
51
|
+
return tableName.split(',')[0].replaceAll("'", '');
|
|
52
|
+
}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { types as t } from '@babel/core';
|
|
2
|
+
import { __parseMagics } from "./magic.js";
|
|
3
|
+
export default async function (options) {
|
|
4
|
+
const { sceneName, moduleName, globFiles, cli } = options;
|
|
5
|
+
const contentRelations = [];
|
|
6
|
+
const contentRecords = [];
|
|
7
|
+
const contentModels = [];
|
|
8
|
+
// const contentModelsOptions: string[] = [];
|
|
9
|
+
for (const globFile of globFiles) {
|
|
10
|
+
const { className, beanName, fileContent, beanNameCapitalize } = globFile;
|
|
11
|
+
const ast = cli.helper.gogocode(fileContent);
|
|
12
|
+
const astNodes = ast.find(`@Model<$$$0>({$$$1})export class ${className} extends $$$2 {}`).match.$$$1;
|
|
13
|
+
const entityName = __parseEntityName(__getAstNode(astNodes, 'entity'));
|
|
14
|
+
const relations = __parseRelations(__getAstNode(astNodes, 'relations'));
|
|
15
|
+
const magics = __parseMagics(cli, ast, globFile, entityName);
|
|
16
|
+
const entityMetaName = `${entityName}Meta`;
|
|
17
|
+
const opionsName = `IModelOptions${beanNameCapitalize}`;
|
|
18
|
+
if (relations && relations.length > 0) {
|
|
19
|
+
contentRelations.push(`export interface ${opionsName} {
|
|
20
|
+
relations: {
|
|
21
|
+
${relations.join('\n')}
|
|
22
|
+
};
|
|
23
|
+
}`);
|
|
24
|
+
}
|
|
25
|
+
contentRecords.push(`export interface ${className} {
|
|
26
|
+
[SymbolKeyEntity]: ${entityName};
|
|
27
|
+
[SymbolKeyEntityMeta]: ${entityMetaName};
|
|
28
|
+
[SymbolKeyModelOptions]: ${opionsName};
|
|
29
|
+
get<T extends IModelGetOptions<${entityName},${className}>>(where: TypeModelWhere<${entityName}>, options?: T): Promise<TypeModelRelationResult<${entityName}, ${className}, T> | undefined>;
|
|
30
|
+
mget<T extends IModelGetOptions<${entityName},${className}>>(ids: TableIdentity[], options?: T): Promise<TypeModelRelationResult<${entityName}, ${className}, T>[]>;
|
|
31
|
+
selectAndCount<T extends IModelSelectParams<${entityName},${className},ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelSelectAndCount<${entityName}, ${className}, T>>;
|
|
32
|
+
select<T extends IModelSelectParams<${entityName},${className},ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<${entityName}, ${className}, T>[]>;
|
|
33
|
+
insert<T extends IModelInsertOptions<${entityName},${className}>>(data?: TypeModelMutateRelationData<${entityName},${className}, T>, options?: T): Promise<TypeModelMutateRelationData<${entityName},${className}, T, true>>;
|
|
34
|
+
insertBulk<T extends IModelInsertOptions<${entityName},${className}>>(items: TypeModelMutateRelationData<${entityName},${className}, T>[], options?: T): Promise<TypeModelMutateRelationData<${entityName},${className}, T, true>[]>;
|
|
35
|
+
update<T extends IModelUpdateOptions<${entityName},${className}>>(data: TypeModelMutateRelationData<${entityName},${className}, T>, options?: T): Promise<TypeModelMutateRelationData<${entityName},${className}, T>>;
|
|
36
|
+
updateBulk<T extends IModelUpdateOptions<${entityName},${className}>>(items: TypeModelMutateRelationData<${entityName},${className}, T>[], options?: T): Promise<TypeModelMutateRelationData<${entityName},${className}, T>[]>;
|
|
37
|
+
delete<T extends IModelDeleteOptions<${entityName},${className}>>(where?: TypeModelWhere<${entityName}>, options?: T): Promise<void>;
|
|
38
|
+
deleteBulk<T extends IModelDeleteOptions<${entityName},${className}>>(ids: TableIdentity[], options?: T): Promise<void>;
|
|
39
|
+
mutate<T extends IModelMutateOptions<${entityName},${className}>>(data?: TypeModelMutateRelationData<${entityName},${className}, T>, options?: T): Promise<TypeModelMutateRelationData<${entityName},${className}, T>>;
|
|
40
|
+
mutateBulk<T extends IModelMutateOptions<${entityName},${className}>>(items: TypeModelMutateRelationData<${entityName},${className}, T>[], options?: T): Promise<TypeModelMutateRelationData<${entityName},${className}, T>[]>;
|
|
41
|
+
count<T extends IModelSelectCountParams<${entityName},${className},ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<string | undefined>;
|
|
42
|
+
aggregate<T extends IModelSelectAggrParams<${entityName},${className},ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelAggrRelationResult<T>>;
|
|
43
|
+
group<T extends IModelSelectGroupParams<${entityName},${className},ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelGroupRelationResult<${entityName}, T>[]>;
|
|
44
|
+
${magics.join('\n')}
|
|
45
|
+
}`);
|
|
46
|
+
contentModels.push(`'${moduleName}:${beanName}': ${className};`);
|
|
47
|
+
// only override cache.keyAux which not enough
|
|
48
|
+
// contentModelsOptions.push(`export interface ${opionsName} {
|
|
49
|
+
// cache?: {
|
|
50
|
+
// keyAux?: keyof ${entityName};
|
|
51
|
+
// };
|
|
52
|
+
// }`);
|
|
53
|
+
}
|
|
54
|
+
if (contentRelations.length === 0 && contentRecords.length === 0 && contentModels.length === 0)
|
|
55
|
+
return '';
|
|
56
|
+
// combine
|
|
57
|
+
const content = `/** ${sceneName}: begin */
|
|
58
|
+
import type { IModelGetOptions, IModelMethodOptions, IModelSelectParams, TypeModelSelectAndCount, TypeModelRelationResult, TypeModelWhere, IModelInsertOptions, TypeModelMutateRelationData, IModelDeleteOptions, IModelUpdateOptions, IModelMutateOptions, IModelSelectCountParams, IModelSelectAggrParams, TypeModelAggrRelationResult, IModelSelectGroupParams, TypeModelGroupRelationResult } from 'vona-module-a-orm';
|
|
59
|
+
import { SymbolKeyEntity, SymbolKeyEntityMeta, SymbolKeyModelOptions } from 'vona-module-a-orm';
|
|
60
|
+
declare module 'vona-module-${moduleName}' {
|
|
61
|
+
${contentRelations.join('\n')}
|
|
62
|
+
${contentRecords.join('\n')}
|
|
63
|
+
}
|
|
64
|
+
declare module 'vona-module-a-orm' {
|
|
65
|
+
export interface IModelClassRecord {
|
|
66
|
+
${contentModels.join('\n')}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** ${sceneName}: end */
|
|
70
|
+
`;
|
|
71
|
+
return content;
|
|
72
|
+
}
|
|
73
|
+
function __getAstNode(astNodes, name) {
|
|
74
|
+
return astNodes.find(node => node.key.name === name);
|
|
75
|
+
}
|
|
76
|
+
function __parseEntityName(node) {
|
|
77
|
+
return node.value.name;
|
|
78
|
+
// const matched = fileContent.match(/@Model<.*?>\(\{[\s\S]*?entity: (Entity\S+)[\s\S]*?\}[\s\S]*?\)\s*export class/);
|
|
79
|
+
// if (!matched) return false;
|
|
80
|
+
// const entityName = matched[1];
|
|
81
|
+
// if (entityName === '') return '';
|
|
82
|
+
// return entityName.split(',')[0];
|
|
83
|
+
}
|
|
84
|
+
function __parseRelations(node) {
|
|
85
|
+
if (!node)
|
|
86
|
+
return;
|
|
87
|
+
const relations = [];
|
|
88
|
+
const nodeRelations = node.value;
|
|
89
|
+
for (const nodeRelation of nodeRelations.properties) {
|
|
90
|
+
relations.push(__parseRelation(nodeRelation));
|
|
91
|
+
}
|
|
92
|
+
return relations;
|
|
93
|
+
}
|
|
94
|
+
function __parseRelation(nodeRelation) {
|
|
95
|
+
const relationName = nodeRelation.key.name;
|
|
96
|
+
const callExpression = nodeRelation.value;
|
|
97
|
+
const relationType = callExpression.callee.property.name;
|
|
98
|
+
const args = callExpression.arguments;
|
|
99
|
+
// relation
|
|
100
|
+
if (relationType === 'hasOne') {
|
|
101
|
+
return `${relationName}: ${__parseRelationHasOne(args)};`;
|
|
102
|
+
}
|
|
103
|
+
else if (relationType === 'belongsTo') {
|
|
104
|
+
return `${relationName}: ${__parseRelationBelongsTo(args)};`;
|
|
105
|
+
}
|
|
106
|
+
else if (relationType === 'hasMany') {
|
|
107
|
+
return `${relationName}: ${__parseRelationHasMany(args)};`;
|
|
108
|
+
}
|
|
109
|
+
else if (relationType === 'belongsToMany') {
|
|
110
|
+
return `${relationName}: ${__parseRelationBelongsToMany(args)};`;
|
|
111
|
+
}
|
|
112
|
+
return '';
|
|
113
|
+
}
|
|
114
|
+
function __parseRelationHasOne(args) {
|
|
115
|
+
// classModel
|
|
116
|
+
const classModel = __parseRelation_classModel(args[0]);
|
|
117
|
+
// key
|
|
118
|
+
const key = __parseRelation_key(args[1]);
|
|
119
|
+
// options
|
|
120
|
+
const options = __parseRelation_options(args[2]);
|
|
121
|
+
// combine
|
|
122
|
+
return `IModelRelationHasOne<${classModel}, '${key}', ${options.autoload}, ${options.columns}>`;
|
|
123
|
+
}
|
|
124
|
+
function __parseRelationBelongsTo(args) {
|
|
125
|
+
// classModelSelf
|
|
126
|
+
const classModelSelf = __parseRelation_classModel(args[0]);
|
|
127
|
+
// classModel
|
|
128
|
+
const classModel = __parseRelation_classModel(args[1]);
|
|
129
|
+
// options
|
|
130
|
+
const options = __parseRelation_options(args[3]);
|
|
131
|
+
// combine
|
|
132
|
+
return `IModelRelationBelongsTo<${classModelSelf}, ${classModel}, ${options.autoload}, ${options.columns}>`;
|
|
133
|
+
}
|
|
134
|
+
function __parseRelationHasMany(args) {
|
|
135
|
+
// classModel
|
|
136
|
+
const classModel = __parseRelation_classModel(args[0]);
|
|
137
|
+
// key
|
|
138
|
+
const key = __parseRelation_key(args[1]);
|
|
139
|
+
// options
|
|
140
|
+
const options = __parseRelation_options(args[2]);
|
|
141
|
+
// modelJoins
|
|
142
|
+
const modelJoins = __parseRelation_modelJoins(args[3]);
|
|
143
|
+
// combine
|
|
144
|
+
return `IModelRelationHasMany<${classModel}, '${key}', ${options.autoload}, ${options.columns}, ${modelJoins}, ${options.aggrs}, ${options.groups}>`;
|
|
145
|
+
}
|
|
146
|
+
function __parseRelationBelongsToMany(args) {
|
|
147
|
+
// classModelMiddle
|
|
148
|
+
const classModelMiddle = __parseRelation_classModel(args[0]);
|
|
149
|
+
// classModel
|
|
150
|
+
const classModel = __parseRelation_classModel(args[1]);
|
|
151
|
+
// options
|
|
152
|
+
const options = __parseRelation_options(args[4]);
|
|
153
|
+
// modelJoins
|
|
154
|
+
const modelJoins = __parseRelation_modelJoins(args[5]);
|
|
155
|
+
// combine
|
|
156
|
+
return `IModelRelationBelongsToMany<${classModelMiddle}, ${classModel}, ${options.autoload}, ${options.columns},${modelJoins},${options.aggrs},${options.groups}>`;
|
|
157
|
+
}
|
|
158
|
+
function __parseRelation_classModel(node) {
|
|
159
|
+
if (t.isArrowFunctionExpression(node)) {
|
|
160
|
+
return node.body.name;
|
|
161
|
+
}
|
|
162
|
+
else if (t.isIdentifier(node)) {
|
|
163
|
+
return node.name;
|
|
164
|
+
}
|
|
165
|
+
else if (t.isStringLiteral(node)) {
|
|
166
|
+
return `'${node.value}'`;
|
|
167
|
+
}
|
|
168
|
+
throw new Error('invalid classModel');
|
|
169
|
+
}
|
|
170
|
+
function __parseRelation_key(node) {
|
|
171
|
+
if (t.isStringLiteral(node)) {
|
|
172
|
+
return node.value;
|
|
173
|
+
}
|
|
174
|
+
throw new Error('invalid key');
|
|
175
|
+
}
|
|
176
|
+
function __parseRelation_modelJoins(node) {
|
|
177
|
+
if (!node)
|
|
178
|
+
return 'undefined';
|
|
179
|
+
if (t.isIdentifier(node) && node.name === 'undefined')
|
|
180
|
+
return 'undefined';
|
|
181
|
+
let modelJoins;
|
|
182
|
+
if (t.isArrayExpression(node)) {
|
|
183
|
+
modelJoins = node.elements.map(item => __parseRelation_classModel(item));
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
modelJoins = [__parseRelation_classModel(node)];
|
|
187
|
+
}
|
|
188
|
+
return `[${modelJoins.join(',')}]`;
|
|
189
|
+
// const content = `${modelJoins.join('|')}`;
|
|
190
|
+
// return `${content} | Array<${content}>`;
|
|
191
|
+
}
|
|
192
|
+
function __parseRelation_aggrs(node) {
|
|
193
|
+
if (!node)
|
|
194
|
+
return 'undefined';
|
|
195
|
+
if (t.isIdentifier(node) && node.name === 'undefined')
|
|
196
|
+
return 'undefined';
|
|
197
|
+
const aggrs = __parseRelation_aggrs_inner(node);
|
|
198
|
+
return `{ ${aggrs.join(';')} }`;
|
|
199
|
+
}
|
|
200
|
+
function __parseRelation_aggrs_inner(node) {
|
|
201
|
+
const aggrs = [];
|
|
202
|
+
for (const _nodeProperty of node.properties) {
|
|
203
|
+
const nodeProperty = _nodeProperty;
|
|
204
|
+
const key = nodeProperty.key.name;
|
|
205
|
+
const value = __parseColumns(nodeProperty);
|
|
206
|
+
if (value) {
|
|
207
|
+
aggrs.push(`${key}?: ${__joinColumnsType(value, true)}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return aggrs;
|
|
211
|
+
}
|
|
212
|
+
function __parseRelation_options(node) {
|
|
213
|
+
const options = __parseRelation_options_inner(node);
|
|
214
|
+
let autoload;
|
|
215
|
+
let columns;
|
|
216
|
+
let groups;
|
|
217
|
+
let aggrs;
|
|
218
|
+
// autoload
|
|
219
|
+
if (options?.autoload) {
|
|
220
|
+
autoload = 'true';
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
autoload = 'false';
|
|
224
|
+
}
|
|
225
|
+
// groups
|
|
226
|
+
if (!options?.groups) {
|
|
227
|
+
groups = 'undefined';
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
groups = __joinColumnsType(options?.groups, true);
|
|
231
|
+
}
|
|
232
|
+
// aggrs
|
|
233
|
+
if (!options?.aggrs) {
|
|
234
|
+
aggrs = 'undefined';
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
aggrs = options?.aggrs;
|
|
238
|
+
}
|
|
239
|
+
// columns
|
|
240
|
+
if (!options?.columns) {
|
|
241
|
+
if (options?.groups) {
|
|
242
|
+
columns = 'undefined';
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
columns = 'undefined'; // '\'*\'';
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
if (options?.columns.includes('*')) {
|
|
250
|
+
columns = '\'*\'';
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
columns = __joinColumnsType(options?.columns, false);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return { autoload, columns, groups, aggrs };
|
|
257
|
+
}
|
|
258
|
+
function __parseRelation_options_inner(node) {
|
|
259
|
+
if (!node)
|
|
260
|
+
return undefined;
|
|
261
|
+
if (!t.isObjectExpression(node))
|
|
262
|
+
throw new Error('invalid options');
|
|
263
|
+
let autoload;
|
|
264
|
+
let columns;
|
|
265
|
+
let groups;
|
|
266
|
+
let aggrs;
|
|
267
|
+
for (const _nodeProperty of node.properties) {
|
|
268
|
+
const nodeProperty = _nodeProperty;
|
|
269
|
+
const key = nodeProperty.key.name;
|
|
270
|
+
if (key === 'autoload') {
|
|
271
|
+
autoload = nodeProperty.value.value;
|
|
272
|
+
}
|
|
273
|
+
else if (key === 'columns') {
|
|
274
|
+
columns = __parseColumns(nodeProperty);
|
|
275
|
+
}
|
|
276
|
+
else if (key === 'groups') {
|
|
277
|
+
groups = __parseColumns(nodeProperty);
|
|
278
|
+
}
|
|
279
|
+
else if (key === 'aggrs') {
|
|
280
|
+
aggrs = __parseRelation_aggrs(nodeProperty.value);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return { autoload, columns, groups, aggrs };
|
|
284
|
+
}
|
|
285
|
+
function __parseColumns(node) {
|
|
286
|
+
if (t.isArrayExpression(node.value)) {
|
|
287
|
+
return node.value.elements.map(item => item.value);
|
|
288
|
+
}
|
|
289
|
+
else if (t.isStringLiteral(node.value)) {
|
|
290
|
+
return [node.value.value];
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function __joinColumnsType(columns, withArray) {
|
|
294
|
+
const temp = columns.map(item => `'${item}'`).join('|');
|
|
295
|
+
return withArray ? `${temp} | Array<${temp}>` : temp;
|
|
296
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { BeanCliBase } from '@cabloy/cli';
|
|
2
|
+
import type { IGlobBeanFile } from '@cabloy/module-info';
|
|
3
|
+
import type GoGoCode from 'gogocode';
|
|
4
|
+
export declare function __parseMagics(cli: BeanCliBase, ast: GoGoCode.GoGoAST, globFile: IGlobBeanFile, entityName: string): string[];
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { ensureArray } from '@cabloy/utils';
|
|
4
|
+
import { toUpperCaseFirstChar } from '@cabloy/word-utils';
|
|
5
|
+
// id/name/enabled/disabled/closed/active
|
|
6
|
+
const __MagicFields = {
|
|
7
|
+
id: {
|
|
8
|
+
optional: false,
|
|
9
|
+
type: 'auto',
|
|
10
|
+
methods: ['getBy', 'updateBy', 'deleteBy'],
|
|
11
|
+
},
|
|
12
|
+
name: {
|
|
13
|
+
optional: true,
|
|
14
|
+
type: 'string',
|
|
15
|
+
methods: ['getBy', 'selectBy'],
|
|
16
|
+
ops: ['', 'eqI'],
|
|
17
|
+
},
|
|
18
|
+
enabled: {
|
|
19
|
+
optional: true,
|
|
20
|
+
type: 'boolean',
|
|
21
|
+
methods: ['getBy', 'selectBy'],
|
|
22
|
+
},
|
|
23
|
+
disabled: {
|
|
24
|
+
optional: true,
|
|
25
|
+
type: 'boolean',
|
|
26
|
+
methods: ['getBy', 'selectBy'],
|
|
27
|
+
},
|
|
28
|
+
closed: {
|
|
29
|
+
optional: true,
|
|
30
|
+
type: 'boolean',
|
|
31
|
+
methods: ['getBy', 'selectBy'],
|
|
32
|
+
},
|
|
33
|
+
active: {
|
|
34
|
+
optional: true,
|
|
35
|
+
type: 'boolean',
|
|
36
|
+
methods: ['getBy', 'selectBy'],
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
export function __parseMagics(cli, ast, globFile, entityName) {
|
|
40
|
+
const { className, file } = globFile;
|
|
41
|
+
const astImportEntity = ast.find(`import { ${entityName} } from '$$$0'`);
|
|
42
|
+
const fileEntity = path.join(path.dirname(file), astImportEntity.value.source.value);
|
|
43
|
+
const entityInfo = __parseEntityInfo(cli, fileEntity, entityName);
|
|
44
|
+
const modelInfo = __parseModelInfo(cli, file, className);
|
|
45
|
+
const contentRecords = [];
|
|
46
|
+
for (const fieldName in __MagicFields) {
|
|
47
|
+
const magicField = __MagicFields[fieldName];
|
|
48
|
+
if (!entityInfo.fieldNames.includes(fieldName))
|
|
49
|
+
continue;
|
|
50
|
+
for (const method of ensureArray(magicField.methods)) {
|
|
51
|
+
const ops = ensureArray(magicField.ops || ['']);
|
|
52
|
+
for (const op of ops) {
|
|
53
|
+
const actionName = `${method}${toUpperCaseFirstChar(fieldName)}${toUpperCaseFirstChar(op)}`;
|
|
54
|
+
if (modelInfo.fieldNames.includes(actionName))
|
|
55
|
+
continue;
|
|
56
|
+
const optional = magicField.optional ? '?' : '';
|
|
57
|
+
const type = fieldName === 'id' ? entityInfo.idType : magicField.type;
|
|
58
|
+
if (method === 'getBy') {
|
|
59
|
+
contentRecords.push(`${actionName}<T extends IModelGetOptions<${entityName},${className}>>(${fieldName}${optional}: ${type}, options?: T): Promise<TypeModelRelationResult<${entityName}, ${className}, T> | undefined>;`);
|
|
60
|
+
}
|
|
61
|
+
else if (method === 'selectBy') {
|
|
62
|
+
contentRecords.push(`${actionName}<T extends IModelSelectParams<${entityName},${className},ModelJoins>, ModelJoins extends TypeModelsClassLikeGeneral | undefined = undefined>(${fieldName}${optional}: ${type}, params?: T, options?: IModelMethodOptions, modelJoins?: ModelJoins): Promise<TypeModelRelationResult<${entityName}, ${className}, T>[]>;`);
|
|
63
|
+
}
|
|
64
|
+
else if (method === 'updateBy') {
|
|
65
|
+
contentRecords.push(`${actionName}<T extends IModelUpdateOptions<${entityName},${className}>>(${fieldName}: ${type}${optional ? ' | undefined' : ''}, data: TypeModelMutateRelationData<${entityName},${className}, T>, options?: T): Promise<TypeModelMutateRelationData<${entityName},${className}, T>>;`);
|
|
66
|
+
}
|
|
67
|
+
else if (method === 'deleteBy') {
|
|
68
|
+
contentRecords.push(`${actionName}<T extends IModelDeleteOptions<${entityName},${className}>>(${fieldName}${optional}: ${type}, options?: T): Promise<void>;`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return contentRecords;
|
|
74
|
+
}
|
|
75
|
+
function __parseEntityInfo(cli, fileEntity, entityName) {
|
|
76
|
+
const content = readFileSync(fileEntity).toString();
|
|
77
|
+
const regexpSimple = new RegExp(`export class ${entityName} extends.*?EntityBaseSimple.*?{`);
|
|
78
|
+
const regexpBase = new RegExp(`export class ${entityName} extends.*?EntityBase.*?{`);
|
|
79
|
+
let idType;
|
|
80
|
+
if (content.match(regexpSimple)) {
|
|
81
|
+
idType = 'number';
|
|
82
|
+
}
|
|
83
|
+
else if (content.match(regexpBase)) {
|
|
84
|
+
idType = 'TableIdentity';
|
|
85
|
+
}
|
|
86
|
+
const ast = cli.helper.gogocode(content);
|
|
87
|
+
const astNodes = ast.find(`export class ${entityName} extends $$$0 {$$$1}`).match.$$$1;
|
|
88
|
+
const fieldNames = [];
|
|
89
|
+
for (const astNode of astNodes) {
|
|
90
|
+
fieldNames.push(astNode.key.name);
|
|
91
|
+
}
|
|
92
|
+
if (idType)
|
|
93
|
+
fieldNames.push('id');
|
|
94
|
+
return { idType, fieldNames };
|
|
95
|
+
}
|
|
96
|
+
function __parseModelInfo(cli, fileModel, modelName) {
|
|
97
|
+
const content = readFileSync(fileModel).toString();
|
|
98
|
+
const ast = cli.helper.gogocode(content);
|
|
99
|
+
const astNodes = ast.find(`export class ${modelName} extends $$$0 {$$$1}`).match.$$$1;
|
|
100
|
+
const fieldNames = [];
|
|
101
|
+
for (const astNode of astNodes) {
|
|
102
|
+
fieldNames.push(astNode.key.name);
|
|
103
|
+
}
|
|
104
|
+
return { fieldNames };
|
|
105
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vona-module-a-orm",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.89",
|
|
5
5
|
"title": "a-orm",
|
|
6
6
|
"vonaModule": {
|
|
7
7
|
"capabilities": {
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"optionsGlobalInterfaceFrom": "vona-module-a-orm",
|
|
20
20
|
"scopeResource": true,
|
|
21
21
|
"scopeResourceTypeTemplate": "{{className}}Meta",
|
|
22
|
-
"boilerplate": "
|
|
23
|
-
"metadataCustom": "
|
|
22
|
+
"boilerplate": "entity/boilerplate",
|
|
23
|
+
"metadataCustom": "entity/metadata/generate.ts"
|
|
24
24
|
},
|
|
25
25
|
"model": {
|
|
26
26
|
"sceneIsolate": true,
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
"optionsGlobalInterfaceFrom": "vona-module-a-orm",
|
|
29
29
|
"scopeResource": true,
|
|
30
30
|
"beanGeneral": true,
|
|
31
|
-
"boilerplate": "
|
|
32
|
-
"metadataCustom": "
|
|
31
|
+
"boilerplate": "model/boilerplate",
|
|
32
|
+
"metadataCustom": "model/metadata/generate.ts"
|
|
33
33
|
},
|
|
34
34
|
"databaseDialect": {
|
|
35
35
|
"beanGeneral": true,
|
|
36
36
|
"optionsGlobalInterfaceName": "IDecoratorDatabaseDialectOptions",
|
|
37
37
|
"optionsGlobalInterfaceFrom": "vona-module-a-orm",
|
|
38
|
-
"boilerplate": "
|
|
38
|
+
"boilerplate": "databaseDialect/boilerplate"
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
},
|
|
@@ -57,7 +57,8 @@
|
|
|
57
57
|
"files": [
|
|
58
58
|
"assets",
|
|
59
59
|
"cli",
|
|
60
|
-
"dist"
|
|
60
|
+
"dist",
|
|
61
|
+
"dist-cli"
|
|
61
62
|
],
|
|
62
63
|
"dependencies": {
|
|
63
64
|
"knex": "^3.1.0",
|
|
@@ -69,7 +70,7 @@
|
|
|
69
70
|
},
|
|
70
71
|
"gitHead": "0eab9dc4a5622caffe89e7b1b3f02c08ccbc4c4b",
|
|
71
72
|
"scripts": {
|
|
72
|
-
"clean": "rimraf dist tsconfig.build.tsbuildinfo",
|
|
73
|
-
"tsc:publish": "npm run clean && vona :bin:buildModule && tsc -p tsconfig.build.json"
|
|
73
|
+
"clean": "rimraf dist dist-cli tsconfig.build.tsbuildinfo tsconfig.cli.tsbuildinfo",
|
|
74
|
+
"tsc:publish": "npm run clean && vona :bin:buildModule && tsc -p tsconfig.build.json && tsc -p tsconfig.cli.json"
|
|
74
75
|
}
|
|
75
76
|
}
|