vibeorm 1.1.0 → 1.1.2
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/package.json +6 -6
- package/src/commands/migrate-generate.ts +26 -4
- package/src/commands/migrate-rollback.ts +115 -0
- package/src/index.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeorm",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "CLI for VibeORM — generate clients, run migrations, introspect databases",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
"bun": ">=1.1.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@vibeorm/parser": "1.1.
|
|
45
|
-
"@vibeorm/generator": "1.1.
|
|
46
|
-
"@vibeorm/migrate": "1.1.
|
|
47
|
-
"@vibeorm/runtime": "1.1.
|
|
48
|
-
"@vibeorm/adapter-bun": "1.1.
|
|
44
|
+
"@vibeorm/parser": "1.1.2",
|
|
45
|
+
"@vibeorm/generator": "1.1.2",
|
|
46
|
+
"@vibeorm/migrate": "1.1.2",
|
|
47
|
+
"@vibeorm/runtime": "1.1.2",
|
|
48
|
+
"@vibeorm/adapter-bun": "1.1.2"
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -99,19 +99,40 @@ export async function runMigrateGenerate(params: {
|
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
// 5.
|
|
102
|
+
// 5. Generate down SQL (reverse operations in reverse order)
|
|
103
|
+
const downSql = operations
|
|
104
|
+
.filter((op: DiffOperation) => op.isReversible)
|
|
105
|
+
.reverse()
|
|
106
|
+
.map((op: DiffOperation) => op.downSql)
|
|
107
|
+
.join("\n\n");
|
|
108
|
+
|
|
109
|
+
const nonReversibleOps = operations.filter((op: DiffOperation) => !op.isReversible);
|
|
110
|
+
let downMigrationSql = "";
|
|
111
|
+
if (nonReversibleOps.length > 0) {
|
|
112
|
+
const warnings = nonReversibleOps
|
|
113
|
+
.map((op: DiffOperation) => `-- WARNING: "${op.description}" is not cleanly reversible.\n${op.downSql}`)
|
|
114
|
+
.reverse()
|
|
115
|
+
.join("\n\n");
|
|
116
|
+
downMigrationSql = `-- Down migration\n-- WARNING: Some operations in this migration are not cleanly reversible.\n\n${warnings}${downSql ? "\n\n" + downSql : ""}`;
|
|
117
|
+
} else {
|
|
118
|
+
downMigrationSql = `-- Down migration\n\n${downSql}`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 6. Create migration files
|
|
103
122
|
const timestamp = generateTimestamp();
|
|
104
123
|
const dirName = `${timestamp}_${migrationName}`;
|
|
105
124
|
const migrationDir = join(config.migrations, dirName);
|
|
106
125
|
const sqlPath = join(migrationDir, "migration.sql");
|
|
126
|
+
const downSqlPath = join(migrationDir, "down.sql");
|
|
107
127
|
|
|
108
128
|
mkdirSync(migrationDir, { recursive: true });
|
|
109
129
|
writeFileSync(sqlPath, migrationSql, "utf-8");
|
|
130
|
+
writeFileSync(downSqlPath, downMigrationSql, "utf-8");
|
|
110
131
|
|
|
111
|
-
//
|
|
132
|
+
// 7. Save snapshot
|
|
112
133
|
saveSnapshot({ schema: currentSchema, migrationsDir: config.migrations, timestamp });
|
|
113
134
|
|
|
114
|
-
//
|
|
135
|
+
// 8. Update journal
|
|
115
136
|
const checksum = computeChecksum({ content: migrationSql });
|
|
116
137
|
const journal = loadJournal({ migrationsDir: config.migrations });
|
|
117
138
|
|
|
@@ -127,7 +148,8 @@ export async function runMigrateGenerate(params: {
|
|
|
127
148
|
|
|
128
149
|
console.log("");
|
|
129
150
|
console.log(`Created migration: ${dirName}`);
|
|
130
|
-
console.log(`
|
|
151
|
+
console.log(` Up: ${sqlPath}`);
|
|
152
|
+
console.log(` Down: ${downSqlPath}`);
|
|
131
153
|
console.log("");
|
|
132
154
|
console.log("Generated SQL:");
|
|
133
155
|
console.log(migrationSql);
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vibeorm migrate rollback
|
|
3
|
+
*
|
|
4
|
+
* Roll back the last N applied migrations using their down.sql files.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
ensureMigrationTable,
|
|
9
|
+
getAppliedMigrations,
|
|
10
|
+
rollbackMigration,
|
|
11
|
+
loadJournal,
|
|
12
|
+
} from "@vibeorm/migrate";
|
|
13
|
+
import type { AppliedMigration, JournalEntry } from "@vibeorm/migrate";
|
|
14
|
+
import { existsSync, readFileSync } from "fs";
|
|
15
|
+
import { join } from "path";
|
|
16
|
+
import type { VibeOrmConfig } from "../config.ts";
|
|
17
|
+
import { createConnection } from "../connection.ts";
|
|
18
|
+
|
|
19
|
+
export async function runMigrateRollback(params: {
|
|
20
|
+
config: VibeOrmConfig;
|
|
21
|
+
flags: Record<string, string>;
|
|
22
|
+
}): Promise<void> {
|
|
23
|
+
const { config, flags } = params;
|
|
24
|
+
const steps = parseInt(flags.steps ?? "1", 10);
|
|
25
|
+
const dryRun = flags["dry-run"] === "true";
|
|
26
|
+
|
|
27
|
+
if (isNaN(steps) || steps < 1) {
|
|
28
|
+
console.error("Error: --steps must be a positive integer.");
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.log("VibeORM Migrate Rollback");
|
|
33
|
+
console.log(` Migrations: ${config.migrations}`);
|
|
34
|
+
console.log(` Steps: ${steps}`);
|
|
35
|
+
console.log("");
|
|
36
|
+
|
|
37
|
+
// 1. Load journal
|
|
38
|
+
const journal = loadJournal({ migrationsDir: config.migrations });
|
|
39
|
+
if (journal.entries.length === 0) {
|
|
40
|
+
console.log("No migrations found in journal.");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 2. Connect to database
|
|
45
|
+
const conn = createConnection({ url: flags.url });
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
// 3. Ensure migration table
|
|
49
|
+
await ensureMigrationTable({ executor: conn.executor });
|
|
50
|
+
|
|
51
|
+
// 4. Get applied migrations (ordered by id)
|
|
52
|
+
const applied = await getAppliedMigrations({ executor: conn.executor });
|
|
53
|
+
|
|
54
|
+
if (applied.length === 0) {
|
|
55
|
+
console.log("No migrations have been applied. Nothing to roll back.");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 5. Take the last N applied migrations (in reverse order for rollback)
|
|
60
|
+
const toRollback = applied.slice(-steps).reverse();
|
|
61
|
+
|
|
62
|
+
console.log(`Rolling back ${toRollback.length} migration(s):`);
|
|
63
|
+
for (const migration of toRollback) {
|
|
64
|
+
console.log(` - ${migration.migrationName}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (dryRun) {
|
|
68
|
+
console.log("");
|
|
69
|
+
console.log("DRY RUN — No changes applied.");
|
|
70
|
+
|
|
71
|
+
for (const migration of toRollback) {
|
|
72
|
+
const downSqlPath = join(config.migrations, migration.migrationName, "down.sql");
|
|
73
|
+
if (existsSync(downSqlPath)) {
|
|
74
|
+
const sql = readFileSync(downSqlPath, "utf-8");
|
|
75
|
+
console.log("");
|
|
76
|
+
console.log(`=== ${migration.migrationName} (down.sql) ===`);
|
|
77
|
+
console.log(sql);
|
|
78
|
+
} else {
|
|
79
|
+
console.log("");
|
|
80
|
+
console.log(`=== ${migration.migrationName} ===`);
|
|
81
|
+
console.log("WARNING: No down.sql found for this migration.");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 6. Roll back each migration in reverse order
|
|
88
|
+
console.log("");
|
|
89
|
+
for (const migration of toRollback) {
|
|
90
|
+
const downSqlPath = join(config.migrations, migration.migrationName, "down.sql");
|
|
91
|
+
|
|
92
|
+
if (!existsSync(downSqlPath)) {
|
|
93
|
+
console.error(`Error: No down.sql found for migration: ${migration.migrationName}`);
|
|
94
|
+
console.error(` Expected at: ${downSqlPath}`);
|
|
95
|
+
console.error(" Cannot roll back without a down migration file.");
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const sql = readFileSync(downSqlPath, "utf-8");
|
|
100
|
+
|
|
101
|
+
console.log(`Rolling back ${migration.migrationName}...`);
|
|
102
|
+
const result = await rollbackMigration({
|
|
103
|
+
executor: conn.executor,
|
|
104
|
+
migrationName: migration.migrationName,
|
|
105
|
+
sql,
|
|
106
|
+
});
|
|
107
|
+
console.log(` Done in ${result.executionTime}ms`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log("");
|
|
111
|
+
console.log(`Rolled back ${toRollback.length} migration(s) successfully.`);
|
|
112
|
+
} finally {
|
|
113
|
+
await conn.close();
|
|
114
|
+
}
|
|
115
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* vibeorm migrate generate [--name <n>] [--dry-run] Generate migration from schema diff
|
|
14
14
|
* vibeorm migrate apply [--dry-run] Apply pending migrations
|
|
15
15
|
* vibeorm migrate status Show migration state
|
|
16
|
+
* vibeorm migrate rollback [--steps <n>] [--dry-run] Roll back last N applied migrations
|
|
16
17
|
* vibeorm migrate resolve --applied <name> | --rolled-back <name> Repair migration state
|
|
17
18
|
*/
|
|
18
19
|
|
|
@@ -29,6 +30,7 @@ import { runMigrateGenerate } from "./commands/migrate-generate.ts";
|
|
|
29
30
|
import { runMigrateApply } from "./commands/migrate-apply.ts";
|
|
30
31
|
import { runMigrateStatus } from "./commands/migrate-status.ts";
|
|
31
32
|
import { runMigrateResolve } from "./commands/migrate-resolve.ts";
|
|
33
|
+
import { runMigrateRollback } from "./commands/migrate-rollback.ts";
|
|
32
34
|
|
|
33
35
|
// ─── Command Router ───────────────────────────────────────────────
|
|
34
36
|
|
|
@@ -43,6 +45,7 @@ const COMMANDS: Record<string, (params: { config: VibeOrmConfig; flags: Record<s
|
|
|
43
45
|
"migrate apply": runMigrateApply,
|
|
44
46
|
"migrate status": runMigrateStatus,
|
|
45
47
|
"migrate resolve": runMigrateResolve,
|
|
48
|
+
"migrate rollback": runMigrateRollback,
|
|
46
49
|
};
|
|
47
50
|
|
|
48
51
|
function printHelp(): void {
|
|
@@ -60,6 +63,7 @@ function printHelp(): void {
|
|
|
60
63
|
console.log(" migrate generate [--name <n>] [--dry-run] Generate a new migration from schema changes");
|
|
61
64
|
console.log(" migrate apply [--dry-run] Apply all pending migrations");
|
|
62
65
|
console.log(" migrate status Show which migrations are applied/pending");
|
|
66
|
+
console.log(" migrate rollback [--steps <n>] [--dry-run] Roll back the last N applied migrations");
|
|
63
67
|
console.log(" migrate resolve --applied <name> | --rolled-back <name> Repair migration state");
|
|
64
68
|
console.log("");
|
|
65
69
|
console.log("Options:");
|