forge-sql-orm 1.0.18 → 1.0.19
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/dist/ForgeSQLORM.js +28 -17
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/{ForgeSQLORM.cjs → ForgeSQLORM.mjs} +18 -29
- package/dist/{ForgeSQLORM.cjs.map → ForgeSQLORM.mjs.map} +1 -1
- package/dist-cli/.env +7 -0
- package/dist-cli/cli.js +571 -0
- package/dist-cli/cli.js.map +1 -0
- package/dist-cli/cli.mjs +570 -0
- package/dist-cli/cli.mjs.map +1 -0
- package/dist-cli/forgeSqlCLI.js +47 -0
- package/dist-cli/src/entities/Users.ts +14 -0
- package/dist-cli/src/entities/index.ts +3 -0
- package/package.json +2 -3
- package/scripts/forgeSqlCLI.js +17 -10
- package/scripts/actions/PatchPostinstall.ts +0 -201
- package/scripts/actions/generate-models.ts +0 -65
- package/scripts/actions/migrations-create.ts +0 -193
- package/scripts/actions/migrations-update.ts +0 -200
- package/scripts/cli.ts +0 -221
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import "reflect-metadata";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import {MikroORM} from "@mikro-orm/mysql";
|
|
5
|
-
import { execSync } from 'child_process';
|
|
6
|
-
import { rmSync } from 'fs';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Cleans SQL statements by removing unnecessary database options.
|
|
10
|
-
* @param sql - The raw SQL statement.
|
|
11
|
-
* @returns The cleaned SQL statement.
|
|
12
|
-
*/
|
|
13
|
-
function cleanSQLStatement(sql: string): string {
|
|
14
|
-
return sql.replace(/\s+default\s+character\s+set\s+utf8mb4\s+engine\s*=\s*InnoDB;?/gi, "").trim();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Generates a migration file using the provided SQL statements.
|
|
19
|
-
* @param createStatements - Array of SQL statements.
|
|
20
|
-
* @param version - Migration version number.
|
|
21
|
-
* @returns TypeScript migration file content.
|
|
22
|
-
*/
|
|
23
|
-
function generateMigrationFile(createStatements: string[], version: number): string {
|
|
24
|
-
const versionPrefix = `v${version}_MIGRATION`;
|
|
25
|
-
|
|
26
|
-
// Clean each SQL statement and generate migration lines with .enqueue()
|
|
27
|
-
const migrationLines = createStatements
|
|
28
|
-
.map(
|
|
29
|
-
(stmt, index) =>
|
|
30
|
-
` .enqueue("${versionPrefix}${index}", \"${cleanSQLStatement(stmt)}\")`, // eslint-disable-line no-useless-escape
|
|
31
|
-
)
|
|
32
|
-
.join("\n");
|
|
33
|
-
|
|
34
|
-
// Migration template
|
|
35
|
-
return `import { MigrationRunner } from "@forge/sql/out/migration";
|
|
36
|
-
|
|
37
|
-
export default (migrationRunner: MigrationRunner): MigrationRunner => {
|
|
38
|
-
return migrationRunner
|
|
39
|
-
${migrationLines};
|
|
40
|
-
};`;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Saves the generated migration file along with `migrationCount.ts` and `index.ts`.
|
|
45
|
-
* @param migrationCode - The migration code to be written to the file.
|
|
46
|
-
* @param version - Migration version number.
|
|
47
|
-
* @param outputDir - Directory where the migration files will be saved.
|
|
48
|
-
*/
|
|
49
|
-
function saveMigrationFiles(migrationCode: string, version: number, outputDir: string) {
|
|
50
|
-
if (!fs.existsSync(outputDir)) {
|
|
51
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const migrationFilePath = path.join(outputDir, `migrationV${version}.ts`);
|
|
55
|
-
const migrationCountPath = path.join(outputDir, `migrationCount.ts`);
|
|
56
|
-
const indexFilePath = path.join(outputDir, `index.ts`);
|
|
57
|
-
|
|
58
|
-
// Write the migration file
|
|
59
|
-
fs.writeFileSync(migrationFilePath, migrationCode);
|
|
60
|
-
|
|
61
|
-
// Write the migration count file
|
|
62
|
-
fs.writeFileSync(migrationCountPath, `export const MIGRATION_VERSION = ${version};`);
|
|
63
|
-
|
|
64
|
-
// Generate the migration index file
|
|
65
|
-
const indexFileContent = `import { MigrationRunner } from "@forge/sql/out/migration";
|
|
66
|
-
import { MIGRATION_VERSION } from "./migrationCount";
|
|
67
|
-
|
|
68
|
-
export type MigrationType = (
|
|
69
|
-
migrationRunner: MigrationRunner,
|
|
70
|
-
) => MigrationRunner;
|
|
71
|
-
|
|
72
|
-
export default async (
|
|
73
|
-
migrationRunner: MigrationRunner,
|
|
74
|
-
): Promise<MigrationRunner> => {
|
|
75
|
-
for (let i = 1; i <= MIGRATION_VERSION; i++) {
|
|
76
|
-
const migrations = (await import(\`./migrationV\${i}\`)) as {
|
|
77
|
-
default: MigrationType;
|
|
78
|
-
};
|
|
79
|
-
migrations.default(migrationRunner);
|
|
80
|
-
}
|
|
81
|
-
return migrationRunner;
|
|
82
|
-
};`;
|
|
83
|
-
|
|
84
|
-
fs.writeFileSync(indexFilePath, indexFileContent);
|
|
85
|
-
|
|
86
|
-
console.log(`✅ Migration file created: ${migrationFilePath}`);
|
|
87
|
-
console.log(`✅ Migration count file updated: ${migrationCountPath}`);
|
|
88
|
-
console.log(`✅ Migration index file created: ${indexFilePath}`);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Extracts only the relevant SQL statements for migration.
|
|
93
|
-
* @param schema - The full database schema as SQL.
|
|
94
|
-
* @returns Filtered list of SQL statements.
|
|
95
|
-
*/
|
|
96
|
-
const extractCreateStatements = (schema: string): string[] => {
|
|
97
|
-
const statements = schema.split(";").map((s) => s.trim());
|
|
98
|
-
|
|
99
|
-
return statements.filter(
|
|
100
|
-
(stmt) =>
|
|
101
|
-
stmt.startsWith("create table") ||
|
|
102
|
-
(stmt.startsWith("alter table") && stmt.includes("add index")) ||
|
|
103
|
-
stmt.startsWith("primary"),
|
|
104
|
-
);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Dynamically loads `entities` from `index.ts` in the specified directory.
|
|
109
|
-
* @param entitiesPath - Path to the directory containing `index.ts`.
|
|
110
|
-
* @returns Array of entity classes.
|
|
111
|
-
*/
|
|
112
|
-
const loadEntities = async (entitiesPath: string) => {
|
|
113
|
-
try {
|
|
114
|
-
const indexFilePath = path.resolve(path.join(entitiesPath, "index.ts"));
|
|
115
|
-
if (!fs.existsSync(indexFilePath)) {
|
|
116
|
-
console.error(`❌ Error: index.ts not found in ${indexFilePath}`);
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const { default: entities } = await import(indexFilePath);
|
|
121
|
-
console.log(`✅ Loaded ${entities.length} entities from ${entitiesPath}`);
|
|
122
|
-
return entities;
|
|
123
|
-
} catch (error) {
|
|
124
|
-
console.error(`❌ Error loading index.ts from ${entitiesPath}:`, error);
|
|
125
|
-
process.exit(1);
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Loads the current migration version from `migrationCount.ts`.
|
|
131
|
-
* @param migrationPath - Path to the migration folder.
|
|
132
|
-
* @returns The latest migration version.
|
|
133
|
-
*/
|
|
134
|
-
const loadMigrationVersion = async (migrationPath: string): Promise<number> => {
|
|
135
|
-
try {
|
|
136
|
-
const migrationCountFilePath = path.resolve(path.join(migrationPath, "migrationCount.ts"));
|
|
137
|
-
if (!fs.existsSync(migrationCountFilePath)) {
|
|
138
|
-
return 0;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const { MIGRATION_VERSION } = await import(migrationCountFilePath);
|
|
142
|
-
console.log(`✅ Current migration version: ${MIGRATION_VERSION}`);
|
|
143
|
-
return MIGRATION_VERSION as number;
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.error(`❌ Error loading migrationCount:`, error);
|
|
146
|
-
process.exit(1);
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Creates a full database migration.
|
|
152
|
-
* @param options - Database connection settings and output paths.
|
|
153
|
-
*/
|
|
154
|
-
export const createMigration = async (options: any) => {
|
|
155
|
-
try {
|
|
156
|
-
let version = await loadMigrationVersion(options.output);
|
|
157
|
-
|
|
158
|
-
if (version > 0) {
|
|
159
|
-
console.error(`❌ Error: Migration has already been created.`);
|
|
160
|
-
process.exit(1);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Start from version 1 if no previous migrations exist
|
|
164
|
-
version = 1;
|
|
165
|
-
|
|
166
|
-
// Load entities dynamically from index.ts
|
|
167
|
-
const entities = await loadEntities(options.entitiesPath);
|
|
168
|
-
|
|
169
|
-
// Initialize MikroORM
|
|
170
|
-
const orm = MikroORM.initSync({
|
|
171
|
-
host: options.host,
|
|
172
|
-
port: options.port,
|
|
173
|
-
user: options.user,
|
|
174
|
-
password: options.password,
|
|
175
|
-
dbName: options.dbName,
|
|
176
|
-
entities: entities,
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Generate SQL schema
|
|
180
|
-
const createSchemaSQL = await orm.schema.getCreateSchemaSQL({ wrap: true });
|
|
181
|
-
const statements = extractCreateStatements(createSchemaSQL);
|
|
182
|
-
|
|
183
|
-
// Generate and save migration files
|
|
184
|
-
const migrationFile = generateMigrationFile(statements, version);
|
|
185
|
-
saveMigrationFiles(migrationFile, version, options.output);
|
|
186
|
-
|
|
187
|
-
console.log(`✅ Migration successfully created!`);
|
|
188
|
-
process.exit(0);
|
|
189
|
-
} catch (error) {
|
|
190
|
-
console.error(`❌ Error during migration creation:`, error);
|
|
191
|
-
process.exit(1);
|
|
192
|
-
}
|
|
193
|
-
};
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import "reflect-metadata";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import {MikroORM} from "@mikro-orm/mysql";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Cleans SQL statements by removing unnecessary database options.
|
|
8
|
-
* @param sql - The raw SQL statement.
|
|
9
|
-
* @returns The cleaned SQL statement.
|
|
10
|
-
*/
|
|
11
|
-
function cleanSQLStatement(sql: string): string {
|
|
12
|
-
return sql.replace(/\s+default\s+character\s+set\s+utf8mb4\s+engine\s*=\s*InnoDB;?/gi, "").trim();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Generates a migration file using the provided SQL statements.
|
|
17
|
-
* @param createStatements - Array of SQL statements.
|
|
18
|
-
* @param version - Migration version number.
|
|
19
|
-
* @returns TypeScript migration file content.
|
|
20
|
-
*/
|
|
21
|
-
function generateMigrationFile(createStatements: string[], version: number): string {
|
|
22
|
-
const versionPrefix = `v${version}_MIGRATION`;
|
|
23
|
-
|
|
24
|
-
// Clean each SQL statement and generate migration lines with .enqueue()
|
|
25
|
-
const migrationLines = createStatements
|
|
26
|
-
.map(
|
|
27
|
-
(stmt, index) =>
|
|
28
|
-
` .enqueue("${versionPrefix}${index}", \"${cleanSQLStatement(stmt)}\")`, // eslint-disable-line no-useless-escape
|
|
29
|
-
)
|
|
30
|
-
.join("\n");
|
|
31
|
-
|
|
32
|
-
// Migration template
|
|
33
|
-
return `import { MigrationRunner } from "@forge/sql/out/migration";
|
|
34
|
-
|
|
35
|
-
export default (migrationRunner: MigrationRunner): MigrationRunner => {
|
|
36
|
-
return migrationRunner
|
|
37
|
-
${migrationLines};
|
|
38
|
-
};`;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Saves the generated migration file along with `migrationCount.ts` and `index.ts`.
|
|
43
|
-
* @param migrationCode - The migration code to be written to the file.
|
|
44
|
-
* @param version - Migration version number.
|
|
45
|
-
* @param outputDir - Directory where the migration files will be saved.
|
|
46
|
-
*/
|
|
47
|
-
function saveMigrationFiles(migrationCode: string, version: number, outputDir: string) {
|
|
48
|
-
if (!fs.existsSync(outputDir)) {
|
|
49
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const migrationFilePath = path.join(outputDir, `migrationV${version}.ts`);
|
|
53
|
-
const migrationCountPath = path.join(outputDir, `migrationCount.ts`);
|
|
54
|
-
const indexFilePath = path.join(outputDir, `index.ts`);
|
|
55
|
-
|
|
56
|
-
// Write the migration file
|
|
57
|
-
fs.writeFileSync(migrationFilePath, migrationCode);
|
|
58
|
-
|
|
59
|
-
// Write the migration count file
|
|
60
|
-
fs.writeFileSync(migrationCountPath, `export const MIGRATION_VERSION = ${version};`);
|
|
61
|
-
|
|
62
|
-
// Generate the migration index file
|
|
63
|
-
const indexFileContent = `import { MigrationRunner } from "@forge/sql/out/migration";
|
|
64
|
-
import { MIGRATION_VERSION } from "./migrationCount";
|
|
65
|
-
|
|
66
|
-
export type MigrationType = (
|
|
67
|
-
migrationRunner: MigrationRunner,
|
|
68
|
-
) => MigrationRunner;
|
|
69
|
-
|
|
70
|
-
export default async (
|
|
71
|
-
migrationRunner: MigrationRunner,
|
|
72
|
-
): Promise<MigrationRunner> => {
|
|
73
|
-
for (let i = 1; i <= MIGRATION_VERSION; i++) {
|
|
74
|
-
const migrations = (await import(\`./migrationV\${i}\`)) as {
|
|
75
|
-
default: MigrationType;
|
|
76
|
-
};
|
|
77
|
-
migrations.default(migrationRunner);
|
|
78
|
-
}
|
|
79
|
-
return migrationRunner;
|
|
80
|
-
};`;
|
|
81
|
-
|
|
82
|
-
fs.writeFileSync(indexFilePath, indexFileContent);
|
|
83
|
-
|
|
84
|
-
console.log(`✅ Migration file created: ${migrationFilePath}`);
|
|
85
|
-
console.log(`✅ Migration count file updated: ${migrationCountPath}`);
|
|
86
|
-
console.log(`✅ Migration index file created: ${indexFilePath}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Extracts only the relevant SQL statements for migration.
|
|
91
|
-
* @param schema - The full database schema as SQL.
|
|
92
|
-
* @returns Filtered list of SQL statements.
|
|
93
|
-
*/
|
|
94
|
-
const extractCreateStatements = (schema: string): string[] => {
|
|
95
|
-
const statements = schema.split(";").map((s) => s.trim());
|
|
96
|
-
|
|
97
|
-
return statements.filter(
|
|
98
|
-
(stmt) =>
|
|
99
|
-
stmt.startsWith("create table") ||
|
|
100
|
-
(stmt.startsWith("alter table") && stmt.includes("add index")) ||
|
|
101
|
-
(stmt.startsWith("alter table") && stmt.includes("add") && !stmt.includes("foreign")) ||
|
|
102
|
-
(stmt.startsWith("alter table") && stmt.includes("modify") && !stmt.includes("foreign")),
|
|
103
|
-
);
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Dynamically loads `entities` from `index.ts` in the specified directory.
|
|
108
|
-
* @param entitiesPath - Path to the directory containing `index.ts`.
|
|
109
|
-
* @returns Array of entity classes.
|
|
110
|
-
*/
|
|
111
|
-
const loadEntities = async (entitiesPath: string) => {
|
|
112
|
-
try {
|
|
113
|
-
const indexFilePath = path.resolve(path.join(entitiesPath, "index.ts"));
|
|
114
|
-
if (!fs.existsSync(indexFilePath)) {
|
|
115
|
-
console.error(`❌ Error: index.ts not found in ${entitiesPath}`);
|
|
116
|
-
process.exit(1);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const { default: entities } = await import(indexFilePath);
|
|
120
|
-
console.log(`✅ Loaded ${entities.length} entities from ${entitiesPath}`);
|
|
121
|
-
return entities;
|
|
122
|
-
} catch (error) {
|
|
123
|
-
console.error(`❌ Error loading index.ts from ${entitiesPath}:`, error);
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Loads the current migration version from `migrationCount.ts`.
|
|
130
|
-
* @param migrationPath - Path to the migration folder.
|
|
131
|
-
* @returns The latest migration version.
|
|
132
|
-
*/
|
|
133
|
-
const loadMigrationVersion = async (migrationPath: string): Promise<number> => {
|
|
134
|
-
try {
|
|
135
|
-
const migrationCountFilePath = path.resolve(path.join(migrationPath, "migrationCount.ts"));
|
|
136
|
-
if (!fs.existsSync(migrationCountFilePath)) {
|
|
137
|
-
console.warn(
|
|
138
|
-
`⚠️ Warning: migrationCount.ts not found in ${migrationCountFilePath}, assuming no previous migrations.`,
|
|
139
|
-
);
|
|
140
|
-
return 0;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const { MIGRATION_VERSION } = await import(migrationCountFilePath);
|
|
144
|
-
console.log(`✅ Current migration version: ${MIGRATION_VERSION}`);
|
|
145
|
-
return MIGRATION_VERSION as number;
|
|
146
|
-
} catch (error) {
|
|
147
|
-
console.error(`❌ Error loading migrationCount:`, error);
|
|
148
|
-
process.exit(1);
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Updates an existing database migration by generating schema modifications.
|
|
154
|
-
* @param options - Database connection settings and output paths.
|
|
155
|
-
*/
|
|
156
|
-
export const updateMigration = async (options: any) => {
|
|
157
|
-
try {
|
|
158
|
-
let version = await loadMigrationVersion(options.output);
|
|
159
|
-
|
|
160
|
-
if (version < 1) {
|
|
161
|
-
console.log(
|
|
162
|
-
`⚠️ Initial migration not found. Run "npx forge-sql-orm migrations:create" first.`,
|
|
163
|
-
);
|
|
164
|
-
process.exit(0);
|
|
165
|
-
}
|
|
166
|
-
version += 1;
|
|
167
|
-
|
|
168
|
-
// Load entities dynamically from index.ts
|
|
169
|
-
const entities = await loadEntities(options.entitiesPath);
|
|
170
|
-
|
|
171
|
-
// Initialize MikroORM
|
|
172
|
-
const orm = MikroORM.initSync({
|
|
173
|
-
host: options.host,
|
|
174
|
-
port: options.port,
|
|
175
|
-
user: options.user,
|
|
176
|
-
password: options.password,
|
|
177
|
-
dbName: options.dbName,
|
|
178
|
-
entities,
|
|
179
|
-
debug: true,
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
// Generate SQL schema updates
|
|
183
|
-
const createSchemaSQL = await orm.schema.getUpdateSchemaMigrationSQL({ wrap: true });
|
|
184
|
-
const statements = extractCreateStatements(createSchemaSQL?.down || "");
|
|
185
|
-
|
|
186
|
-
if (statements.length) {
|
|
187
|
-
const migrationFile = generateMigrationFile(statements, version);
|
|
188
|
-
saveMigrationFiles(migrationFile, version, options.output);
|
|
189
|
-
|
|
190
|
-
console.log(`✅ Migration successfully updated!`);
|
|
191
|
-
process.exit(0);
|
|
192
|
-
} else {
|
|
193
|
-
console.log(`⚠️ No new migration changes detected.`);
|
|
194
|
-
process.exit(0);
|
|
195
|
-
}
|
|
196
|
-
} catch (error) {
|
|
197
|
-
console.error(`❌ Error during migration update:`, error);
|
|
198
|
-
process.exit(1);
|
|
199
|
-
}
|
|
200
|
-
};
|
package/scripts/cli.ts
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
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);
|