@bobbykim/manguito-cms-cli 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +81 -35
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -17217,27 +17217,59 @@ async function runDevMigration(configPath) {
|
|
|
17217
17217
|
env: resolvedPathEnv()
|
|
17218
17218
|
});
|
|
17219
17219
|
}
|
|
17220
|
-
async function
|
|
17220
|
+
async function runGenerate(configPath, outFolder, cwd) {
|
|
17221
17221
|
let beforeFiles = [];
|
|
17222
17222
|
try {
|
|
17223
|
-
const entries = await fs.readdir(
|
|
17223
|
+
const entries = await fs.readdir(outFolder);
|
|
17224
17224
|
beforeFiles = entries.filter((f) => f.endsWith(".sql"));
|
|
17225
17225
|
} catch {
|
|
17226
17226
|
}
|
|
17227
17227
|
execSync(`drizzle-kit generate --config=${configPath}`, {
|
|
17228
17228
|
stdio: "inherit",
|
|
17229
|
-
cwd
|
|
17229
|
+
cwd,
|
|
17230
17230
|
env: resolvedPathEnv()
|
|
17231
17231
|
});
|
|
17232
17232
|
let afterFiles = [];
|
|
17233
17233
|
try {
|
|
17234
|
-
const entries = await fs.readdir(
|
|
17234
|
+
const entries = await fs.readdir(outFolder);
|
|
17235
17235
|
afterFiles = entries.filter((f) => f.endsWith(".sql"));
|
|
17236
17236
|
} catch {
|
|
17237
17237
|
}
|
|
17238
17238
|
const beforeSet = new Set(beforeFiles);
|
|
17239
17239
|
return afterFiles.filter((f) => !beforeSet.has(f));
|
|
17240
17240
|
}
|
|
17241
|
+
async function generateMigration(configPath, migrationsFolder) {
|
|
17242
|
+
return runGenerate(configPath, migrationsFolder, path.dirname(configPath));
|
|
17243
|
+
}
|
|
17244
|
+
async function previewMigration(configPath, migrationsFolder) {
|
|
17245
|
+
const configDir = path.dirname(configPath);
|
|
17246
|
+
const tmp = await fs.mkdtemp(path.join(configDir, ".migration-preview-"));
|
|
17247
|
+
try {
|
|
17248
|
+
const out = path.join(tmp, "migrations");
|
|
17249
|
+
try {
|
|
17250
|
+
await fs.cp(migrationsFolder, out, { recursive: true });
|
|
17251
|
+
} catch (err) {
|
|
17252
|
+
if (err.code !== "ENOENT") throw err;
|
|
17253
|
+
}
|
|
17254
|
+
const base = `./${path.basename(configPath).replace(/\.[cm]?[jt]s$/, "")}`;
|
|
17255
|
+
const tmpConfig = path.join(tmp, "drizzle.config.ts");
|
|
17256
|
+
await fs.writeFile(
|
|
17257
|
+
tmpConfig,
|
|
17258
|
+
[
|
|
17259
|
+
`import base from '.${base}'`,
|
|
17260
|
+
// Relative to the real config's folder, where drizzle-kit runs.
|
|
17261
|
+
`export default { ...base, out: './${path.relative(configDir, out).split(path.sep).join("/")}' }`,
|
|
17262
|
+
""
|
|
17263
|
+
].join("\n")
|
|
17264
|
+
);
|
|
17265
|
+
const names = await runGenerate(tmpConfig, out, configDir);
|
|
17266
|
+
return await Promise.all(
|
|
17267
|
+
names.map(async (name) => ({ name, sql: await fs.readFile(path.join(out, name), "utf8") }))
|
|
17268
|
+
);
|
|
17269
|
+
} finally {
|
|
17270
|
+
await fs.rm(tmp, { recursive: true, force: true });
|
|
17271
|
+
}
|
|
17272
|
+
}
|
|
17241
17273
|
async function applyMigrations(configPath, db, options) {
|
|
17242
17274
|
const { migrationsTable, migrationsFolder } = options;
|
|
17243
17275
|
await db.execute(
|
|
@@ -17379,11 +17411,14 @@ function formatAlterColumnType(line2) {
|
|
|
17379
17411
|
return `ALTER COLUMN ${tableName}.${colName} TYPE ${newType}`;
|
|
17380
17412
|
}
|
|
17381
17413
|
function scanMigrationFiles(filePaths) {
|
|
17414
|
+
return scanMigrationSql(
|
|
17415
|
+
filePaths.map((filePath) => ({ name: path2.basename(filePath), sql: readFileSync(filePath, "utf-8") }))
|
|
17416
|
+
);
|
|
17417
|
+
}
|
|
17418
|
+
function scanMigrationSql(migrations) {
|
|
17382
17419
|
const operations = [];
|
|
17383
|
-
for (const
|
|
17384
|
-
const content = readFileSync(filePath, "utf-8");
|
|
17420
|
+
for (const { name: filename, sql: content } of migrations) {
|
|
17385
17421
|
const lines = content.split("\n");
|
|
17386
|
-
const filename = path2.basename(filePath);
|
|
17387
17422
|
for (const line2 of lines) {
|
|
17388
17423
|
const upper = line2.trim().toUpperCase();
|
|
17389
17424
|
if (upper.includes("DROP COLUMN")) {
|
|
@@ -24739,7 +24774,7 @@ function registerUserRoutes(app, db, requirePermission, requireHierarchy) {
|
|
|
24739
24774
|
}
|
|
24740
24775
|
var API_VERSION = (() => {
|
|
24741
24776
|
try {
|
|
24742
|
-
return "0.9.
|
|
24777
|
+
return "0.9.1";
|
|
24743
24778
|
} catch {
|
|
24744
24779
|
return "0.0.0";
|
|
24745
24780
|
}
|
|
@@ -26124,6 +26159,16 @@ function buildDeps(options, cwd) {
|
|
|
26124
26159
|
prompt: createPromptAdapter()
|
|
26125
26160
|
};
|
|
26126
26161
|
}
|
|
26162
|
+
function printDestructiveOperations(scan) {
|
|
26163
|
+
process.stdout.write("\u26A0 This migration contains destructive operations:\n");
|
|
26164
|
+
for (const op of scan.operations) process.stdout.write(` - ${op.operation}
|
|
26165
|
+
`);
|
|
26166
|
+
process.stdout.write("\n");
|
|
26167
|
+
}
|
|
26168
|
+
async function readPendingMigrations(db, migrationsTable, migrationsFolder) {
|
|
26169
|
+
const { pending } = await getMigrationStatus(db.getDb(), { migrationsTable, migrationsFolder });
|
|
26170
|
+
return Promise.all(pending.map(async (name) => ({ name, sql: await readFile2(join12(migrationsFolder, name), "utf-8") })));
|
|
26171
|
+
}
|
|
26127
26172
|
async function runMigrate(options, deps) {
|
|
26128
26173
|
if (options.status) {
|
|
26129
26174
|
loadEnvFile(options.env);
|
|
@@ -26189,19 +26234,39 @@ async function runMigrate(options, deps) {
|
|
|
26189
26234
|
printSuccess("Build complete");
|
|
26190
26235
|
const generatedDir = resolve8(cwd, "dist/generated");
|
|
26191
26236
|
await generateDrizzleConfig(config2, generatedDir);
|
|
26237
|
+
if (options.dryRun) {
|
|
26238
|
+
const pending2 = await readPendingMigrations(deps.db, migrationsTable, migrationsFolder);
|
|
26239
|
+
const preview = await previewMigration(deps.configPath, migrationsFolder);
|
|
26240
|
+
const all = [...pending2, ...preview];
|
|
26241
|
+
if (pending2.length > 0) {
|
|
26242
|
+
printSuccess(`Generated earlier, not yet applied: ${pending2.map((m2) => m2.name).join(", ")}`);
|
|
26243
|
+
}
|
|
26244
|
+
printSuccess(
|
|
26245
|
+
preview.length === 0 ? "No new migration would be generated" : `Would generate ${preview.length} migration file${preview.length !== 1 ? "s" : ""}: ${preview.map((m2) => m2.name).join(", ")}`
|
|
26246
|
+
);
|
|
26247
|
+
process.stdout.write("\nDry run \u2014 no migration files written, no changes applied.\n\n");
|
|
26248
|
+
if (all.length > 0) {
|
|
26249
|
+
process.stdout.write("SQL `manguito migrate` would apply:\n");
|
|
26250
|
+
process.stdout.write("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
|
|
26251
|
+
for (const m2 of all) process.stdout.write(`-- ${m2.name}
|
|
26252
|
+
${m2.sql}
|
|
26253
|
+
`);
|
|
26254
|
+
process.stdout.write("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n");
|
|
26255
|
+
const scan = scanMigrationSql(all);
|
|
26256
|
+
if (scan.hasDestructiveOperations) printDestructiveOperations(scan);
|
|
26257
|
+
else process.stdout.write("No destructive operations detected.\n\n");
|
|
26258
|
+
process.stdout.write("Run `manguito migrate` to generate and apply these.\n");
|
|
26259
|
+
}
|
|
26260
|
+
process.exit(0);
|
|
26261
|
+
}
|
|
26192
26262
|
const newFileNames = await generateMigration(deps.configPath, migrationsFolder);
|
|
26193
|
-
const newFilePaths = newFileNames.map((f) => join12(migrationsFolder, f));
|
|
26194
26263
|
printSuccess(
|
|
26195
26264
|
newFileNames.length === 0 ? "No new migration files generated" : `Generated ${newFileNames.length} migration file${newFileNames.length !== 1 ? "s" : ""}: ${newFileNames.join(", ")}`
|
|
26196
26265
|
);
|
|
26197
|
-
const
|
|
26266
|
+
const { pending } = await getMigrationStatus(deps.db.getDb(), { migrationsTable, migrationsFolder });
|
|
26267
|
+
const scanResult = scanMigrationFiles(pending.map((f) => join12(migrationsFolder, f)));
|
|
26198
26268
|
if (scanResult.hasDestructiveOperations) {
|
|
26199
|
-
|
|
26200
|
-
for (const op of scanResult.operations) {
|
|
26201
|
-
process.stdout.write(` - ${op.operation}
|
|
26202
|
-
`);
|
|
26203
|
-
}
|
|
26204
|
-
process.stdout.write("\n");
|
|
26269
|
+
printDestructiveOperations(scanResult);
|
|
26205
26270
|
process.stdout.write(" These changes are irreversible and may cause data loss.\n");
|
|
26206
26271
|
const uniqueFiles = [...new Set(scanResult.operations.map((op) => op.file))];
|
|
26207
26272
|
for (const file of uniqueFiles) {
|
|
@@ -26219,25 +26284,6 @@ async function runMigrate(options, deps) {
|
|
|
26219
26284
|
}
|
|
26220
26285
|
}
|
|
26221
26286
|
}
|
|
26222
|
-
if (options.dryRun) {
|
|
26223
|
-
process.stdout.write("\nDry run \u2014 no files will be written, no changes applied.\n\n");
|
|
26224
|
-
if (newFilePaths.length > 0) {
|
|
26225
|
-
process.stdout.write("Generated SQL:\n");
|
|
26226
|
-
process.stdout.write("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
|
|
26227
|
-
for (const filePath of newFilePaths) {
|
|
26228
|
-
const sql2 = await readFile2(filePath, "utf-8");
|
|
26229
|
-
process.stdout.write(sql2);
|
|
26230
|
-
}
|
|
26231
|
-
process.stdout.write("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n");
|
|
26232
|
-
} else {
|
|
26233
|
-
process.stdout.write("No SQL changes generated.\n\n");
|
|
26234
|
-
}
|
|
26235
|
-
if (!scanResult.hasDestructiveOperations) {
|
|
26236
|
-
process.stdout.write("No destructive operations detected.\n\n");
|
|
26237
|
-
}
|
|
26238
|
-
process.stdout.write("Run `manguito migrate` to generate and apply this migration.\n");
|
|
26239
|
-
process.exit(0);
|
|
26240
|
-
}
|
|
26241
26287
|
const migrationResult = await applyMigrations(deps.configPath, deps.db.getDb(), {
|
|
26242
26288
|
migrationsTable,
|
|
26243
26289
|
migrationsFolder
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobbykim/manguito-cms-cli",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Bobby Kim <bobby.sihun.kim@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/bobbykim89/manguito-cms",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"typescript": "^6.0.3",
|
|
31
31
|
"vite": "^8.1.3",
|
|
32
32
|
"@bobbykim/manguito-cms-admin": "0.5.4",
|
|
33
|
-
"@bobbykim/manguito-cms-api": "0.9.
|
|
34
|
-
"@bobbykim/manguito-cms-
|
|
35
|
-
"@bobbykim/manguito-cms-
|
|
33
|
+
"@bobbykim/manguito-cms-api": "0.9.1",
|
|
34
|
+
"@bobbykim/manguito-cms-db": "0.2.0",
|
|
35
|
+
"@bobbykim/manguito-cms-core": "0.10.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^25.9.5",
|