@currentjs/gen 0.5.0 → 0.5.1
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/CHANGELOG.md +10 -0
- package/dist/cli.js +0 -0
- package/dist/generators/controllerGenerator.d.ts +7 -0
- package/dist/generators/controllerGenerator.js +56 -17
- package/dist/generators/domainLayerGenerator.js +17 -7
- package/dist/generators/dtoGenerator.js +13 -8
- package/dist/generators/serviceGenerator.d.ts +6 -0
- package/dist/generators/serviceGenerator.js +219 -23
- package/dist/generators/storeGenerator.d.ts +4 -0
- package/dist/generators/storeGenerator.js +116 -9
- package/dist/generators/templates/appTemplates.js +1 -1
- package/dist/generators/templates/data/frontendScriptTemplate +11 -4
- package/dist/generators/templates/data/mainViewTemplate +1 -0
- package/dist/generators/templates/storeTemplates.d.ts +1 -1
- package/dist/generators/templates/storeTemplates.js +3 -26
- package/dist/generators/useCaseGenerator.js +6 -3
- package/dist/types/configTypes.d.ts +1 -0
- package/dist/utils/typeUtils.d.ts +4 -0
- package/dist/utils/typeUtils.js +7 -0
- package/package.json +1 -1
- package/dist/commands/migratePush.d.ts +0 -1
- package/dist/commands/migratePush.js +0 -135
- package/dist/commands/migrateUpdate.d.ts +0 -1
- package/dist/commands/migrateUpdate.js +0 -147
- package/dist/commands/newGenerateAll.d.ts +0 -4
- package/dist/commands/newGenerateAll.js +0 -336
- package/dist/generators/domainModelGenerator.d.ts +0 -41
- package/dist/generators/domainModelGenerator.js +0 -242
- package/dist/generators/newControllerGenerator.d.ts +0 -55
- package/dist/generators/newControllerGenerator.js +0 -644
- package/dist/generators/newServiceGenerator.d.ts +0 -19
- package/dist/generators/newServiceGenerator.js +0 -266
- package/dist/generators/newStoreGenerator.d.ts +0 -39
- package/dist/generators/newStoreGenerator.js +0 -408
- package/dist/generators/newTemplateGenerator.d.ts +0 -29
- package/dist/generators/newTemplateGenerator.js +0 -510
- package/dist/generators/storeGeneratorV2.d.ts +0 -31
- package/dist/generators/storeGeneratorV2.js +0 -190
- package/dist/generators/templates/controllerTemplates.d.ts +0 -43
- package/dist/generators/templates/controllerTemplates.js +0 -82
- package/dist/generators/templates/newStoreTemplates.d.ts +0 -5
- package/dist/generators/templates/newStoreTemplates.js +0 -141
- package/dist/generators/templates/serviceTemplates.d.ts +0 -16
- package/dist/generators/templates/serviceTemplates.js +0 -59
- package/dist/generators/templates/validationTemplates.d.ts +0 -25
- package/dist/generators/templates/validationTemplates.js +0 -66
- package/dist/generators/templates/viewTemplates.d.ts +0 -25
- package/dist/generators/templates/viewTemplates.js +0 -491
- package/dist/generators/validationGenerator.d.ts +0 -29
- package/dist/generators/validationGenerator.js +0 -250
- package/dist/utils/new_parts_of_migrationUtils.d.ts +0 -0
- package/dist/utils/new_parts_of_migrationUtils.js +0 -164
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ModuleConfig } from '../types/configTypes';
|
|
2
2
|
export declare class StoreGenerator {
|
|
3
3
|
private availableValueObjects;
|
|
4
|
+
private availableAggregates;
|
|
5
|
+
private isAggregateField;
|
|
4
6
|
private isValueObjectType;
|
|
5
7
|
private getValueObjectName;
|
|
6
8
|
private getValueObjectConfig;
|
|
@@ -31,6 +33,8 @@ export declare class StoreGenerator {
|
|
|
31
33
|
private generateUpdateDataMapping;
|
|
32
34
|
private generateUpdateFieldsArray;
|
|
33
35
|
private generateValueObjectImports;
|
|
36
|
+
private generateAggregateRefImports;
|
|
37
|
+
private generateListMethods;
|
|
34
38
|
private generateGetByParentIdMethod;
|
|
35
39
|
private generateGetResourceOwnerMethod;
|
|
36
40
|
private generateStore;
|
|
@@ -46,6 +46,10 @@ const typeUtils_1 = require("../utils/typeUtils");
|
|
|
46
46
|
class StoreGenerator {
|
|
47
47
|
constructor() {
|
|
48
48
|
this.availableValueObjects = new Map();
|
|
49
|
+
this.availableAggregates = new Set();
|
|
50
|
+
}
|
|
51
|
+
isAggregateField(fieldConfig) {
|
|
52
|
+
return (0, typeUtils_1.isAggregateReference)(fieldConfig.type, this.availableAggregates);
|
|
49
53
|
}
|
|
50
54
|
isValueObjectType(fieldType) {
|
|
51
55
|
const capitalizedType = (0, typeUtils_1.capitalize)(fieldType);
|
|
@@ -64,8 +68,8 @@ class StoreGenerator {
|
|
|
64
68
|
*/
|
|
65
69
|
sortFieldsForConstructor(fields) {
|
|
66
70
|
return [...fields].sort((a, b) => {
|
|
67
|
-
const aRequired = a[1].required !== false && !a[1].auto;
|
|
68
|
-
const bRequired = b[1].required !== false && !b[1].auto;
|
|
71
|
+
const aRequired = a[1].required !== false && !a[1].auto && !this.isAggregateField(a[1]);
|
|
72
|
+
const bRequired = b[1].required !== false && !b[1].auto && !this.isAggregateField(b[1]);
|
|
69
73
|
if (aRequired === bRequired)
|
|
70
74
|
return 0;
|
|
71
75
|
return aRequired ? -1 : 1;
|
|
@@ -139,6 +143,10 @@ class StoreGenerator {
|
|
|
139
143
|
const ownerOrParentField = childInfo ? childInfo.parentIdField : 'ownerId';
|
|
140
144
|
result.push(` ${ownerOrParentField}: number;`);
|
|
141
145
|
fields.forEach(([fieldName, fieldConfig]) => {
|
|
146
|
+
if (this.isAggregateField(fieldConfig)) {
|
|
147
|
+
result.push(` ${fieldName}_id?: number;`);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
142
150
|
const tsType = this.mapTypeToRowType(fieldConfig.type);
|
|
143
151
|
const isOptional = !fieldConfig.required;
|
|
144
152
|
result.push(` ${fieldName}${isOptional ? '?' : ''}: ${tsType};`);
|
|
@@ -148,15 +156,26 @@ class StoreGenerator {
|
|
|
148
156
|
generateFieldNamesStr(fields, childInfo) {
|
|
149
157
|
const fieldNames = ['id'];
|
|
150
158
|
fieldNames.push(childInfo ? childInfo.parentIdField : 'ownerId');
|
|
151
|
-
fieldNames.push(...fields.map(([name]) => name));
|
|
159
|
+
fieldNames.push(...fields.map(([name, config]) => this.isAggregateField(config) ? `${name}_id` : name));
|
|
152
160
|
return fieldNames.map(f => `\\\`${f}\\\``).join(', ');
|
|
153
161
|
}
|
|
154
|
-
generateRowToModelMapping(fields, childInfo) {
|
|
162
|
+
generateRowToModelMapping(modelName, fields, childInfo) {
|
|
155
163
|
const result = [];
|
|
156
164
|
const ownerOrParentField = childInfo ? childInfo.parentIdField : 'ownerId';
|
|
157
165
|
result.push(` row.${ownerOrParentField}`);
|
|
158
166
|
fields.forEach(([fieldName, fieldConfig]) => {
|
|
159
167
|
const fieldType = fieldConfig.type;
|
|
168
|
+
// Handle enum type - cast string to the generated union type
|
|
169
|
+
if (fieldType === 'enum' && fieldConfig.values && fieldConfig.values.length > 0) {
|
|
170
|
+
const enumTypeName = `${modelName}${(0, typeUtils_1.capitalize)(fieldName)}`;
|
|
171
|
+
result.push(` row.${fieldName} as ${enumTypeName}`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// Handle aggregate reference - create stub from FK
|
|
175
|
+
if (this.isAggregateField(fieldConfig)) {
|
|
176
|
+
result.push(` row.${fieldName}_id != null ? ({ id: row.${fieldName}_id } as unknown as ${fieldType}) : undefined`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
160
179
|
// Handle datetime/date conversion
|
|
161
180
|
if (fieldType === 'datetime' || fieldType === 'date') {
|
|
162
181
|
result.push(this.generateDatetimeConversion(fieldName, 'toDate'));
|
|
@@ -189,6 +208,11 @@ class StoreGenerator {
|
|
|
189
208
|
result.push(` ${ownerOrParentField}: entity.${ownerOrParentField}`);
|
|
190
209
|
fields.forEach(([fieldName, fieldConfig]) => {
|
|
191
210
|
const fieldType = fieldConfig.type;
|
|
211
|
+
// Handle aggregate reference - extract FK id
|
|
212
|
+
if (this.isAggregateField(fieldConfig)) {
|
|
213
|
+
result.push(` ${fieldName}_id: entity.${fieldName}?.id`);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
192
216
|
// Handle datetime/date - convert Date to MySQL DATETIME format
|
|
193
217
|
if (fieldType === 'datetime' || fieldType === 'date') {
|
|
194
218
|
result.push(this.generateDatetimeConversion(fieldName, 'toMySQL'));
|
|
@@ -213,6 +237,9 @@ class StoreGenerator {
|
|
|
213
237
|
return fields
|
|
214
238
|
.map(([fieldName, fieldConfig]) => {
|
|
215
239
|
const fieldType = fieldConfig.type;
|
|
240
|
+
if (this.isAggregateField(fieldConfig)) {
|
|
241
|
+
return ` ${fieldName}_id: entity.${fieldName}?.id`;
|
|
242
|
+
}
|
|
216
243
|
if (fieldType === 'datetime' || fieldType === 'date') {
|
|
217
244
|
return this.generateDatetimeConversion(fieldName, 'toMySQL');
|
|
218
245
|
}
|
|
@@ -228,7 +255,7 @@ class StoreGenerator {
|
|
|
228
255
|
.join(',\n');
|
|
229
256
|
}
|
|
230
257
|
generateUpdateFieldsArray(fields) {
|
|
231
|
-
return JSON.stringify(fields.map(([name]) => name));
|
|
258
|
+
return JSON.stringify(fields.map(([name, config]) => this.isAggregateField(config) ? `${name}_id` : name));
|
|
232
259
|
}
|
|
233
260
|
generateValueObjectImports(fields) {
|
|
234
261
|
const imports = [];
|
|
@@ -255,10 +282,71 @@ class StoreGenerator {
|
|
|
255
282
|
}
|
|
256
283
|
return '\n' + uniqueImports.join('\n');
|
|
257
284
|
}
|
|
285
|
+
generateAggregateRefImports(modelName, fields) {
|
|
286
|
+
const imports = [];
|
|
287
|
+
fields.forEach(([, fieldConfig]) => {
|
|
288
|
+
if (this.isAggregateField(fieldConfig) && fieldConfig.type !== modelName) {
|
|
289
|
+
imports.push(`import { ${fieldConfig.type} } from '../../domain/entities/${fieldConfig.type}';`);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
const uniqueImports = [...new Set(imports)];
|
|
293
|
+
if (uniqueImports.length === 0)
|
|
294
|
+
return '';
|
|
295
|
+
return '\n' + uniqueImports.join('\n');
|
|
296
|
+
}
|
|
297
|
+
generateListMethods(modelName, fieldNamesStr, childInfo) {
|
|
298
|
+
const isRoot = !childInfo;
|
|
299
|
+
const ownerParam = isRoot ? ', ownerId?: number' : '';
|
|
300
|
+
const ownerFilter = isRoot
|
|
301
|
+
? `\n const ownerFilter = ownerId != null ? ' AND \\\`ownerId\\\` = :ownerId' : '';`
|
|
302
|
+
: '';
|
|
303
|
+
const ownerFilterRef = isRoot ? '\${ownerFilter}' : '';
|
|
304
|
+
const ownerParamsSetup = isRoot
|
|
305
|
+
? `\n if (ownerId != null) params.ownerId = ownerId;`
|
|
306
|
+
: '';
|
|
307
|
+
const getPaginated = ` async getPaginated(page: number = 1, limit: number = 20${ownerParam}): Promise<${modelName}[]> {
|
|
308
|
+
const offset = (page - 1) * limit;${ownerFilter}
|
|
309
|
+
const params: Record<string, any> = { limit: String(limit), offset: String(offset) };${ownerParamsSetup}
|
|
310
|
+
const result = await this.db.query(
|
|
311
|
+
\`SELECT ${fieldNamesStr} FROM \\\`\${this.tableName}\\\` WHERE deleted_at IS NULL${ownerFilterRef} LIMIT :limit OFFSET :offset\`,
|
|
312
|
+
params
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
if (result.success && result.data) {
|
|
316
|
+
return result.data.map((row: ${modelName}Row) => this.rowToModel(row));
|
|
317
|
+
}
|
|
318
|
+
return [];
|
|
319
|
+
}`;
|
|
320
|
+
const getAll = ` async getAll(${isRoot ? 'ownerId?: number' : ''}): Promise<${modelName}[]> {${ownerFilter}
|
|
321
|
+
const params: Record<string, any> = {};${ownerParamsSetup}
|
|
322
|
+
const result = await this.db.query(
|
|
323
|
+
\`SELECT ${fieldNamesStr} FROM \\\`\${this.tableName}\\\` WHERE deleted_at IS NULL${ownerFilterRef}\`,
|
|
324
|
+
params
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
if (result.success && result.data) {
|
|
328
|
+
return result.data.map((row: ${modelName}Row) => this.rowToModel(row));
|
|
329
|
+
}
|
|
330
|
+
return [];
|
|
331
|
+
}`;
|
|
332
|
+
const count = ` async count(${isRoot ? 'ownerId?: number' : ''}): Promise<number> {${ownerFilter}
|
|
333
|
+
const params: Record<string, any> = {};${ownerParamsSetup}
|
|
334
|
+
const result = await this.db.query(
|
|
335
|
+
\`SELECT COUNT(*) as count FROM \\\`\${this.tableName}\\\` WHERE deleted_at IS NULL${ownerFilterRef}\`,
|
|
336
|
+
params
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
if (result.success && result.data && result.data.length > 0) {
|
|
340
|
+
return parseInt(result.data[0].count, 10);
|
|
341
|
+
}
|
|
342
|
+
return 0;
|
|
343
|
+
}`;
|
|
344
|
+
return `${getPaginated}\n\n${getAll}\n\n${count}`;
|
|
345
|
+
}
|
|
258
346
|
generateGetByParentIdMethod(modelName, fields, childInfo) {
|
|
259
347
|
if (!childInfo)
|
|
260
348
|
return '';
|
|
261
|
-
const fieldList = ['id', childInfo.parentIdField, ...fields.map(([name]) => name)].map(f => '\\`' + f + '\\`').join(', ');
|
|
349
|
+
const fieldList = ['id', childInfo.parentIdField, ...fields.map(([name, config]) => this.isAggregateField(config) ? `${name}_id` : name)].map(f => '\\`' + f + '\\`').join(', ');
|
|
262
350
|
const parentIdField = childInfo.parentIdField;
|
|
263
351
|
return `
|
|
264
352
|
|
|
@@ -319,26 +407,38 @@ class StoreGenerator {
|
|
|
319
407
|
const fields = Object.entries(aggregateConfig.fields);
|
|
320
408
|
// Sort fields for rowToModel to match entity constructor order (required first, optional second)
|
|
321
409
|
const sortedFields = this.sortFieldsForConstructor(fields);
|
|
410
|
+
const fieldNamesStr = this.generateFieldNamesStr(fields, childInfo);
|
|
322
411
|
const variables = {
|
|
323
412
|
ENTITY_NAME: modelName,
|
|
324
413
|
TABLE_NAME: tableName,
|
|
325
414
|
ROW_FIELDS: this.generateRowFields(fields, childInfo),
|
|
326
|
-
FIELD_NAMES:
|
|
327
|
-
ROW_TO_MODEL_MAPPING: this.generateRowToModelMapping(sortedFields, childInfo),
|
|
415
|
+
FIELD_NAMES: fieldNamesStr,
|
|
416
|
+
ROW_TO_MODEL_MAPPING: this.generateRowToModelMapping(modelName, sortedFields, childInfo),
|
|
328
417
|
INSERT_DATA_MAPPING: this.generateInsertDataMapping(fields, childInfo),
|
|
329
418
|
UPDATE_DATA_MAPPING: this.generateUpdateDataMapping(fields),
|
|
330
419
|
UPDATE_FIELDS_ARRAY: this.generateUpdateFieldsArray(fields),
|
|
331
420
|
VALUE_OBJECT_IMPORTS: this.generateValueObjectImports(fields),
|
|
421
|
+
AGGREGATE_REF_IMPORTS: this.generateAggregateRefImports(modelName, fields),
|
|
422
|
+
LIST_METHODS: this.generateListMethods(modelName, fieldNamesStr, childInfo),
|
|
332
423
|
GET_BY_PARENT_ID_METHOD: this.generateGetByParentIdMethod(modelName, fields, childInfo),
|
|
333
424
|
GET_RESOURCE_OWNER_METHOD: this.generateGetResourceOwnerMethod(childInfo)
|
|
334
425
|
};
|
|
335
426
|
const rowInterface = this.replaceTemplateVars(storeTemplates_1.storeTemplates.rowInterface, variables);
|
|
336
427
|
const storeClass = this.replaceTemplateVars(storeTemplates_1.storeTemplates.storeClass, variables);
|
|
428
|
+
// Build entity import items: entity name + any enum type names
|
|
429
|
+
const entityImportItems = [modelName];
|
|
430
|
+
fields.forEach(([fieldName, fieldConfig]) => {
|
|
431
|
+
if (fieldConfig.type === 'enum' && fieldConfig.values && fieldConfig.values.length > 0) {
|
|
432
|
+
entityImportItems.push(`${modelName}${(0, typeUtils_1.capitalize)(fieldName)}`);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
337
435
|
return this.replaceTemplateVars(storeTemplates_1.storeFileTemplate, {
|
|
338
436
|
ENTITY_NAME: modelName,
|
|
437
|
+
ENTITY_IMPORT_ITEMS: entityImportItems.join(', '),
|
|
339
438
|
ROW_INTERFACE: rowInterface,
|
|
340
439
|
STORE_CLASS: storeClass,
|
|
341
|
-
VALUE_OBJECT_IMPORTS: variables.VALUE_OBJECT_IMPORTS
|
|
440
|
+
VALUE_OBJECT_IMPORTS: variables.VALUE_OBJECT_IMPORTS,
|
|
441
|
+
AGGREGATE_REF_IMPORTS: variables.AGGREGATE_REF_IMPORTS
|
|
342
442
|
});
|
|
343
443
|
}
|
|
344
444
|
generateFromConfig(config) {
|
|
@@ -350,6 +450,13 @@ class StoreGenerator {
|
|
|
350
450
|
this.availableValueObjects.set(name, voConfig);
|
|
351
451
|
});
|
|
352
452
|
}
|
|
453
|
+
// Collect all aggregate names for detecting entity references
|
|
454
|
+
this.availableAggregates.clear();
|
|
455
|
+
if (config.domain.aggregates) {
|
|
456
|
+
Object.keys(config.domain.aggregates).forEach(name => {
|
|
457
|
+
this.availableAggregates.add(name);
|
|
458
|
+
});
|
|
459
|
+
}
|
|
353
460
|
// Generate a store for each aggregate
|
|
354
461
|
const childEntityMap = (0, childEntityUtils_1.buildChildEntityMap)(config);
|
|
355
462
|
if (config.domain.aggregates) {
|
|
@@ -374,7 +374,10 @@ window.AppConfig = {
|
|
|
374
374
|
*/
|
|
375
375
|
function navigateToPage(url, targetElement = null) {
|
|
376
376
|
const target = targetElement || document.querySelector('#main');
|
|
377
|
-
if (!target)
|
|
377
|
+
if (!target) {
|
|
378
|
+
window.location.href = url;
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
378
381
|
|
|
379
382
|
showLoading('#main');
|
|
380
383
|
|
|
@@ -388,18 +391,22 @@ window.AppConfig = {
|
|
|
388
391
|
if (!response.ok) {
|
|
389
392
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
390
393
|
}
|
|
394
|
+
const targetLayout = response.headers.get('X-Layout') || '';
|
|
395
|
+
const currentLayout = (document.querySelector('meta[name="app-layout"]') || {}).content || '';
|
|
396
|
+
if (targetLayout !== currentLayout) {
|
|
397
|
+
window.location.href = url;
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
391
400
|
return response.text();
|
|
392
401
|
})
|
|
393
402
|
.then(html => {
|
|
403
|
+
if (html === null) return;
|
|
394
404
|
target.innerHTML = html;
|
|
395
|
-
// Update browser history
|
|
396
405
|
window.history.pushState({}, '', url);
|
|
397
|
-
// No need to re-initialize - delegation handles new content automatically
|
|
398
406
|
})
|
|
399
407
|
.catch(error => {
|
|
400
408
|
console.error('Navigation failed:', error);
|
|
401
409
|
showToast('Failed to load page', 'error');
|
|
402
|
-
// Fallback to normal navigation
|
|
403
410
|
window.location.href = url;
|
|
404
411
|
})
|
|
405
412
|
.finally(() => {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>Your App</title>
|
|
8
|
+
<meta name="app-layout" content="main_view">
|
|
8
9
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
|
9
10
|
<script src="/app.js"></script>
|
|
10
11
|
</head>
|
|
@@ -2,4 +2,4 @@ export declare const storeTemplates: {
|
|
|
2
2
|
rowInterface: string;
|
|
3
3
|
storeClass: string;
|
|
4
4
|
};
|
|
5
|
-
export declare const storeFileTemplate = "import { Injectable } from '../../../../system';\nimport { {{
|
|
5
|
+
export declare const storeFileTemplate = "import { Injectable } from '../../../../system';\nimport { {{ENTITY_IMPORT_ITEMS}} } from '../../domain/entities/{{ENTITY_NAME}}';\nimport type { ISqlProvider } from '@currentjs/provider-mysql';{{VALUE_OBJECT_IMPORTS}}{{AGGREGATE_REF_IMPORTS}}\n\n{{ROW_INTERFACE}}\n\n{{STORE_CLASS}}\n";
|
|
@@ -29,30 +29,7 @@ export class {{ENTITY_NAME}}Store {
|
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
const offset = (page - 1) * limit;
|
|
34
|
-
const result = await this.db.query(
|
|
35
|
-
\`SELECT {{FIELD_NAMES}} FROM \\\`\${this.tableName}\\\` WHERE deleted_at IS NULL LIMIT :limit OFFSET :offset\`,
|
|
36
|
-
{ limit: String(limit), offset: String(offset) }
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
if (result.success && result.data) {
|
|
40
|
-
return result.data.map((row: {{ENTITY_NAME}}Row) => this.rowToModel(row));
|
|
41
|
-
}
|
|
42
|
-
return [];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async count(): Promise<number> {
|
|
46
|
-
const result = await this.db.query(
|
|
47
|
-
\`SELECT COUNT(*) as count FROM \\\`\${this.tableName}\\\` WHERE deleted_at IS NULL\`,
|
|
48
|
-
{}
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
if (result.success && result.data && result.data.length > 0) {
|
|
52
|
-
return parseInt(result.data[0].count, 10);
|
|
53
|
-
}
|
|
54
|
-
return 0;
|
|
55
|
-
}
|
|
32
|
+
{{LIST_METHODS}}
|
|
56
33
|
|
|
57
34
|
async getById(id: number): Promise<{{ENTITY_NAME}} | null> {
|
|
58
35
|
const result = await this.db.query(
|
|
@@ -134,8 +111,8 @@ export class {{ENTITY_NAME}}Store {
|
|
|
134
111
|
{{GET_RESOURCE_OWNER_METHOD}}}`
|
|
135
112
|
};
|
|
136
113
|
exports.storeFileTemplate = `import { Injectable } from '../../../../system';
|
|
137
|
-
import { {{
|
|
138
|
-
import type { ISqlProvider } from '@currentjs/provider-mysql';{{VALUE_OBJECT_IMPORTS}}
|
|
114
|
+
import { {{ENTITY_IMPORT_ITEMS}} } from '../../domain/entities/{{ENTITY_NAME}}';
|
|
115
|
+
import type { ISqlProvider } from '@currentjs/provider-mysql';{{VALUE_OBJECT_IMPORTS}}{{AGGREGATE_REF_IMPORTS}}
|
|
139
116
|
|
|
140
117
|
{{ROW_INTERFACE}}
|
|
141
118
|
|
|
@@ -71,8 +71,8 @@ class UseCaseGenerator {
|
|
|
71
71
|
let params = '';
|
|
72
72
|
if (defaultAction === 'list') {
|
|
73
73
|
params = ((_a = useCaseConfig.input) === null || _a === void 0 ? void 0 : _a.pagination)
|
|
74
|
-
? 'input.page || 1, input.limit || 20'
|
|
75
|
-
: '';
|
|
74
|
+
? 'input.page || 1, input.limit || 20, ownerId'
|
|
75
|
+
: 'ownerId';
|
|
76
76
|
}
|
|
77
77
|
else if (defaultAction === 'get') {
|
|
78
78
|
params = 'input.id';
|
|
@@ -99,7 +99,10 @@ class UseCaseGenerator {
|
|
|
99
99
|
}
|
|
100
100
|
}).join('\n');
|
|
101
101
|
const returnStatement = '\n return result;';
|
|
102
|
-
|
|
102
|
+
const methodParams = actionName === 'list'
|
|
103
|
+
? `input: ${inputType}, ownerId?: number`
|
|
104
|
+
: `input: ${inputType}`;
|
|
105
|
+
return ` async ${methodName}(${methodParams}): Promise<${returnType}> {
|
|
103
106
|
${handlerCalls}${returnStatement}
|
|
104
107
|
}`;
|
|
105
108
|
}
|
|
@@ -13,6 +13,10 @@ export declare function capitalize(str: string): string;
|
|
|
13
13
|
* Map a YAML field type to TypeScript type, resolving aggregates and value objects by name.
|
|
14
14
|
*/
|
|
15
15
|
export declare function mapType(yamlType: string, aggregates?: Set<string> | Map<string, unknown>, valueObjects?: Set<string> | Map<string, unknown>): string;
|
|
16
|
+
/**
|
|
17
|
+
* Check if a YAML field type references another aggregate entity.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isAggregateReference(yamlType: string, aggregates?: Set<string> | Map<string, unknown>): boolean;
|
|
16
20
|
/**
|
|
17
21
|
* Map a YAML type to the store row TypeScript type (value objects become string).
|
|
18
22
|
*/
|
package/dist/utils/typeUtils.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.ROW_TYPE_MAPPING = exports.TYPE_MAPPING = void 0;
|
|
7
7
|
exports.capitalize = capitalize;
|
|
8
8
|
exports.mapType = mapType;
|
|
9
|
+
exports.isAggregateReference = isAggregateReference;
|
|
9
10
|
exports.mapRowType = mapRowType;
|
|
10
11
|
/** Standard YAML type to TypeScript (domain) type mapping. */
|
|
11
12
|
exports.TYPE_MAPPING = {
|
|
@@ -55,6 +56,12 @@ function mapType(yamlType, aggregates, valueObjects) {
|
|
|
55
56
|
}
|
|
56
57
|
return (_a = exports.TYPE_MAPPING[yamlType]) !== null && _a !== void 0 ? _a : 'any';
|
|
57
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Check if a YAML field type references another aggregate entity.
|
|
61
|
+
*/
|
|
62
|
+
function isAggregateReference(yamlType, aggregates) {
|
|
63
|
+
return !!(aggregates === null || aggregates === void 0 ? void 0 : aggregates.has(yamlType));
|
|
64
|
+
}
|
|
58
65
|
/**
|
|
59
66
|
* Map a YAML type to the store row TypeScript type (value objects become string).
|
|
60
67
|
*/
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function handleMigratePush(yamlPath?: string): Promise<void>;
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.handleMigratePush = handleMigratePush;
|
|
37
|
-
const fs = __importStar(require("fs"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
const colors_1 = require("../utils/colors");
|
|
40
|
-
const cliUtils_1 = require("../utils/cliUtils");
|
|
41
|
-
const migrationUtils_1 = require("../utils/migrationUtils");
|
|
42
|
-
async function handleMigratePush(yamlPath) {
|
|
43
|
-
let connection;
|
|
44
|
-
try {
|
|
45
|
-
const resolvedYamlPath = (0, cliUtils_1.resolveYamlPath)(yamlPath);
|
|
46
|
-
const projectRoot = path.dirname(resolvedYamlPath);
|
|
47
|
-
const migrationsDir = path.join(projectRoot, 'migrations');
|
|
48
|
-
// Check if migrations directory exists
|
|
49
|
-
if (!fs.existsSync(migrationsDir)) {
|
|
50
|
-
// eslint-disable-next-line no-console
|
|
51
|
-
console.log(colors_1.colors.yellow('⚠️ No migrations directory found. Run "currentjs migrate commit" first.'));
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
// Get all migration files
|
|
55
|
-
const migrationFiles = fs.readdirSync(migrationsDir)
|
|
56
|
-
.filter(f => f.endsWith('.sql'))
|
|
57
|
-
.sort();
|
|
58
|
-
if (migrationFiles.length === 0) {
|
|
59
|
-
// eslint-disable-next-line no-console
|
|
60
|
-
console.log(colors_1.colors.yellow('⚠️ No migration files found. Run "currentjs migrate commit" first.'));
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
// eslint-disable-next-line no-console
|
|
64
|
-
console.log(colors_1.colors.cyan('\n🔌 Connecting to database...'));
|
|
65
|
-
// Verify environment variables
|
|
66
|
-
if (!process.env.DB_HOST || !process.env.DB_USER || !process.env.DB_NAME) {
|
|
67
|
-
// eslint-disable-next-line no-console
|
|
68
|
-
console.log(colors_1.colors.yellow('\n💡 Database configuration:'));
|
|
69
|
-
// eslint-disable-next-line no-console
|
|
70
|
-
console.log(colors_1.colors.gray(` Host: ${process.env.DB_HOST || 'localhost (default)'}`));
|
|
71
|
-
// eslint-disable-next-line no-console
|
|
72
|
-
console.log(colors_1.colors.gray(` Port: ${process.env.DB_PORT || '3306 (default)'}`));
|
|
73
|
-
// eslint-disable-next-line no-console
|
|
74
|
-
console.log(colors_1.colors.gray(` User: ${process.env.DB_USER || 'root (default)'}`));
|
|
75
|
-
// eslint-disable-next-line no-console
|
|
76
|
-
console.log(colors_1.colors.gray(` Database: ${process.env.DB_NAME || 'test (default)'}`));
|
|
77
|
-
if (!process.env.DB_HOST || !process.env.DB_USER || !process.env.DB_NAME) {
|
|
78
|
-
// eslint-disable-next-line no-console
|
|
79
|
-
console.log(colors_1.colors.yellow('\n⚠️ Environment variables not set. Using defaults.'));
|
|
80
|
-
// eslint-disable-next-line no-console
|
|
81
|
-
console.log(colors_1.colors.cyan(' Set DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME to configure.'));
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
connection = await (0, migrationUtils_1.connectToDatabase)();
|
|
85
|
-
// eslint-disable-next-line no-console
|
|
86
|
-
console.log(colors_1.colors.green('✓ Connected to database'));
|
|
87
|
-
// Get already applied migrations
|
|
88
|
-
// eslint-disable-next-line no-console
|
|
89
|
-
console.log(colors_1.colors.cyan('\n📖 Checking applied migrations...'));
|
|
90
|
-
const appliedMigrations = await (0, migrationUtils_1.getAppliedMigrations)(connection);
|
|
91
|
-
// eslint-disable-next-line no-console
|
|
92
|
-
console.log(colors_1.colors.gray(` Applied: ${appliedMigrations.length} migration(s)`));
|
|
93
|
-
// Find pending migrations
|
|
94
|
-
const pendingMigrations = migrationFiles.filter(f => !appliedMigrations.includes(f));
|
|
95
|
-
if (pendingMigrations.length === 0) {
|
|
96
|
-
// eslint-disable-next-line no-console
|
|
97
|
-
console.log(colors_1.colors.green('\n✅ Database is up to date. No pending migrations.'));
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
// eslint-disable-next-line no-console
|
|
101
|
-
console.log(colors_1.colors.cyan(`\n🚀 Applying ${pendingMigrations.length} migration(s)...`));
|
|
102
|
-
// Apply pending migrations
|
|
103
|
-
for (const migrationFile of pendingMigrations) {
|
|
104
|
-
const migrationPath = path.join(migrationsDir, migrationFile);
|
|
105
|
-
const migrationSQL = fs.readFileSync(migrationPath, 'utf8');
|
|
106
|
-
// eslint-disable-next-line no-console
|
|
107
|
-
console.log(colors_1.colors.gray(` → ${migrationFile}...`));
|
|
108
|
-
try {
|
|
109
|
-
await (0, migrationUtils_1.executeMigration)(connection, migrationSQL);
|
|
110
|
-
await (0, migrationUtils_1.recordMigration)(connection, migrationFile);
|
|
111
|
-
// eslint-disable-next-line no-console
|
|
112
|
-
console.log(colors_1.colors.green(` ✓ ${migrationFile} applied`));
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
// eslint-disable-next-line no-console
|
|
116
|
-
console.error(colors_1.colors.red(` ✗ Failed to apply ${migrationFile}:`));
|
|
117
|
-
// eslint-disable-next-line no-console
|
|
118
|
-
console.error(colors_1.colors.red(` ${error instanceof Error ? error.message : String(error)}`));
|
|
119
|
-
throw error;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
// eslint-disable-next-line no-console
|
|
123
|
-
console.log(colors_1.colors.green('\n✅ All migrations applied successfully!'));
|
|
124
|
-
}
|
|
125
|
-
catch (error) {
|
|
126
|
-
// eslint-disable-next-line no-console
|
|
127
|
-
console.error(colors_1.colors.red('\n❌ Error applying migrations:'), error instanceof Error ? error.message : String(error));
|
|
128
|
-
process.exitCode = 1;
|
|
129
|
-
}
|
|
130
|
-
finally {
|
|
131
|
-
if (connection) {
|
|
132
|
-
await connection.end();
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function handleMigrateUpdate(yamlPath?: string): Promise<void>;
|