forge-sql-orm 1.0.13 → 1.0.16

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/scripts/cli.ts ADDED
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from "commander";
4
+ import dotenv from "dotenv";
5
+ import inquirer from "inquirer";
6
+ import { generateModels } from "./actions/generate-models";
7
+ import { createMigration } from "./actions/migrations-create";
8
+ import { updateMigration } from "./actions/migrations-update";
9
+ import {runPostInstallPatch} from "./actions/PatchPostinstall";
10
+
11
+ // 🔄 Load environment variables from `.env` file
12
+ dotenv.config();
13
+
14
+ /**
15
+ * Prompts the user for missing parameters using Inquirer.js.
16
+ * @param config - The current configuration object.
17
+ * @param defaultOutput - Default output path.
18
+ * @param customAskMissingParams - Optional function for additional prompts.
19
+ * @returns Updated configuration with user input.
20
+ */
21
+ const askMissingParams = async (
22
+ config: any,
23
+ defaultOutput: string,
24
+ customAskMissingParams?: (cfg: any, questions: unknown[]) => void,
25
+ ) => {
26
+ const questions: unknown[] = [];
27
+
28
+ if (!config.host)
29
+ questions.push({
30
+ type: "input",
31
+ name: "host",
32
+ message: "Enter database host:",
33
+ default: "localhost",
34
+ });
35
+
36
+ if (!config.port)
37
+ questions.push({
38
+ type: "input",
39
+ name: "port",
40
+ message: "Enter database port:",
41
+ default: "3306",
42
+ validate: (input: string) => !isNaN(parseInt(input, 10)),
43
+ });
44
+
45
+ if (!config.user)
46
+ questions.push({
47
+ type: "input",
48
+ name: "user",
49
+ message: "Enter database user:",
50
+ default: "root",
51
+ });
52
+
53
+ if (!config.password)
54
+ questions.push({
55
+ type: "password",
56
+ name: "password",
57
+ message: "Enter database password:",
58
+ mask: "*",
59
+ });
60
+
61
+ if (!config.dbName)
62
+ questions.push({
63
+ type: "input",
64
+ name: "dbName",
65
+ message: "Enter database name:",
66
+ });
67
+
68
+ if (!config.output)
69
+ questions.push({
70
+ type: "input",
71
+ name: "output",
72
+ message: "Enter output path:",
73
+ default: defaultOutput,
74
+ });
75
+
76
+ // Allow additional questions from the caller
77
+ if (customAskMissingParams) {
78
+ customAskMissingParams(config, questions);
79
+ }
80
+
81
+ // If there are missing parameters, prompt the user
82
+ if (questions.length > 0) {
83
+ // @ts-ignore - Ignore TypeScript warning for dynamic question type
84
+ const answers = await inquirer.prompt(questions);
85
+ return { ...config, ...answers, port: parseInt(answers.port, 10) };
86
+ }
87
+
88
+ return config;
89
+ };
90
+
91
+ /**
92
+ * Retrieves configuration parameters from command-line arguments and environment variables.
93
+ * If any required parameters are missing, prompts the user for input.
94
+ * @param cmd - The command object containing CLI options.
95
+ * @param defaultOutput - Default output directory.
96
+ * @param customConfig - Optional function for additional configuration parameters.
97
+ * @param customAskMissingParams - Optional function for additional prompts.
98
+ * @returns A fully resolved configuration object.
99
+ */
100
+ const getConfig = async (
101
+ cmd: any,
102
+ defaultOutput: string,
103
+ customConfig?: () => any,
104
+ customAskMissingParams?: (cfg: any, questions: unknown[]) => void,
105
+ ) => {
106
+ let config = {
107
+ host: cmd.host || process.env.FORGE_SQL_ORM_HOST,
108
+ port: cmd.port
109
+ ? parseInt(cmd.port, 10)
110
+ : process.env.FORGE_SQL_ORM_PORT
111
+ ? parseInt(process.env.FORGE_SQL_ORM_PORT, 10)
112
+ : undefined,
113
+ user: cmd.user || process.env.FORGE_SQL_ORM_USER,
114
+ password: cmd.password || process.env.FORGE_SQL_ORM_PASSWORD,
115
+ dbName: cmd.dbName || process.env.FORGE_SQL_ORM_DBNAME,
116
+ output: cmd.output || process.env.FORGE_SQL_ORM_OUTPUT,
117
+ };
118
+
119
+ // Merge additional configurations if provided
120
+ if (customConfig) {
121
+ config = { ...config, ...customConfig() };
122
+ }
123
+
124
+ return await askMissingParams(config, defaultOutput, customAskMissingParams);
125
+ };
126
+
127
+ // 📌 Initialize CLI
128
+ const program = new Command();
129
+ program.version("1.0.0");
130
+
131
+ // ✅ Command: Generate database models (Entities)
132
+ program
133
+ .command("generate:model")
134
+ .description("Generate MikroORM models from the database.")
135
+ .option("--host <string>", "Database host")
136
+ .option("--port <number>", "Database port")
137
+ .option("--user <string>", "Database user")
138
+ .option("--password <string>", "Database password")
139
+ .option("--dbName <string>", "Database name")
140
+ .option("--output <string>", "Output path for entities")
141
+ .action(async (cmd) => {
142
+ const config = await getConfig(cmd, "./database/entities");
143
+ await generateModels(config);
144
+ });
145
+
146
+ // ✅ Command: Create initial database migration
147
+ program
148
+ .command("migrations:create")
149
+ .description("Generate an initial migration for the entire database.")
150
+ .option("--host <string>", "Database host")
151
+ .option("--port <number>", "Database port")
152
+ .option("--user <string>", "Database user")
153
+ .option("--password <string>", "Database password")
154
+ .option("--dbName <string>", "Database name")
155
+ .option("--output <string>", "Output path for migrations")
156
+ .option("--entitiesPath <string>", "Path to the folder containing entities")
157
+ .action(async (cmd) => {
158
+ const config = await getConfig(
159
+ cmd,
160
+ "./database/migration",
161
+ () => ({
162
+ entitiesPath: cmd.entitiesPath || process.env.FORGE_SQL_ORM_ENTITIES_PATH,
163
+ }),
164
+ (cfg, questions: unknown[]) => {
165
+ if (!cfg.entitiesPath)
166
+ questions.push({
167
+ type: "input",
168
+ name: "entitiesPath",
169
+ message: "Enter the path to entities:",
170
+ default: "./database/entities",
171
+ });
172
+ },
173
+ );
174
+ await createMigration(config);
175
+ });
176
+
177
+ // ✅ Command: Update migration for schema changes
178
+ program
179
+ .command("migrations:update")
180
+ .description("Generate a migration to update the database schema.")
181
+ .option("--host <string>", "Database host")
182
+ .option("--port <number>", "Database port")
183
+ .option("--user <string>", "Database user")
184
+ .option("--password <string>", "Database password")
185
+ .option("--dbName <string>", "Database name")
186
+ .option("--output <string>", "Output path for migrations")
187
+ .option("--entitiesPath <string>", "Path to the folder containing entities")
188
+ .action(async (cmd) => {
189
+ const config = await getConfig(
190
+ cmd,
191
+ "./database/migration",
192
+ () => ({
193
+ entitiesPath: cmd.entitiesPath || process.env.FORGE_SQL_ORM_ENTITIES_PATH,
194
+ }),
195
+ (cfg, questions: unknown[]) => {
196
+ if (!cfg.entitiesPath)
197
+ questions.push({
198
+ type: "input",
199
+ name: "entitiesPath",
200
+ message: "Enter the path to entities:",
201
+ default: "./database/entities",
202
+ });
203
+ },
204
+ );
205
+ await updateMigration(config);
206
+ });
207
+
208
+ // Patch MikroORM and Knex
209
+ program
210
+ .command("patch:mikroorm")
211
+ .description("Patch MikroORM and Knex dependencies to work properly with Forge")
212
+ .action(async () => {
213
+ console.log("Running MikroORM patch...");
214
+ await runPostInstallPatch();
215
+ await runPostInstallPatch();
216
+ await runPostInstallPatch();
217
+ console.log("✅ MikroORM patch applied successfully!");
218
+ });
219
+
220
+ // 🔥 Execute CLI
221
+ program.parse(process.argv);
@@ -8,10 +8,7 @@ const os = require("os");
8
8
  const args = process.argv.slice(2).join(" ");
9
9
 
10
10
  // Resolve the path to cli.ts (your TypeScript entry file)
11
- const cliPath = path.resolve(__dirname, "cli.js");
12
-
13
- // Detect platform-specific `ts-node` binary paths
14
- const localTsNode = path.resolve(__dirname, "../node_modules/.bin/ts-node") + (os.platform() === "win32" ? ".cmd" : "");
11
+ const cliPath = path.resolve(__dirname, "cli.ts");
15
12
 
16
13
  // Function to run a command
17
14
  const runCommand = (cmd) => {
@@ -19,7 +16,6 @@ const runCommand = (cmd) => {
19
16
  execSync(cmd, { stdio: "inherit", shell: true });
20
17
  process.exit(0);
21
18
  } catch (e) {
22
- console.error("⚠️ Command execution failed:", e.message);
23
19
  process.exit(1);
24
20
  }
25
21
  };
@@ -36,15 +32,9 @@ const isGlobalTsNodeInstalled = (() => {
36
32
 
37
33
  if (isGlobalTsNodeInstalled) {
38
34
  console.log("✅ Using global ts-node");
39
- runCommand(`ts-node ${cliPath} ${args}`);
40
- }
41
-
42
- // **2. If not, check for local ts-node**
43
- if (fs.existsSync(localTsNode)) {
44
- console.log("✅ Using local ts-node");
45
- runCommand(`"${localTsNode}" ${cliPath} ${args}`);
35
+ runCommand(`node -r ts-node/register ${cliPath} ${args}`);
46
36
  }
47
37
 
48
- // **3. If neither found, fallback to npx**
38
+ // **3. fallback to npx**
49
39
  console.warn("⚠️ Neither global nor local ts-node found, using npx...");
50
- runCommand(`node -r ts-node/register ${cliPath} ${args}`);
40
+ runCommand(`npx node -r ts-node/register ${cliPath} ${args}`);