迁移系统
createMigrationRunner 提供了版本化数据库结构变更能力,支持顺序执行、回滚和迁移状态追踪。迁移记录持久化于 __migrations 表。
import { createMigrationRunner } from "@ventostack/database";import type { Migration } from "@ventostack/database";
const migrations: Migration[] = [ { name: "001_create_users_table", up: async (exec) => { await exec(` CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT NOW() ) `); }, down: async (exec) => { await exec("DROP TABLE IF EXISTS users"); }, }, { name: "002_create_posts_table", up: async (exec) => { await exec(` CREATE TABLE posts ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, title VARCHAR(500) NOT NULL, created_at TIMESTAMP DEFAULT NOW() ) `); }, down: async (exec) => { await exec("DROP TABLE IF EXISTS posts"); }, },];// 创建迁移运行器const runner = createMigrationRunner(db.raw);
// 注册迁移for (const m of migrations) { runner.addMigration(m);}
// 应用所有待执行的迁移const executed = await runner.up();console.log("已执行迁移:", executed);
// 回滚最近 1 个迁移const rolledBack = await runner.down();console.log("已回滚迁移:", rolledBack);
// 回滚最近 3 个迁移await runner.down(3);查询迁移状态
Section titled “查询迁移状态”const status = await runner.status();status.forEach(({ name, executedAt }) => { console.log(`${name}: ${executedAt ? "已执行" : "待执行"}`);});在应用启动时运行
Section titled “在应用启动时运行”VentoStackApp 通过 app.lifecycle 暴露生命周期钩子,使用 onBeforeStart 在应用开始监听前运行迁移:
const app = createApp({ port: 3000 });
app.lifecycle.onBeforeStart(async () => { const runner = createMigrationRunner(db.raw); for (const m of migrations) { runner.addMigration(m); } const executed = await runner.up(); console.log("数据库迁移完成", executed);});MigrationRunner 接口
Section titled “MigrationRunner 接口”interface Migration { name: string; up: (executor: (text: string, params?: unknown[]) => Promise<unknown>) => Promise<void>; down: (executor: (text: string, params?: unknown[]) => Promise<unknown>) => Promise<void>;}
interface MigrationStatus { name: string; executedAt: Date | null;}
interface MigrationRunner { addMigration(migration: Migration): void; up(): Promise<string[]>; down(steps?: number): Promise<string[]>; status(): Promise<MigrationStatus[]>;}- 迁移名称
name是唯一标识,建议使用时间戳或序号前缀(如001_、20240101_)保证顺序。 up()按名称升序执行所有未执行的迁移。down(steps)按名称倒序回滚最近steps个已执行迁移,默认回滚 1 个。- 迁移执行器
exec接收 SQL 字符串和可选的参数数组,与db.raw签名一致。 __migrations表自动创建,无需手动维护。- 重复注册相同
name的迁移会抛出错误。