panels-origin/api/liquibase.ts
2026-08-21 16:55:01 -05:00

67 lines
1.8 KiB
TypeScript

import { join } from "node:path";
import { ROOT, DATA_DIR } from "./config.ts";
const LIQUIBASE = join(ROOT, "db", "tools", "liquibase", "liquibase");
const SQLITE_JDBC = join(ROOT, "db", "tools", "sqlite-jdbc.jar");
const BOOTSTRAP = join(ROOT, "db", "bootstrap-tools.sh");
async function ensureTools(): Promise<boolean> {
try {
await Deno.stat(LIQUIBASE);
await Deno.stat(SQLITE_JDBC);
return true;
} catch {
const cmd = new Deno.Command("bash", {
args: [BOOTSTRAP],
stdout: "piped",
stderr: "piped",
});
const { code, stdout, stderr } = await cmd.output();
if (code !== 0) {
console.warn(
"[liquibase] bootstrap failed:\n",
new TextDecoder().decode(stdout),
new TextDecoder().decode(stderr),
);
return false;
}
return true;
}
}
async function updateOne(name: "app" | "platform"): Promise<void> {
const dir = join(ROOT, "db", name);
const dbPath = join(DATA_DIR, `${name}.db`);
const cmd = new Deno.Command(LIQUIBASE, {
args: [
"--defaultsFile=liquibase.properties",
`--classpath=${SQLITE_JDBC}`,
`--url=jdbc:sqlite:${dbPath}`,
"update",
],
cwd: dir,
stdout: "piped",
stderr: "piped",
});
const { code, stdout, stderr } = await cmd.output();
const out = new TextDecoder().decode(stdout);
const err = new TextDecoder().decode(stderr);
if (code !== 0) {
throw new Error(`Liquibase update failed for ${name}:\n${out}\n${err}`);
}
}
let ran = false;
/** Apply Liquibase changelogs for app.db and platform.db (idempotent). */
export async function runLiquibase(): Promise<void> {
if (ran) return;
if (!await ensureTools()) {
console.warn("[liquibase] CLI missing; run ./db/update.sh");
ran = true;
return;
}
await updateOne("app");
await updateOne("platform");
ran = true;
}