Study/scripts/backup-database.mjs

42 lines
1.6 KiB
JavaScript

import { existsSync } from "node:fs";
import path from "node:path";
import { pathToFileURL } from "node:url";
import Database from "better-sqlite3";
import { databasePathFromUrl } from "./databasePath.mjs";
function argument(name) {
const index = process.argv.indexOf(name);
return index >= 0 ? process.argv[index + 1] : undefined;
}
export async function backupDatabase(sourcePath, outputPath) {
const source = path.resolve(sourcePath);
const output = path.resolve(outputPath);
if (!existsSync(source)) throw new Error(`Source database does not exist: ${source}`);
if (existsSync(output)) throw new Error(`Backup destination already exists: ${output}`);
if (source === output) throw new Error("Backup destination must differ from source");
const database = new Database(source, { readonly: true, fileMustExist: true });
try {
await database.backup(output);
} finally {
database.close();
}
const backup = new Database(output, { readonly: true, fileMustExist: true });
try {
const integrity = backup.pragma("integrity_check", { simple: true });
if (integrity !== "ok") throw new Error(`Backup integrity check failed: ${integrity}`);
} finally {
backup.close();
}
return output;
}
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
const source = argument("--source") ?? databasePathFromUrl(process.env.DATABASE_URL);
const output = argument("--output");
if (!output) throw new Error("Usage: npm run db:backup -- --output <new-backup.db>");
const completedPath = await backupDatabase(source, output);
console.info(`Verified SQLite backup created: ${completedPath}`);
}