import { existsSync } from 'node:fs'; import { join } from 'node:path'; import type { BackupEnv } from '@dorfteich/shared'; import { extractArchive } from './archive.js'; import { archiveFileName, dumpFileName } from './backup-set.js'; import { dataDirs } from './data-dirs.js'; import { pgRestore } from './pg.js'; import type { RemoteLogger } from './remote.js'; /** * Restores one local set into the live database and data volumes: * `pg_restore --clean --if-exists` of the dump, then the volume archive * back over the data mounts (see data-dirs.ts). Shared by the operator CLI * (restore.js via restore.sh) and the in-app restore orchestrator (#103) — * one restore path, exercised by drills and the app alike. */ export async function performRestore( env: Pick< BackupEnv, 'BACKUPS_DIR' | 'DATABASE_URL' | 'UPLOADS_DIR' | 'PLUGINS_DIR' | 'CUSTOM_FONTS_DIR' >, backupId: string, log: RemoteLogger, ): Promise { const dumpFile = join(env.BACKUPS_DIR, dumpFileName(backupId)); const archiveFile = join(env.BACKUPS_DIR, archiveFileName(backupId)); for (const file of [dumpFile, archiveFile]) { if (!existsSync(file)) { throw new Error(`restore set is incomplete — ${file} not found`); } } log.info({ backupId }, 'restoring database dump'); await pgRestore(env.DATABASE_URL, dumpFile); log.info({ backupId }, 'restoring the data-directory archive'); await extractArchive(archiveFile, dataDirs(env)); }