2026-03-04 11:14:14 -08:00
|
|
|
import { writeFileSync, mkdirSync } from "node:fs";
|
|
|
|
|
import { dirname } from "node:path";
|
2026-03-15 04:17:11 -07:00
|
|
|
import { resolveFilesystemPath, isProtectedSystemPath } from "@/lib/workspace";
|
2026-03-04 11:14:14 -08:00
|
|
|
|
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
|
export const runtime = "nodejs";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* POST /api/workspace/write-binary
|
|
|
|
|
* Accepts FormData with `file` (Blob) and `path` (string).
|
|
|
|
|
* Writes the binary data to the workspace path.
|
|
|
|
|
*/
|
|
|
|
|
export async function POST(req: Request) {
|
|
|
|
|
let formData: FormData;
|
|
|
|
|
try {
|
|
|
|
|
formData = await req.formData();
|
|
|
|
|
} catch {
|
|
|
|
|
return Response.json({ error: "Invalid form data" }, { status: 400 });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const file = formData.get("file");
|
|
|
|
|
const relPath = formData.get("path");
|
|
|
|
|
|
|
|
|
|
if (!relPath || typeof relPath !== "string") {
|
|
|
|
|
return Response.json({ error: "Missing 'path' field" }, { status: 400 });
|
|
|
|
|
}
|
|
|
|
|
if (!(file instanceof Blob)) {
|
|
|
|
|
return Response.json({ error: "Missing 'file' field (Blob)" }, { status: 400 });
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-15 04:17:11 -07:00
|
|
|
const targetPath = resolveFilesystemPath(relPath, { allowMissing: true });
|
|
|
|
|
if (isProtectedSystemPath(targetPath)) {
|
2026-03-04 11:14:14 -08:00
|
|
|
return Response.json({ error: "Cannot modify system file" }, { status: 403 });
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-15 04:17:11 -07:00
|
|
|
if (!targetPath) {
|
2026-03-04 11:14:14 -08:00
|
|
|
return Response.json(
|
|
|
|
|
{ error: "Invalid path or path traversal rejected" },
|
|
|
|
|
{ status: 400 },
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const buffer = Buffer.from(await file.arrayBuffer());
|
2026-03-15 04:17:11 -07:00
|
|
|
mkdirSync(dirname(targetPath.absolutePath), { recursive: true });
|
|
|
|
|
writeFileSync(targetPath.absolutePath, buffer);
|
2026-03-04 11:14:14 -08:00
|
|
|
return Response.json({ ok: true, path: relPath });
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return Response.json(
|
|
|
|
|
{ error: err instanceof Error ? err.message : "Write failed" },
|
|
|
|
|
{ status: 500 },
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|