78 lines
2.1 KiB
TypeScript
78 lines
2.1 KiB
TypeScript
import { rmSync } from "node:fs";
|
|
import {
|
|
discoverWorkspaces,
|
|
getActiveWorkspaceName,
|
|
resolveWorkspaceRoot,
|
|
setUIActiveWorkspace,
|
|
} from "@/lib/workspace";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
export const runtime = "nodejs";
|
|
|
|
const WORKSPACE_NAME_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
|
|
|
|
function normalizeWorkspaceName(raw: unknown): string | null {
|
|
if (typeof raw !== "string") {
|
|
return null;
|
|
}
|
|
const trimmed = raw.trim();
|
|
if (!trimmed) {
|
|
return null;
|
|
}
|
|
if (!WORKSPACE_NAME_RE.test(trimmed)) {
|
|
return null;
|
|
}
|
|
return trimmed;
|
|
}
|
|
|
|
export async function POST(req: Request) {
|
|
const body = (await req.json().catch(() => ({}))) as { workspace?: unknown; profile?: unknown };
|
|
const workspaceName = normalizeWorkspaceName(body.workspace ?? body.profile);
|
|
if (!workspaceName) {
|
|
return Response.json(
|
|
{ error: "Invalid workspace name. Use letters, numbers, hyphens, or underscores." },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
|
|
const availableWorkspace = discoverWorkspaces().find((candidate) => candidate.name === workspaceName);
|
|
if (!availableWorkspace) {
|
|
return Response.json(
|
|
{ error: `Workspace '${workspaceName}' was not found.` },
|
|
{ status: 404 },
|
|
);
|
|
}
|
|
if (!availableWorkspace.workspaceDir) {
|
|
return Response.json(
|
|
{ error: `Workspace '${workspaceName}' does not have a directory to delete.` },
|
|
{ status: 409 },
|
|
);
|
|
}
|
|
|
|
try {
|
|
rmSync(availableWorkspace.workspaceDir, { recursive: true, force: false });
|
|
} catch (error) {
|
|
return Response.json(
|
|
{ error: `Workspace delete failed: ${(error as Error).message}` },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
|
|
const remaining = discoverWorkspaces();
|
|
const previousActive = getActiveWorkspaceName();
|
|
if (previousActive === workspaceName) {
|
|
setUIActiveWorkspace(remaining[0]?.name ?? null);
|
|
}
|
|
const activeWorkspace = getActiveWorkspaceName();
|
|
|
|
return Response.json({
|
|
deleted: true,
|
|
workspace: workspaceName,
|
|
activeWorkspace,
|
|
workspaceRoot: resolveWorkspaceRoot(),
|
|
// Backward-compat response fields while callers migrate.
|
|
profile: workspaceName,
|
|
activeProfile: activeWorkspace,
|
|
});
|
|
}
|