123 lines
3.4 KiB
TypeScript

import { randomUUID } from "node:crypto";
import { NextResponse } from "next/server";
import { auth } from "@/app/(auth)/auth";
import {
getKittyCadModelingCommandError,
isKittyCadModelingCommandSuccessful,
sendKittyCadModelingCommand,
takeKittyCadModelingSnapshot,
} from "@/lib/kittycad/modeling-session";
export const runtime = "nodejs";
export const maxDuration = 60;
type ModelingCommandRequest = {
captureSnapshot?: boolean;
cmd?: Record<string, unknown>;
cmdId?: string;
sessionId?: string;
snapshotFormat?: "jpeg" | "png";
};
function readOptionalRecord(value: unknown) {
return value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: null;
}
export async function POST(request: Request) {
try {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json(
{ success: false, error: "未登录" },
{ status: 401 }
);
}
const body = (await request.json()) as ModelingCommandRequest;
const sessionId = String(body.sessionId || "").trim();
if (!sessionId) {
return NextResponse.json(
{ success: false, error: "缺少官方建模会话 ID" },
{ status: 400 }
);
}
const cmd = readOptionalRecord(body.cmd);
const cmdType = String(cmd?.type || "").trim();
if (!cmd || !cmdType) {
return NextResponse.json(
{ success: false, error: "缺少有效的官方建模命令" },
{ status: 400 }
);
}
const cmdId = String(body.cmdId || "").trim() || randomUUID();
const response = await sendKittyCadModelingCommand({
cmd: {
...cmd,
type: cmdType,
},
cmdId,
sessionId,
});
if (!isKittyCadModelingCommandSuccessful(response)) {
return NextResponse.json(
{
success: false,
error: getKittyCadModelingCommandError(response),
payload: response.errors || null,
},
{ status: 400 }
);
}
let snapshotUrl: string | null = null;
let snapshotError: string | null = null;
const shouldCaptureSnapshot =
body.captureSnapshot === true && cmdType !== "take_snapshot";
if (cmdType === "take_snapshot") {
const contents = String(response.resp?.data?.contents || "").trim();
const snapshotFormat = body.snapshotFormat || "png";
snapshotUrl = contents
? `data:${snapshotFormat === "jpeg" ? "image/jpeg" : "image/png"};base64,${contents}`
: null;
} else if (shouldCaptureSnapshot) {
try {
const snapshot = await takeKittyCadModelingSnapshot({
format: body.snapshotFormat || "png",
sessionId,
});
snapshotUrl = snapshot.snapshotUrl;
} catch (error) {
snapshotError =
error instanceof Error ? error.message : "获取官方建模快照失败";
}
}
return NextResponse.json({
success: true,
data: {
raw: response,
requestId: response.request_id || cmdId,
responseData: response.resp?.data || null,
responseType: response.resp?.type || cmdType,
snapshotError,
snapshotUrl,
},
});
} catch (error) {
return NextResponse.json(
{
success: false,
error: error instanceof Error ? error.message : "发送官方建模命令失败",
},
{ status: 500 }
);
}
}