import { Command } from "commander"; import grabDBDir from "../utils/grab-db-dir"; import fs from "fs"; import chalk from "chalk"; import grabSortedBackups from "../utils/grab-sorted-backups"; import { select } from "@inquirer/prompts"; import grabBackupData from "../utils/grab-backup-data"; import path from "path"; import mariadbCliEnv, { mariadbCliConnectionArgs, } from "../utils/mariadb-cli-env"; /** * Prefer mariadb client, fall back to mysql. */ function resolveClientBinary(): string { const candidates = ["mariadb", "mysql"]; for (const bin of candidates) { try { const result = Bun.spawnSync(["which", bin], { stdout: "pipe", stderr: "pipe", }); if (result.exitCode === 0) { return new TextDecoder().decode(result.stdout).trim() || bin; } } catch { // try next } } return "mariadb"; } export default function () { return new Command("restore") .description("Restore MariaDB database from an SQL dump") .action(async () => { console.log(`Restoring database ...`); const config = global.CONFIG; const { backup_dir } = grabDBDir({ config }); const backups = grabSortedBackups({ config }).filter((b) => b.endsWith(".sql"), ); if (!backups?.[0]) { console.error( `No SQL backups to restore. Use the \`backup\` command to create a backup.`, ); process.exit(1); } try { const selected_backup = await select({ message: "Select a backup:", choices: backups.map((b, i) => { const { backup_date } = grabBackupData({ backup_name: b, }); return { name: `Backup #${i + 1}: ${backup_date.toDateString()} ${backup_date.getHours()}:${backup_date.getMinutes()}:${backup_date.getSeconds().toString().padStart(2, "0")}`, value: b, }; }), }); const backup_path = path.join(backup_dir, selected_backup); if (!fs.existsSync(backup_path)) { console.error(`Backup file not found: ${backup_path}`); process.exit(1); } const clientBin = resolveClientBinary(); const sql = fs.readFileSync(backup_path, "utf-8"); const args = [ clientBin, ...mariadbCliConnectionArgs(), config.db_name, ]; const proc = Bun.spawn(args, { stdin: new Blob([sql]), stdout: "pipe", stderr: "pipe", env: mariadbCliEnv(), }); const [stderr, exitCode] = await Promise.all([ new Response(proc.stderr).text(), proc.exited, ]); if (exitCode !== 0) { console.error( chalk.red( `Restore failed (exit ${exitCode}): ${stderr || "unknown error"}`, ), ); process.exit(1); } console.log( `${chalk.bold(chalk.green(`DB Restore Success!`))} ← ${selected_backup}`, ); process.exit(0); } catch (error: any) { console.error(`Backup Restore ERROR => ${error.message}`); process.exit(1); } }); }