Nexova / src /app /api /backup /route.ts
Nexova
fix: backup/restore use HF commit API, correct auth
15172c9
import { existsSync, readdirSync, statSync, readFileSync } from "fs";
import { join } from "path";
const DB_DIR = join(process.cwd(), "data");
const DB_PATH = join(DB_DIR, "nexova.db");
export async function POST(req: Request) {
const { action } = await req.json().catch(() => ({ action: "backup" }));
if (action === "info") {
const files = existsSync(DB_DIR)
? readdirSync(DB_DIR).map((f) => {
const s = statSync(join(DB_DIR, f));
return { name: f, size: `${(s.size / 1024).toFixed(1)}KB`, modified: s.mtime.toISOString() };
})
: [];
return Response.json({ ok: true, data: { dir: DB_DIR, files } });
}
if (action === "backup") {
if (!existsSync(DB_PATH))
return Response.json({ ok: false, error: "no database file" }, { status: 400 });
const token = process.env.HF_TOKEN;
const repo = process.env.HF_DATASET ?? "jay-hank/Nexova-storage";
if (!token) return Response.json({ ok: false, error: "HF_TOKEN not set" }, { status: 500 });
try {
const file = readFileSync(DB_PATH);
const b64 = Buffer.from(file).toString("base64");
const res = await fetch(
`https://huggingface.co/api/datasets/${repo}/commit/main`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
summary: `backup ${new Date().toISOString()}`,
operations: [{
op: "upload",
path: "nexova.db",
encoding: "base64",
content: b64,
}],
}),
}
);
const status = res.status;
const text = await res.text();
return Response.json({ ok: status < 400, message: `HTTP ${status}`, detail: text });
} catch (e: unknown) {
return Response.json({ ok: false, error: e instanceof Error ? e.message : String(e) }, { status: 500 });
}
}
return Response.json({ ok: false, error: `unknown action: ${action}` }, { status: 400 });
}