import { mkdir, rm } from "node:fs/promises"; import { execFile } from "node:child_process"; import { promisify } from "node:util"; import { NextResponse } from "next/server"; import { getProjectPath, getProjectsRoot, projectNameSchema, } from "@/lib/projects"; export const runtime = "nodejs"; const execFileAsync = promisify(execFile); export async function POST(request: Request) { let body: unknown; try { body = await request.json(); } catch { return NextResponse.json({ error: "The request body must be valid JSON." }, { status: 400 }); } const result = projectNameSchema.safeParse( typeof body === "object" && body !== null && "name" in body ? (body as { name: unknown }).name : undefined, ); if (!result.success) { return NextResponse.json( { error: result.error.issues[0]?.message || "Enter a valid project name." }, { status: 400 }, ); } const name = result.data; const projectPath = getProjectPath(name); let directoryCreated = false; try { await mkdir(getProjectsRoot(), { recursive: true }); await mkdir(projectPath); directoryCreated = true; await execFileAsync("git", ["init"], { cwd: projectPath }); return NextResponse.json( { name, path: projectPath, gitInitialized: true }, { status: 201 }, ); } catch (error) { if (directoryCreated) { await rm(projectPath, { recursive: true, force: true }).catch(() => undefined); } const code = error && typeof error === "object" && "code" in error ? (error as { code?: string }).code : undefined; if (code === "EEXIST") { return NextResponse.json( { error: "A project with that name already exists." }, { status: 409 }, ); } if (code === "ENOENT") { return NextResponse.json( { error: "Git was not found. Install Git and try again." }, { status: 503 }, ); } console.error("Project creation failed", error); return NextResponse.json( { error: "The project could not be created. Check the server logs for details." }, { status: 500 }, ); } }