@currentjs/gen 0.3.1 → 0.5.0

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 (69) hide show
  1. package/CHANGELOG.md +8 -289
  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/commands/migratePush.d.ts +1 -0
  11. package/dist/commands/migratePush.js +135 -0
  12. package/dist/commands/migrateUpdate.d.ts +1 -0
  13. package/dist/commands/migrateUpdate.js +147 -0
  14. package/dist/commands/newGenerateAll.d.ts +4 -0
  15. package/dist/commands/newGenerateAll.js +336 -0
  16. package/dist/generators/controllerGenerator.d.ts +43 -19
  17. package/dist/generators/controllerGenerator.js +547 -329
  18. package/dist/generators/domainLayerGenerator.d.ts +21 -0
  19. package/dist/generators/domainLayerGenerator.js +276 -0
  20. package/dist/generators/dtoGenerator.d.ts +21 -0
  21. package/dist/generators/dtoGenerator.js +518 -0
  22. package/dist/generators/newControllerGenerator.d.ts +55 -0
  23. package/dist/generators/newControllerGenerator.js +644 -0
  24. package/dist/generators/newServiceGenerator.d.ts +19 -0
  25. package/dist/generators/newServiceGenerator.js +266 -0
  26. package/dist/generators/newStoreGenerator.d.ts +39 -0
  27. package/dist/generators/newStoreGenerator.js +408 -0
  28. package/dist/generators/newTemplateGenerator.d.ts +29 -0
  29. package/dist/generators/newTemplateGenerator.js +510 -0
  30. package/dist/generators/serviceGenerator.d.ts +16 -51
  31. package/dist/generators/serviceGenerator.js +167 -586
  32. package/dist/generators/storeGenerator.d.ts +35 -32
  33. package/dist/generators/storeGenerator.js +291 -238
  34. package/dist/generators/storeGeneratorV2.d.ts +31 -0
  35. package/dist/generators/storeGeneratorV2.js +190 -0
  36. package/dist/generators/templateGenerator.d.ts +21 -21
  37. package/dist/generators/templateGenerator.js +393 -268
  38. package/dist/generators/templates/appTemplates.d.ts +3 -1
  39. package/dist/generators/templates/appTemplates.js +15 -10
  40. package/dist/generators/templates/data/appYamlTemplate +5 -2
  41. package/dist/generators/templates/data/cursorRulesTemplate +315 -221
  42. package/dist/generators/templates/data/frontendScriptTemplate +76 -47
  43. package/dist/generators/templates/data/mainViewTemplate +1 -1
  44. package/dist/generators/templates/data/systemTsTemplate +5 -0
  45. package/dist/generators/templates/index.d.ts +0 -3
  46. package/dist/generators/templates/index.js +0 -3
  47. package/dist/generators/templates/newStoreTemplates.d.ts +5 -0
  48. package/dist/generators/templates/newStoreTemplates.js +141 -0
  49. package/dist/generators/templates/storeTemplates.d.ts +1 -5
  50. package/dist/generators/templates/storeTemplates.js +102 -219
  51. package/dist/generators/templates/viewTemplates.js +1 -1
  52. package/dist/generators/useCaseGenerator.d.ts +13 -0
  53. package/dist/generators/useCaseGenerator.js +188 -0
  54. package/dist/types/configTypes.d.ts +148 -0
  55. package/dist/types/configTypes.js +10 -0
  56. package/dist/utils/childEntityUtils.d.ts +18 -0
  57. package/dist/utils/childEntityUtils.js +78 -0
  58. package/dist/utils/commandUtils.d.ts +43 -0
  59. package/dist/utils/commandUtils.js +124 -0
  60. package/dist/utils/commitUtils.d.ts +4 -1
  61. package/dist/utils/constants.d.ts +10 -0
  62. package/dist/utils/constants.js +13 -1
  63. package/dist/utils/diResolver.d.ts +32 -0
  64. package/dist/utils/diResolver.js +204 -0
  65. package/dist/utils/new_parts_of_migrationUtils.d.ts +0 -0
  66. package/dist/utils/new_parts_of_migrationUtils.js +164 -0
  67. package/dist/utils/typeUtils.d.ts +19 -0
  68. package/dist/utils/typeUtils.js +70 -0
  69. package/package.json +7 -3
@@ -0,0 +1,135 @@
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
+ }
@@ -0,0 +1 @@
1
+ export declare function handleMigrateUpdate(yamlPath?: string): Promise<void>;
@@ -0,0 +1,147 @@
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.handleMigrateUpdate = handleMigrateUpdate;
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 handleMigrateUpdate(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
+ const stateFilePath = path.join(migrationsDir, 'schema_state.yaml');
49
+ // Ensure migrations directory exists
50
+ if (!fs.existsSync(migrationsDir)) {
51
+ fs.mkdirSync(migrationsDir, { recursive: true });
52
+ }
53
+ // eslint-disable-next-line no-console
54
+ console.log(colors_1.colors.cyan('\n🔌 Connecting to database...'));
55
+ // Verify environment variables
56
+ if (!process.env.DB_HOST || !process.env.DB_USER || !process.env.DB_NAME) {
57
+ // eslint-disable-next-line no-console
58
+ console.log(colors_1.colors.yellow('\n💡 Database configuration:'));
59
+ // eslint-disable-next-line no-console
60
+ console.log(colors_1.colors.gray(` Host: ${process.env.DB_HOST || 'localhost (default)'}`));
61
+ // eslint-disable-next-line no-console
62
+ console.log(colors_1.colors.gray(` Port: ${process.env.DB_PORT || '3306 (default)'}`));
63
+ // eslint-disable-next-line no-console
64
+ console.log(colors_1.colors.gray(` User: ${process.env.DB_USER || 'root (default)'}`));
65
+ // eslint-disable-next-line no-console
66
+ console.log(colors_1.colors.gray(` Database: ${process.env.DB_NAME || 'test (default)'}`));
67
+ if (!process.env.DB_HOST || !process.env.DB_USER || !process.env.DB_NAME) {
68
+ // eslint-disable-next-line no-console
69
+ console.log(colors_1.colors.yellow('\n⚠️ Environment variables not set. Using defaults.'));
70
+ // eslint-disable-next-line no-console
71
+ console.log(colors_1.colors.cyan(' Set DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME to configure.'));
72
+ }
73
+ }
74
+ connection = await (0, migrationUtils_1.connectToDatabase)();
75
+ // eslint-disable-next-line no-console
76
+ console.log(colors_1.colors.green('✓ Connected to database'));
77
+ // Extract schema from database
78
+ // eslint-disable-next-line no-console
79
+ console.log(colors_1.colors.cyan('\n🔍 Extracting schema from database...'));
80
+ const dbModels = await (0, migrationUtils_1.extractSchemaFromDatabase)(connection);
81
+ if (dbModels.length === 0) {
82
+ // eslint-disable-next-line no-console
83
+ console.log(colors_1.colors.yellow('⚠️ No tables found in database.'));
84
+ return;
85
+ }
86
+ // eslint-disable-next-line no-console
87
+ console.log(colors_1.colors.green(`✓ Found ${dbModels.length} table(s): ${dbModels.map(m => m.name).join(', ')}`));
88
+ // Load current state
89
+ const currentState = (0, migrationUtils_1.loadSchemaState)(stateFilePath);
90
+ if (currentState) {
91
+ // eslint-disable-next-line no-console
92
+ console.log(colors_1.colors.cyan(`📖 Current schema state loaded (version: ${currentState.version})`));
93
+ }
94
+ else {
95
+ // eslint-disable-next-line no-console
96
+ console.log(colors_1.colors.cyan('📖 No current schema state found'));
97
+ }
98
+ // Compare database schema with current state
99
+ // eslint-disable-next-line no-console
100
+ console.log(colors_1.colors.cyan('\n🔍 Comparing database schema with current state...'));
101
+ const sqlStatements = (0, migrationUtils_1.compareSchemas)(currentState, dbModels);
102
+ if (sqlStatements.length === 0 || sqlStatements.every(s => s.trim() === '' || s.startsWith('--'))) {
103
+ // eslint-disable-next-line no-console
104
+ console.log(colors_1.colors.green('✅ Database schema matches current state. No changes to record.'));
105
+ return;
106
+ }
107
+ // Generate migration file
108
+ const timestamp = (0, migrationUtils_1.generateTimestamp)();
109
+ const migrationFileName = (0, migrationUtils_1.getMigrationFileName)(timestamp);
110
+ const migrationFilePath = path.join(migrationsDir, migrationFileName);
111
+ const migrationHeader = `-- Migration: Database schema sync
112
+ -- Created: ${new Date().toISOString().split('T')[0]}
113
+ -- Timestamp: ${timestamp}
114
+ -- Source: Database schema extraction
115
+
116
+ `;
117
+ const migrationContent = migrationHeader + sqlStatements.join('\n');
118
+ fs.writeFileSync(migrationFilePath, migrationContent);
119
+ // Update state file
120
+ const newState = {
121
+ models: dbModels,
122
+ version: timestamp,
123
+ timestamp: new Date().toISOString()
124
+ };
125
+ (0, migrationUtils_1.saveSchemaState)(stateFilePath, newState);
126
+ // eslint-disable-next-line no-console
127
+ console.log(colors_1.colors.green('\n✅ Migration created from database schema!'));
128
+ // eslint-disable-next-line no-console
129
+ console.log(colors_1.colors.gray(` File: ${migrationFileName}`));
130
+ // eslint-disable-next-line no-console
131
+ console.log(colors_1.colors.gray(` Path: ${migrationFilePath}`));
132
+ // eslint-disable-next-line no-console
133
+ console.log(colors_1.colors.cyan('\n💡 Schema state updated to match database.'));
134
+ // eslint-disable-next-line no-console
135
+ console.log(colors_1.colors.cyan(' You can now modify your YAML files and run "currentjs migrate commit" to create new migrations.'));
136
+ }
137
+ catch (error) {
138
+ // eslint-disable-next-line no-console
139
+ console.error(colors_1.colors.red('\n❌ Error updating migration from database:'), error instanceof Error ? error.message : String(error));
140
+ process.exitCode = 1;
141
+ }
142
+ finally {
143
+ if (connection) {
144
+ await connection.end();
145
+ }
146
+ }
147
+ }
@@ -0,0 +1,4 @@
1
+ export declare function handleNewGenerateAll(yamlPathArg?: string, _outArg?: string, moduleName?: string, opts?: {
2
+ force?: boolean;
3
+ skip?: boolean;
4
+ }): Promise<void>;
@@ -0,0 +1,336 @@
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.handleNewGenerateAll = handleNewGenerateAll;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const cliUtils_1 = require("../utils/cliUtils");
40
+ const yaml_1 = require("yaml");
41
+ const domainLayerGenerator_1 = require("../generators/domainLayerGenerator");
42
+ const dtoGenerator_1 = require("../generators/dtoGenerator");
43
+ const useCaseGenerator_1 = require("../generators/useCaseGenerator");
44
+ const newServiceGenerator_1 = require("../generators/newServiceGenerator");
45
+ const newControllerGenerator_1 = require("../generators/newControllerGenerator");
46
+ const newTemplateGenerator_1 = require("../generators/newTemplateGenerator");
47
+ const newStoreGenerator_1 = require("../generators/newStoreGenerator");
48
+ const generationRegistry_1 = require("../utils/generationRegistry");
49
+ const colors_1 = require("../utils/colors");
50
+ const constants_1 = require("../utils/constants");
51
+ const configTypes_1 = require("../types/configTypes");
52
+ const childEntityUtils_1 = require("../utils/childEntityUtils");
53
+ async function handleNewGenerateAll(yamlPathArg, _outArg, moduleName, opts) {
54
+ var _a, _b;
55
+ const appYamlPath = (0, cliUtils_1.resolveYamlPath)(yamlPathArg);
56
+ (0, generationRegistry_1.initGenerationRegistry)(process.cwd());
57
+ const raw = fs.readFileSync(appYamlPath, 'utf8');
58
+ const appConfig = (0, yaml_1.parse)(raw);
59
+ const modulesList = ((_a = appConfig === null || appConfig === void 0 ? void 0 : appConfig.modules) !== null && _a !== void 0 ? _a : []).map(m => (typeof m === 'string' ? m : m.module));
60
+ const providersConfig = appConfig === null || appConfig === void 0 ? void 0 : appConfig.providers;
61
+ const databaseProviderName = appConfig === null || appConfig === void 0 ? void 0 : appConfig.database;
62
+ const shouldIncludeModule = (moduleYamlRel) => {
63
+ if (!moduleName || moduleName === '*')
64
+ return true;
65
+ const moduleNameLc = moduleName.toLowerCase();
66
+ const relNormalized = moduleYamlRel.replace(/\\/g, '/').toLowerCase();
67
+ if (relNormalized.endsWith(`/${moduleNameLc}.yaml`))
68
+ return true;
69
+ const moduleYamlPath = path.isAbsolute(moduleYamlRel)
70
+ ? moduleYamlRel
71
+ : path.resolve(process.cwd(), moduleYamlRel);
72
+ const dirName = path.basename(path.dirname(moduleYamlPath)).toLowerCase();
73
+ if (dirName === moduleNameLc)
74
+ return true;
75
+ if (relNormalized.includes(`/${moduleNameLc}/`) || relNormalized.endsWith(`/${moduleNameLc}`))
76
+ return true;
77
+ return false;
78
+ };
79
+ const filteredModules = modulesList.filter(shouldIncludeModule);
80
+ if (filteredModules.length === 0) {
81
+ // eslint-disable-next-line no-console
82
+ console.warn(colors_1.colors.yellow(`No modules matched: ${moduleName}`));
83
+ return;
84
+ }
85
+ // Initialize generators
86
+ const domainGen = new domainLayerGenerator_1.DomainLayerGenerator();
87
+ const dtoGen = new dtoGenerator_1.DtoGenerator();
88
+ const useCaseGen = new useCaseGenerator_1.UseCaseGenerator();
89
+ const serviceGen = new newServiceGenerator_1.NewServiceGenerator();
90
+ const controllerGen = new newControllerGenerator_1.NewControllerGenerator();
91
+ const templateGen = new newTemplateGenerator_1.NewTemplateGenerator();
92
+ const storeGen = new newStoreGenerator_1.NewStoreGenerator();
93
+ const initsBySrcDir = new Map();
94
+ // Process each module
95
+ for (const moduleYamlRel of filteredModules) {
96
+ const moduleYamlPath = path.isAbsolute(moduleYamlRel)
97
+ ? moduleYamlRel
98
+ : path.resolve(process.cwd(), moduleYamlRel);
99
+ if (!fs.existsSync(moduleYamlPath)) {
100
+ // eslint-disable-next-line no-console
101
+ console.warn(colors_1.colors.yellow(`Module YAML not found: ${moduleYamlPath}`));
102
+ continue;
103
+ }
104
+ // Check if this is a new format config
105
+ const moduleYamlContent = fs.readFileSync(moduleYamlPath, 'utf8');
106
+ const moduleConfig = (0, yaml_1.parse)(moduleYamlContent);
107
+ if (!(0, configTypes_1.isNewModuleConfig)(moduleConfig)) {
108
+ // eslint-disable-next-line no-console
109
+ console.warn(colors_1.colors.yellow(`Skipping ${moduleYamlPath}: not in new format (missing domain/useCases)`));
110
+ continue;
111
+ }
112
+ const moduleDir = path.dirname(moduleYamlPath);
113
+ // eslint-disable-next-line no-console
114
+ console.log(colors_1.colors.blue(`\nGenerating module: ${path.basename(moduleDir)}`));
115
+ // 1. Generate domain layer (entities + value objects)
116
+ // eslint-disable-next-line no-await-in-loop
117
+ await domainGen.generateAndSaveFiles(moduleYamlPath, moduleDir, opts);
118
+ // 2. Generate DTOs
119
+ // eslint-disable-next-line no-await-in-loop
120
+ await dtoGen.generateAndSaveFiles(moduleYamlPath, moduleDir, opts);
121
+ // 3. Generate Use Cases
122
+ // eslint-disable-next-line no-await-in-loop
123
+ await useCaseGen.generateAndSaveFiles(moduleYamlPath, moduleDir, opts);
124
+ // 4. Generate Services
125
+ // eslint-disable-next-line no-await-in-loop
126
+ await serviceGen.generateAndSaveFiles(moduleYamlPath, moduleDir, opts);
127
+ // 5. Generate Stores
128
+ // eslint-disable-next-line no-await-in-loop
129
+ await storeGen.generateAndSaveFiles(moduleYamlPath, moduleDir, opts);
130
+ // 6. Generate Controllers
131
+ // eslint-disable-next-line no-await-in-loop
132
+ const controllerPaths = await controllerGen.generateAndSaveFiles(moduleYamlPath, moduleDir, opts);
133
+ // 7. Generate Templates
134
+ // eslint-disable-next-line no-await-in-loop
135
+ await templateGen.generateAndSaveFiles(moduleYamlPath, moduleDir, opts);
136
+ // Collect wiring information for app.ts
137
+ let probeDir = moduleDir;
138
+ let srcDir = null;
139
+ for (let i = 0; i < 6; i += 1) {
140
+ const candidate = path.join(probeDir, 'src', constants_1.COMMON_FILES.APP_TS);
141
+ if (fs.existsSync(candidate)) {
142
+ srcDir = path.join(probeDir, 'src');
143
+ break;
144
+ }
145
+ const parent = path.dirname(probeDir);
146
+ if (parent === probeDir)
147
+ break;
148
+ probeDir = parent;
149
+ }
150
+ if (!srcDir)
151
+ continue;
152
+ // Build wiring for each model in the module
153
+ const list = (_b = initsBySrcDir.get(srcDir)) !== null && _b !== void 0 ? _b : [];
154
+ Object.keys(moduleConfig.useCases).forEach(modelName => {
155
+ const entityVar = modelName.charAt(0).toLowerCase() + modelName.slice(1);
156
+ const moduleFolderName = path.basename(moduleDir);
157
+ const init = {
158
+ entityName: modelName,
159
+ entityVar,
160
+ importStore: `import { ${modelName}Store } from './modules/${moduleFolderName}/infrastructure/stores/${modelName}Store';`,
161
+ importService: `import { ${modelName}Service } from './modules/${moduleFolderName}/application/services/${modelName}Service';`,
162
+ importUseCase: `import { ${modelName}UseCase } from './modules/${moduleFolderName}/application/useCases/${modelName}UseCase';`,
163
+ importController: '',
164
+ wiring: [],
165
+ registration: ''
166
+ };
167
+ // Check if this root entity's web controller needs child services (withChild: true)
168
+ const childEntityMap = (0, childEntityUtils_1.buildChildEntityMap)(moduleConfig);
169
+ const isRootEntity = !childEntityMap.has(modelName);
170
+ const withChildChildren = isRootEntity ? (0, childEntityUtils_1.getChildrenOfParent)(moduleConfig, modelName) : [];
171
+ const webUseCases = moduleConfig.useCases[modelName];
172
+ const needsChildServices = withChildChildren.length > 0 && webUseCases && Object.entries(webUseCases).some(([action, uc]) => action === 'get' && uc.withChild === true);
173
+ // Add controller imports if they exist
174
+ controllerPaths.forEach(ctrlPath => {
175
+ const ctrlName = path.basename(ctrlPath, '.ts');
176
+ const ctrlModelName = ctrlName.replace(/(Api|Web)Controller$/, '');
177
+ if (ctrlModelName === modelName) {
178
+ const rel = path.relative(srcDir, ctrlPath).replace(/\\/g, '/').replace(/\.ts$/, '');
179
+ const importPath = rel.startsWith('.') ? rel : `./${rel}`;
180
+ init.importController += `import { ${ctrlName} } from '${importPath}';\n`;
181
+ // Web controllers may need child services when withChild is true
182
+ const isWebCtrl = ctrlName.endsWith('WebController');
183
+ if (isWebCtrl && needsChildServices) {
184
+ const childServiceArgs = withChildChildren
185
+ .map(c => c.childEntityName.charAt(0).toLowerCase() + c.childEntityName.slice(1) + 'Service')
186
+ .join(', ');
187
+ init.registration += `new ${ctrlName}(${entityVar}UseCase, ${childServiceArgs}),\n `;
188
+ }
189
+ else {
190
+ init.registration += `new ${ctrlName}(${entityVar}UseCase),\n `;
191
+ }
192
+ }
193
+ });
194
+ list.push(init);
195
+ });
196
+ initsBySrcDir.set(srcDir, list);
197
+ }
198
+ // Update app.ts files with wiring
199
+ for (const [srcDir, controllerInits] of initsBySrcDir.entries()) {
200
+ try {
201
+ const appTsPath = path.join(srcDir, constants_1.COMMON_FILES.APP_TS);
202
+ if (!fs.existsSync(appTsPath))
203
+ continue;
204
+ let appTs = fs.readFileSync(appTsPath, 'utf8');
205
+ // Build providers import and initialization from app.yaml providers section
206
+ const importLines = [];
207
+ const providerInitLines = [];
208
+ const providersArrayEntries = [];
209
+ let isIProviderImported = false;
210
+ if (providersConfig && Object.keys(providersConfig).length > 0) {
211
+ for (const [provName, mod] of Object.entries(providersConfig)) {
212
+ if (!mod)
213
+ continue;
214
+ // Assume default import name from module spec after last '/'
215
+ const baseName = mod.split('/').pop() || 'provider';
216
+ const className = baseName
217
+ .replace(/^[^a-zA-Z_]*/g, '')
218
+ .split(/[-_]/)
219
+ .map(s => s.charAt(0).toUpperCase() + s.slice(1))
220
+ .join('');
221
+ // Only add import if the module path isn't already imported
222
+ if (!appTs.includes(`from '${mod}'`)) {
223
+ importLines.push(`import { ${className}${!isIProviderImported ? ', IProvider, ISqlProvider' : ''} } from '${mod}';`);
224
+ }
225
+ if (!isIProviderImported)
226
+ isIProviderImported = true;
227
+ // Read provider configuration from env by name, parse JSON if possible, pass as is
228
+ providerInitLines.push(` ${provName}: new ${className}((() => {
229
+ const raw = process.env.${provName.toUpperCase()} || '';
230
+ try { return raw ? JSON.parse(raw) : undefined; } catch { return raw; }
231
+ })())`);
232
+ providersArrayEntries.push(provName);
233
+ }
234
+ }
235
+ else {
236
+ // Fallback to MySQL provider if no providers configured
237
+ if (!appTs.includes("from '@currentjs/provider-mysql'")) {
238
+ importLines.push(`import { ProviderMysql, IProvider, ISqlProvider } from '@currentjs/provider-mysql';`);
239
+ }
240
+ providerInitLines.push(` mysql: new ProviderMysql((() => {
241
+ const raw = process.env.MYSQL || '';
242
+ try { return raw ? JSON.parse(raw) : undefined; } catch { return raw; }
243
+ })())`);
244
+ providersArrayEntries.push('mysql');
245
+ }
246
+ const dbProviderKey = databaseProviderName || providersArrayEntries[0];
247
+ const ensureDbLine = `const providers: Record<string, IProvider> = {\n${providerInitLines.join(',\n')}\n};\nconst db = providers['${dbProviderKey}'] as ISqlProvider;`;
248
+ // Ensure router imports
249
+ if (!appTs.includes("from '@currentjs/router'")) {
250
+ importLines.push(`import { createWebServer } from '@currentjs/router';`);
251
+ }
252
+ // Add entity imports
253
+ for (const init of controllerInits) {
254
+ const lines = [
255
+ init.importStore,
256
+ init.importService,
257
+ init.importUseCase,
258
+ init.importController
259
+ ].filter(line => line && line.trim() !== '');
260
+ for (const line of lines) {
261
+ if (!appTs.includes(line) && !importLines.includes(line)) {
262
+ importLines.push(line);
263
+ }
264
+ }
265
+ }
266
+ if (importLines.length) {
267
+ // Filter out duplicates before prepending
268
+ const existingImports = new Set();
269
+ const importRegex = /^import[^;]+;$/gm;
270
+ const currentImports = appTs.match(importRegex) || [];
271
+ currentImports.forEach(line => existingImports.add(line.trim()));
272
+ const toAdd = importLines.filter(line => !existingImports.has(line.trim()));
273
+ if (toAdd.length)
274
+ appTs = toAdd.join('\n') + '\n' + appTs;
275
+ }
276
+ // Build wiring block
277
+ const wiringLines = [];
278
+ // Providers + DB initialization
279
+ wiringLines.push(ensureDbLine);
280
+ // Store -> Service -> UseCase wiring
281
+ for (const init of controllerInits) {
282
+ const { entityName, entityVar } = init;
283
+ wiringLines.push(`const ${entityVar}Store = new ${entityName}Store(db);`);
284
+ wiringLines.push(`const ${entityVar}Service = new ${entityName}Service(${entityVar}Store);`);
285
+ wiringLines.push(`const ${entityVar}UseCase = new ${entityName}UseCase(${entityVar}Service);`);
286
+ }
287
+ // Controller registrations
288
+ const registrations = controllerInits
289
+ .map(i => i.registration)
290
+ .filter(r => r && r.trim() !== '')
291
+ .join('');
292
+ wiringLines.push('const controllers = [');
293
+ if (registrations) {
294
+ wiringLines.push(` ${registrations.trim()}`);
295
+ }
296
+ wiringLines.push('];');
297
+ // Replace content between markers
298
+ const startMarker = constants_1.GENERATOR_MARKERS.CONTROLLERS_START;
299
+ const endMarker = constants_1.GENERATOR_MARKERS.CONTROLLERS_END;
300
+ const startIdx = appTs.indexOf(startMarker);
301
+ const endIdx = appTs.indexOf(endMarker);
302
+ if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
303
+ const before = appTs.slice(0, startIdx + startMarker.length);
304
+ const after = appTs.slice(endIdx);
305
+ const block = '\n' + wiringLines.join('\n') + '\n';
306
+ appTs = before + block + after;
307
+ }
308
+ // Deduplicate import lines across the entire file
309
+ const lines = appTs.split('\n');
310
+ const seenImports = new Set();
311
+ const deduped = lines.filter(line => {
312
+ const trimmed = line.trim();
313
+ if (/^import\s+/.test(trimmed) && trimmed.endsWith(';')) {
314
+ if (seenImports.has(trimmed))
315
+ return false;
316
+ seenImports.add(trimmed);
317
+ }
318
+ return true;
319
+ });
320
+ appTs = deduped.join('\n');
321
+ fs.writeFileSync(appTsPath, appTs, 'utf8');
322
+ // eslint-disable-next-line no-console
323
+ console.log(colors_1.colors.green(`Updated ${appTsPath}`));
324
+ }
325
+ catch (e) {
326
+ // eslint-disable-next-line no-console
327
+ console.warn(colors_1.colors.yellow(`Could not update app.ts: ${e instanceof Error ? e.message : String(e)}`));
328
+ }
329
+ }
330
+ // Run build
331
+ (0, cliUtils_1.runCommand)('npm run build', {
332
+ infoMessage: '\nBuilding...',
333
+ successMessage: '[v] Build completed successfully',
334
+ errorMessage: '[x] Build failed:'
335
+ });
336
+ }