|
- import { NextResponse } from 'next/server';
- import { mkdir, writeFile, rm } from 'node:fs/promises';
- import path from 'node:path';
- import crypto from 'node:crypto';
- import { checkSystemBin } from '@/lib/system-bins';
- import { restoreFromZipFile } from '@/lib/restore-zip';
-
- export const dynamic = 'force-dynamic';
- export const maxDuration = 600;
-
- const PROJECT_ROOT = process.cwd();
- const UPLOAD_STAGING = path.join(PROJECT_ROOT, '.restore-staging');
-
- export async function POST(request: Request) {
- if (!(await checkSystemBin('unzip', '-v'))) {
- return NextResponse.json(
- { error: "Restore is unavailable: the 'unzip' command is not installed on the server. Ask the administrator to install it." },
- { status: 503 },
- );
- }
-
- const sessionId = crypto.randomUUID();
- const sessionDir = path.join(UPLOAD_STAGING, `upload-${sessionId}`);
- const zipPath = path.join(sessionDir, 'backup.zip');
-
- try {
- const formData = await request.formData();
- const file = formData.get('file') as File | null;
- if (!file) {
- return NextResponse.json(
- { error: 'No backup file was received. Choose a .zip backup file before clicking Restore.' },
- { status: 400 },
- );
- }
-
- await mkdir(sessionDir, { recursive: true });
- await writeFile(zipPath, Buffer.from(await file.arrayBuffer()));
-
- const result = await restoreFromZipFile(zipPath);
- if (!result.ok) {
- return NextResponse.json({ error: result.error, detail: result.detail }, { status: result.status });
- }
- return NextResponse.json({
- ok: true,
- restored: { cards: result.cards, portals: result.portals },
- previousDataBackup: result.previousBackup,
- });
- } catch (error) {
- console.error('Restore error:', error);
- return NextResponse.json(
- { error: 'Unexpected error during restore. Existing data was not changed. Check the server logs for details and try again.' },
- { status: 500 },
- );
- } finally {
- try { await rm(sessionDir, { recursive: true, force: true }); } catch { /* ignore */ }
- }
- }
|