@currentjs/gen 0.3.2 → 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.
Files changed (60) hide show
  1. package/CHANGELOG.md +18 -609
  2. package/README.md +623 -427
  3. package/dist/cli.js +2 -1
  4. package/dist/commands/commit.js +25 -42
  5. package/dist/commands/createApp.js +1 -0
  6. package/dist/commands/createModule.js +151 -45
  7. package/dist/commands/diff.js +27 -40
  8. package/dist/commands/generateAll.js +141 -291
  9. package/dist/commands/migrateCommit.js +6 -18
  10. package/dist/generators/controllerGenerator.d.ts +50 -19
  11. package/dist/generators/controllerGenerator.js +588 -331
  12. package/dist/generators/domainLayerGenerator.d.ts +21 -0
  13. package/dist/generators/domainLayerGenerator.js +286 -0
  14. package/dist/generators/dtoGenerator.d.ts +21 -0
  15. package/dist/generators/dtoGenerator.js +523 -0
  16. package/dist/generators/serviceGenerator.d.ts +22 -51
  17. package/dist/generators/serviceGenerator.js +345 -568
  18. package/dist/generators/storeGenerator.d.ts +39 -32
  19. package/dist/generators/storeGenerator.js +396 -236
  20. package/dist/generators/templateGenerator.d.ts +21 -21
  21. package/dist/generators/templateGenerator.js +393 -268
  22. package/dist/generators/templates/appTemplates.d.ts +3 -1
  23. package/dist/generators/templates/appTemplates.js +16 -11
  24. package/dist/generators/templates/data/appYamlTemplate +5 -2
  25. package/dist/generators/templates/data/cursorRulesTemplate +315 -221
  26. package/dist/generators/templates/data/frontendScriptTemplate +56 -15
  27. package/dist/generators/templates/data/mainViewTemplate +2 -1
  28. package/dist/generators/templates/data/systemTsTemplate +5 -0
  29. package/dist/generators/templates/index.d.ts +0 -3
  30. package/dist/generators/templates/index.js +0 -3
  31. package/dist/generators/templates/storeTemplates.d.ts +1 -5
  32. package/dist/generators/templates/storeTemplates.js +84 -224
  33. package/dist/generators/useCaseGenerator.d.ts +13 -0
  34. package/dist/generators/useCaseGenerator.js +191 -0
  35. package/dist/types/configTypes.d.ts +149 -0
  36. package/dist/types/configTypes.js +10 -0
  37. package/dist/utils/childEntityUtils.d.ts +18 -0
  38. package/dist/utils/childEntityUtils.js +78 -0
  39. package/dist/utils/commandUtils.d.ts +43 -0
  40. package/dist/utils/commandUtils.js +124 -0
  41. package/dist/utils/commitUtils.d.ts +4 -1
  42. package/dist/utils/constants.d.ts +10 -0
  43. package/dist/utils/constants.js +13 -1
  44. package/dist/utils/diResolver.d.ts +32 -0
  45. package/dist/utils/diResolver.js +204 -0
  46. package/dist/utils/typeUtils.d.ts +23 -0
  47. package/dist/utils/typeUtils.js +77 -0
  48. package/package.json +7 -3
  49. package/dist/generators/domainModelGenerator.d.ts +0 -41
  50. package/dist/generators/domainModelGenerator.js +0 -242
  51. package/dist/generators/templates/controllerTemplates.d.ts +0 -43
  52. package/dist/generators/templates/controllerTemplates.js +0 -82
  53. package/dist/generators/templates/serviceTemplates.d.ts +0 -16
  54. package/dist/generators/templates/serviceTemplates.js +0 -59
  55. package/dist/generators/templates/validationTemplates.d.ts +0 -25
  56. package/dist/generators/templates/validationTemplates.js +0 -66
  57. package/dist/generators/templates/viewTemplates.d.ts +0 -25
  58. package/dist/generators/templates/viewTemplates.js +0 -491
  59. package/dist/generators/validationGenerator.d.ts +0 -29
  60. package/dist/generators/validationGenerator.js +0 -250
@@ -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) return;
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(() => {
@@ -414,7 +421,7 @@ window.AppConfig = {
414
421
  * @returns {any} Converted value
415
422
  */
416
423
  function convertFieldValue(value, fieldType) {
417
- if (!value || value === '') {
424
+ if (value === undefined || value === null || value === '') {
418
425
  return null;
419
426
  }
420
427
 
@@ -422,6 +429,7 @@ window.AppConfig = {
422
429
  case 'number':
423
430
  case 'int':
424
431
  case 'integer':
432
+ case 'id':
425
433
  const intVal = parseInt(value, 10);
426
434
  return isNaN(intVal) ? null : intVal;
427
435
 
@@ -432,10 +440,15 @@ window.AppConfig = {
432
440
 
433
441
  case 'boolean':
434
442
  case 'bool':
435
- if (value === 'true') return true;
436
- if (value === 'false') return false;
443
+ if (value === 'true' || value === 'on' || value === '1') return true;
444
+ if (value === 'false' || value === 'off' || value === '0') return false;
437
445
  return Boolean(value);
446
+
447
+ case 'json':
448
+ try { return JSON.parse(value); } catch { return value; }
438
449
 
450
+ case 'datetime':
451
+ case 'date':
439
452
  case 'enum':
440
453
  case 'string':
441
454
  case 'text':
@@ -474,6 +487,30 @@ window.AppConfig = {
474
487
  jsonData[key] = convertedValue;
475
488
  }
476
489
  }
490
+
491
+ // Unchecked checkboxes are not included in FormData — default to false
492
+ for (const [fieldName, fieldType] of Object.entries(fieldTypes)) {
493
+ const ft = fieldType.toLowerCase();
494
+ if ((ft === 'boolean' || ft === 'bool') && !(fieldName in jsonData)) {
495
+ jsonData[fieldName] = false;
496
+ }
497
+ }
498
+
499
+ // Unflatten dot-notation keys (e.g., "amount.currency") into nested objects
500
+ const finalData = {};
501
+ for (const [key, value] of Object.entries(jsonData)) {
502
+ if (key.includes('.')) {
503
+ const parts = key.split('.');
504
+ let current = finalData;
505
+ for (let i = 0; i < parts.length - 1; i++) {
506
+ if (!(parts[i] in current)) current[parts[i]] = {};
507
+ current = current[parts[i]];
508
+ }
509
+ current[parts[parts.length - 1]] = value;
510
+ } else {
511
+ finalData[key] = value;
512
+ }
513
+ }
477
514
 
478
515
  const url = form.getAttribute('data-action') || form.action;
479
516
  const method = (form.getAttribute('data-method') || form.method || 'POST').toUpperCase();
@@ -486,16 +523,20 @@ window.AppConfig = {
486
523
  'Content-Type': 'application/json',
487
524
  'Accept': 'application/json'
488
525
  }),
489
- body: JSON.stringify(jsonData)
526
+ body: JSON.stringify(finalData)
490
527
  })
491
- .then(response => {
492
- if (!response.ok) {
493
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
528
+ .then(response =>
529
+ response.json()
530
+ .catch(() => ({}))
531
+ .then(body => ({ ok: response.ok, status: response.status, statusText: response.statusText, body }))
532
+ )
533
+ .then(({ ok, status, statusText, body }) => {
534
+ if (!ok) {
535
+ const message = body.message || body.error || `HTTP ${status}: ${statusText}`;
536
+ handleFormError({ message }, options);
537
+ return;
494
538
  }
495
- return response.json();
496
- })
497
- .then(data => {
498
- handleFormSuccess(data, strategy, options);
539
+ handleFormSuccess(body, strategy, options);
499
540
  })
500
541
  .catch(error => {
501
542
  console.error('Form submission failed:', error);
@@ -5,12 +5,13 @@
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>
11
12
  <body>
12
13
  <div class="container-fluid">
13
- <div id="main">{{ content }}</div>
14
+ <div id="main">{{{ content }}}</div>
14
15
  </div>
15
16
  </body>
16
17
  </html>
@@ -0,0 +1,5 @@
1
+ export function Injectable() {
2
+ return function (target: any) {
3
+ target.__injectable = true;
4
+ };
5
+ }
@@ -1,5 +1,2 @@
1
- export * from './serviceTemplates';
2
- export * from './controllerTemplates';
3
1
  export * from './storeTemplates';
4
- export * from './validationTemplates';
5
2
  export * from './appTemplates';
@@ -14,8 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./serviceTemplates"), exports);
18
- __exportStar(require("./controllerTemplates"), exports);
19
17
  __exportStar(require("./storeTemplates"), exports);
20
- __exportStar(require("./validationTemplates"), exports);
21
18
  __exportStar(require("./appTemplates"), exports);
@@ -1,9 +1,5 @@
1
1
  export declare const storeTemplates: {
2
2
  rowInterface: string;
3
3
  storeClass: string;
4
- conversionMethods: string;
5
- };
6
- export declare const fileTemplates: {
7
- storeFile: string;
8
- storeInterface: string;
9
4
  };
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";
@@ -1,260 +1,120 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fileTemplates = exports.storeTemplates = void 0;
3
+ exports.storeFileTemplate = exports.storeTemplates = void 0;
4
4
  exports.storeTemplates = {
5
5
  rowInterface: `export interface {{ENTITY_NAME}}Row {
6
6
  id: number;
7
7
  {{ROW_FIELDS}}
8
- created_at: Date;
9
- updated_at: Date;
10
- deleted_at?: Date;
8
+ created_at: string;
9
+ updated_at: string;
10
+ deleted_at?: string;
11
11
  }`,
12
- storeClass: `export class {{ENTITY_NAME}}Store implements StoreInterface<{{ENTITY_NAME}}, {{ENTITY_NAME}}Row> {
13
- private static readonly FILTERABLE_FIELDS = [{{FILTERABLE_FIELDS_ARRAY}}];
14
- private static readonly UPDATABLE_FIELDS = [{{UPDATABLE_FIELDS_ARRAY}}];
15
-
12
+ storeClass: `/**
13
+ * Data access layer for {{ENTITY_NAME}}
14
+ */
15
+ @Injectable()
16
+ export class {{ENTITY_NAME}}Store {
17
+ private tableName = '{{TABLE_NAME}}';
18
+
16
19
  constructor(private db: ISqlProvider) {}
17
20
 
18
- async getById(id: number): Promise<{{ENTITY_NAME}} | null> {
19
- try {
20
- const query = 'SELECT * FROM {{TABLE_NAME}} WHERE id = :id AND deleted_at IS NULL';
21
- const result = await this.db.query(query, { id });
22
-
23
- if (!result.success || result.data.length === 0) {
24
- return null;
25
- }
26
-
27
- return {{ENTITY_NAME}}Store.rowToModel(result.data[0] as {{ENTITY_NAME}}Row);
28
- } catch (error) {
29
- if (error instanceof MySQLConnectionError) {
30
- throw new Error(\`Database connection error while fetching {{ENTITY_NAME}} with id \${id}: \${error.message}\`);
31
- } else if (error instanceof MySQLQueryError) {
32
- throw new Error(\`Query error while fetching {{ENTITY_NAME}} with id \${id}: \${error.message}\`);
33
- }
34
- throw error;
35
- }
21
+ private toMySQLDatetime(date: Date): string {
22
+ return date.toISOString().slice(0, 19).replace('T', ' ');
36
23
  }
37
24
 
38
- async getAll(page: number = 1, limit: number = 10): Promise<{{ENTITY_NAME}}[]> {
39
- const offset = (page - 1) * limit;
40
- const query = \`SELECT * FROM {{TABLE_NAME}} WHERE deleted_at IS NULL ORDER BY created_at DESC LIMIT \${limit} OFFSET \${offset}\`;
41
- const result = await this.db.query(query, {});
42
-
43
- if (!result.success) {
44
- return [];
45
- }
46
-
47
- return result.data.map((row: {{ENTITY_NAME}}Row) => {{ENTITY_NAME}}Store.rowToModel(row));
25
+ private rowToModel(row: {{ENTITY_NAME}}Row): {{ENTITY_NAME}} {
26
+ return new {{ENTITY_NAME}}(
27
+ row.id,
28
+ {{ROW_TO_MODEL_MAPPING}}
29
+ );
48
30
  }
49
31
 
50
- async getAllByUserId(userId: number, page: number = 1, limit: number = 10): Promise<{{ENTITY_NAME}}[]> {
51
- const offset = (page - 1) * limit;
52
- const query = \`SELECT * FROM {{TABLE_NAME}} WHERE user_id = :userId AND deleted_at IS NULL ORDER BY created_at DESC LIMIT \${limit} OFFSET \${offset}\`;
53
- const result = await this.db.query(query, { userId });
54
-
55
- if (!result.success) {
56
- return [];
57
- }
58
-
59
- return result.data.map((row: {{ENTITY_NAME}}Row) => {{ENTITY_NAME}}Store.rowToModel(row));
60
- }
32
+ {{LIST_METHODS}}
61
33
 
62
- async getBy(filters: Partial<Pick<{{ENTITY_NAME}}Row, {{FILTERABLE_FIELDS}}>>): Promise<{{ENTITY_NAME}} | null> {
63
- const filterKeys = Object.keys(filters);
64
-
65
- // Runtime validation against SQL injection
66
- for (const key of filterKeys) {
67
- if (!{{ENTITY_NAME}}Store.FILTERABLE_FIELDS.includes(key)) {
68
- throw new Error(\`Invalid filter field: \${key}\`);
69
- }
70
- }
71
-
72
- const whereConditions = filterKeys.map(key => \`\${key} = :\${key}\`);
73
-
74
- if (whereConditions.length === 0) {
75
- throw new Error('At least one filter condition is required');
76
- }
77
-
78
- const query = \`SELECT * FROM {{TABLE_NAME}} WHERE \${whereConditions.join(' AND ')} AND deleted_at IS NULL LIMIT 1\`;
79
- const result = await this.db.query(query, filters);
80
-
81
- if (!result.success || result.data.length === 0) {
82
- return null;
83
- }
84
-
85
- return {{ENTITY_NAME}}Store.rowToModel(result.data[0] as {{ENTITY_NAME}}Row);
86
- }
34
+ async getById(id: number): Promise<{{ENTITY_NAME}} | null> {
35
+ const result = await this.db.query(
36
+ \`SELECT {{FIELD_NAMES}} FROM \\\`\${this.tableName}\\\` WHERE id = :id AND deleted_at IS NULL\`,
37
+ { id }
38
+ );
87
39
 
88
- async getAllBy(filters: Partial<Pick<{{ENTITY_NAME}}Row, {{FILTERABLE_FIELDS}}>>): Promise<{{ENTITY_NAME}}[]> {
89
- const filterKeys = Object.keys(filters);
90
-
91
- // Runtime validation against SQL injection
92
- for (const key of filterKeys) {
93
- if (!{{ENTITY_NAME}}Store.FILTERABLE_FIELDS.includes(key)) {
94
- throw new Error(\`Invalid filter field: \${key}\`);
95
- }
96
- }
97
-
98
- const whereConditions = filterKeys.map(key => \`\${key} = :\${key}\`);
99
-
100
- if (whereConditions.length === 0) {
101
- return this.getAll();
102
- }
103
-
104
- const query = \`SELECT * FROM {{TABLE_NAME}} WHERE \${whereConditions.join(' AND ')} AND deleted_at IS NULL ORDER BY created_at DESC\`;
105
- const result = await this.db.query(query, filters);
106
-
107
- if (!result.success) {
108
- return [];
40
+ if (result.success && result.data && result.data.length > 0) {
41
+ return this.rowToModel(result.data[0] as {{ENTITY_NAME}}Row);
109
42
  }
110
-
111
- return result.data.map((row: {{ENTITY_NAME}}Row) => {{ENTITY_NAME}}Store.rowToModel(row));
43
+ return null;
112
44
  }
113
45
 
114
- async insert(model: Omit<{{ENTITY_NAME}}, 'id'>): Promise<{{ENTITY_NAME}}> {
115
- try {
116
- const row = {{ENTITY_NAME}}Store.modelToRow(model as {{ENTITY_NAME}});
117
- delete row.id; // Remove id for insert
118
- row.created_at = new Date();
119
- row.updated_at = new Date();
120
-
121
- const fields = Object.keys(row);
122
- const placeholders = fields.map(field => \`:\${field}\`).join(', ');
123
-
124
- const query = \`INSERT INTO {{TABLE_NAME}} (\${fields.join(', ')}) VALUES (\${placeholders})\`;
125
- const result = await this.db.query(query, row);
126
-
127
- if (!result.success || !result.insertId) {
128
- throw new Error('Failed to insert {{ENTITY_NAME}}: Insert operation did not return a valid ID');
129
- }
130
-
131
- return this.getById(Number(result.insertId));
132
- } catch (error) {
133
- if (error instanceof MySQLQueryError) {
134
- throw new Error(\`Failed to insert {{ENTITY_NAME}}: \${error.message}\`);
135
- } else if (error instanceof MySQLConnectionError) {
136
- throw new Error(\`Database connection error while inserting {{ENTITY_NAME}}: \${error.message}\`);
137
- }
138
- throw error;
139
- }
140
- }
46
+ async insert(entity: {{ENTITY_NAME}}): Promise<{{ENTITY_NAME}}> {
47
+ const now = new Date();
48
+ const data: Partial<{{ENTITY_NAME}}Row> = {
49
+ {{INSERT_DATA_MAPPING}},
50
+ created_at: this.toMySQLDatetime(now),
51
+ updated_at: this.toMySQLDatetime(now)
52
+ };
141
53
 
142
- async update(id: number, updates: Partial<Omit<{{ENTITY_NAME}}, 'id' | 'createdAt'>>): Promise<{{ENTITY_NAME}} | null> {
143
- const existing = await this.getById(id);
144
- if (!existing) {
145
- return null;
146
- }
147
-
148
- // Extract only data properties, not methods
149
- const updateData = this.extractDataProperties(updates);
150
- const updateKeys = Object.keys(updateData);
151
-
152
- // Runtime validation against SQL injection
153
- for (const key of updateKeys) {
154
- if (!{{ENTITY_NAME}}Store.UPDATABLE_FIELDS.includes(key)) {
155
- throw new Error(\`Invalid update field: \${key}\`);
156
- }
157
- }
158
-
159
- const updateFields = updateKeys.map(key => \`\${key} = :\${key}\`);
160
-
161
- if (updateFields.length === 0) {
162
- return existing;
54
+ const fieldsList = Object.keys(data).map(f => \`\\\`\${f}\\\`\`).join(', ');
55
+ const placeholders = Object.keys(data).map(f => \`:\${f}\`).join(', ');
56
+
57
+ const result = await this.db.query(
58
+ \`INSERT INTO \\\`\${this.tableName}\\\` (\${fieldsList}) VALUES (\${placeholders})\`,
59
+ data
60
+ );
61
+
62
+ if (result.success && result.insertId) {
63
+ const newId = typeof result.insertId === 'string' ? parseInt(result.insertId, 10) : result.insertId;
64
+ return this.getById(newId) as Promise<{{ENTITY_NAME}}>;
163
65
  }
164
-
165
- const params = { ...updateData, updated_at: new Date(), id };
166
-
167
- const query = \`UPDATE {{TABLE_NAME}} SET \${updateFields.join(', ')}, updated_at = :updated_at WHERE id = :id\`;
168
- await this.db.query(query, params);
169
-
170
- return this.getById(id);
66
+
67
+ throw new Error('Failed to insert {{ENTITY_NAME}}');
171
68
  }
172
69
 
173
- async upsert(model: Partial<{{ENTITY_NAME}}>): Promise<{{ENTITY_NAME}}> {
174
- if (model.id) {
175
- const existing = await this.getById(model.id);
176
- if (existing) {
177
- return this.update(model.id, model) as Promise<{{ENTITY_NAME}}>;
178
- }
70
+ async update(id: number, entity: {{ENTITY_NAME}}): Promise<{{ENTITY_NAME}}> {
71
+ const now = new Date();
72
+ const data: Partial<{{ENTITY_NAME}}Row> & { id: number } = {
73
+ {{UPDATE_DATA_MAPPING}},
74
+ updated_at: this.toMySQLDatetime(now),
75
+ id
76
+ };
77
+
78
+ const updateFields = {{UPDATE_FIELDS_ARRAY}}.map(f => \`\\\`\${f}\\\` = :\${f}\`).join(', ');
79
+
80
+ const result = await this.db.query(
81
+ \`UPDATE \\\`\${this.tableName}\\\` SET \${updateFields}, updated_at = :updated_at WHERE id = :id\`,
82
+ data
83
+ );
84
+
85
+ if (result.success) {
86
+ return this.getById(id) as Promise<{{ENTITY_NAME}}>;
179
87
  }
180
-
181
- return this.insert(model as Omit<{{ENTITY_NAME}}, 'id'>);
88
+
89
+ throw new Error('Failed to update {{ENTITY_NAME}}');
182
90
  }
183
91
 
184
92
  async softDelete(id: number): Promise<boolean> {
185
- const query = 'UPDATE {{TABLE_NAME}} SET deleted_at = :deleted_at WHERE id = :id AND deleted_at IS NULL';
186
- const result = await this.db.query(query, { deleted_at: new Date(), id });
187
-
188
- return result.success && (result.affectedRows || 0) > 0;
189
- }
93
+ const now = new Date();
94
+ const result = await this.db.query(
95
+ \`UPDATE \\\`\${this.tableName}\\\` SET deleted_at = :deleted_at WHERE id = :id\`,
96
+ { deleted_at: this.toMySQLDatetime(now), id }
97
+ );
190
98
 
191
- async count(filters?: Partial<Pick<{{ENTITY_NAME}}Row, {{FILTERABLE_FIELDS}}>>): Promise<number> {
192
- let query = 'SELECT COUNT(*) as count FROM {{TABLE_NAME}} WHERE deleted_at IS NULL';
193
- let params: Record<string, any> = {};
194
-
195
- if (filters && Object.keys(filters).length > 0) {
196
- const whereConditions = Object.keys(filters).map(key => \`\${key} = :\${key}\`);
197
- params = { ...filters };
198
- query += \` AND \${whereConditions.join(' AND ')}\`;
199
- }
200
-
201
- const result = await this.db.query(query, params);
202
-
203
- if (!result.success || result.data.length === 0) {
204
- return 0;
205
- }
206
-
207
- return result.data[0].count;
99
+ return result.success;
208
100
  }
209
101
 
210
- {{CONVERSION_METHODS}}
211
- }`,
212
- conversionMethods: ` static rowToModel(row: {{ENTITY_NAME}}Row): {{ENTITY_NAME}} {
213
- return new {{ENTITY_NAME}}(
214
- row.id,
215
- {{ROW_TO_MODEL_MAPPING}}
102
+ async hardDelete(id: number): Promise<boolean> {
103
+ const result = await this.db.query(
104
+ \`DELETE FROM \\\`\${this.tableName}\\\` WHERE id = :id\`,
105
+ { id }
216
106
  );
217
- }
218
107
 
219
- static modelToRow(model: {{ENTITY_NAME}}): Partial<{{ENTITY_NAME}}Row> {
220
- return {
221
- id: model.id,
222
- {{MODEL_TO_ROW_MAPPING}},
223
- updated_at: new Date()
224
- };
108
+ return result.success;
225
109
  }
226
-
227
- private extractDataProperties(obj: any): Record<string, any> {
228
- const result: Record<string, any> = {};
229
-
230
- for (const [key, value] of Object.entries(obj)) {
231
- // Only include properties that are not functions and are in updatable fields
232
- if (typeof value !== 'function' && {{ENTITY_NAME}}Store.UPDATABLE_FIELDS.includes(key)) {
233
- result[key] = value;
234
- }
235
- }
236
-
237
- return result;
238
- }`
110
+ {{GET_BY_PARENT_ID_METHOD}}
111
+ {{GET_RESOURCE_OWNER_METHOD}}}`
239
112
  };
240
- exports.fileTemplates = {
241
- storeFile: `import { {{ENTITY_NAME}} } from '../../domain/entities/{{ENTITY_NAME}}';
242
- import { StoreInterface } from '../interfaces/StoreInterface';
243
- import { ProviderMysql, ISqlProvider, MySQLQueryError, MySQLConnectionError } from '@currentjs/provider-mysql';
113
+ exports.storeFileTemplate = `import { Injectable } from '../../../../system';
114
+ import { {{ENTITY_IMPORT_ITEMS}} } from '../../domain/entities/{{ENTITY_NAME}}';
115
+ import type { ISqlProvider } from '@currentjs/provider-mysql';{{VALUE_OBJECT_IMPORTS}}{{AGGREGATE_REF_IMPORTS}}
244
116
 
245
117
  {{ROW_INTERFACE}}
246
118
 
247
- {{STORE_CLASS}}`,
248
- storeInterface: `export interface StoreInterface<TModel, TRow> {
249
- getById(id: number): Promise<TModel | null>;
250
- getAll(page?: number, limit?: number): Promise<TModel[]>;
251
- getAllByUserId(userId: number, page?: number, limit?: number): Promise<TModel[]>;
252
- getBy(filters: Partial<TRow>): Promise<TModel | null>;
253
- getAllBy(filters: Partial<TRow>): Promise<TModel[]>;
254
- insert(model: Omit<TModel, 'id'>): Promise<TModel>;
255
- update(id: number, updates: Partial<Omit<TModel, 'id' | 'createdAt'>>): Promise<TModel | null>;
256
- upsert(model: Partial<TModel>): Promise<TModel>;
257
- softDelete(id: number): Promise<boolean>;
258
- count(filters?: Partial<TRow>): Promise<number>;
259
- }`
260
- };
119
+ {{STORE_CLASS}}
120
+ `;
@@ -0,0 +1,13 @@
1
+ import { ModuleConfig } from '../types/configTypes';
2
+ export declare class UseCaseGenerator {
3
+ private availableAggregates;
4
+ private generateUseCaseMethod;
5
+ private generateGetResourceOwnerMethod;
6
+ private generateUseCase;
7
+ generateFromConfig(config: ModuleConfig): Record<string, string>;
8
+ generateFromYamlFile(yamlFilePath: string): Record<string, string>;
9
+ generateAndSaveFiles(yamlFilePath: string, moduleDir: string, opts?: {
10
+ force?: boolean;
11
+ skipOnConflict?: boolean;
12
+ }): Promise<void>;
13
+ }