34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
/**
|
|
* # 函数 数据库迁移执行器
|
|
* 读取 src/db/migrations/*.sql 按文件名顺序应用,记录到 drizzle.__migrations。
|
|
* 支持重复执行(幂等)。Bun.sql 直连,不依赖 pg/postgres.js。
|
|
*/
|
|
import { readdirSync, readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { SQL } from "bun";
|
|
|
|
const url = process.env.DATABASE_URL || "postgres://dusuniot:dusuniot@127.0.0.1:25432/dusuniot";
|
|
const sql = new SQL(url);
|
|
|
|
await sql`CREATE SCHEMA IF NOT EXISTS drizzle`;
|
|
await sql`CREATE TABLE IF NOT EXISTS drizzle.__migrations (id serial primary key, hash text unique, created_at timestamptz default now())`;
|
|
|
|
const applied = new Set<string>();
|
|
for (const row of await sql`SELECT hash FROM drizzle.__migrations`.values()) applied.add(row[0] as string);
|
|
|
|
const dir = join(import.meta.dir, "../src/db/migrations");
|
|
const files = readdirSync(dir).filter((f) => f.endsWith(".sql")).sort();
|
|
let ran = 0;
|
|
for (const f of files) {
|
|
if (applied.has(f)) continue;
|
|
const content = readFileSync(join(dir, f), "utf8");
|
|
await sql.begin(async (tx) => {
|
|
await tx.unsafe(content);
|
|
await tx`INSERT INTO drizzle.__migrations (hash) VALUES (${f})`;
|
|
});
|
|
console.log(`applied ${f}`);
|
|
ran++;
|
|
}
|
|
console.log(ran === 0 ? "already up to date" : `done: ${ran} migration(s)`);
|
|
sql.end();
|