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 "); const completedPath = await backupDatabase(source, output); console.info(`Verified SQLite backup created: ${completedPath}`); }