vona-module-a-orm 5.0.88 → 5.0.90
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.
|
@@ -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,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.90",
|
|
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
|
}
|