42 lines
1.6 KiB
JavaScript
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}`);
|
|
}
|