Files
Jyotisha/frontend/src/lib/rectification-handoff-route.ts
T
2026-07-21 11:58:42 +08:00

103 lines
3.2 KiB
TypeScript

import { z } from "zod";
import {
RectificationHandoffServiceError,
type RectificationHandoffService,
} from "./rectification-handoff-service.ts";
const identity = {
caseId: z.string().uuid(),
turnVersion: z.number().int().nonnegative(),
actionId: z.string().uuid(),
question: z.string().trim().min(1).max(500),
} as const;
const commandSchema = z.discriminatedUnion("type", [
z.object({ type: z.literal("attach"), ...identity }).strict(),
z.object({ type: z.literal("claim"), ...identity }).strict(),
]);
type Authenticated = Readonly<{ userId: string }>;
export type RectificationHandoffRouteDependencies = Readonly<{
authenticate(): Promise<Authenticated | null>;
service(): RectificationHandoffService;
}>;
function publicFailure(error: unknown) {
if (error instanceof RectificationHandoffServiceError) {
if (error.code === "not_found") {
return Response.json(
{ code: "handoff_not_found", message: "没有找到可继续的原问题。" },
{ status: 404 },
);
}
if (error.code === "stale") {
return Response.json(
{ code: "stale_turn", message: "校正状态已经更新,请刷新后重试。" },
{ status: 409 },
);
}
if (error.code === "conflict") {
return Response.json(
{ code: "handoff_conflict", message: "原问题状态已经变化,请刷新后查看。" },
{ status: 409 },
);
}
}
return Response.json(
{ code: "handoff_unavailable", message: "暂时无法保存或继续原问题,请稍后重试。" },
{ status: 503 },
);
}
export function createRectificationHandoffHandlers(
dependencies: RectificationHandoffRouteDependencies,
) {
return Object.freeze({
async get() {
const authenticated = await dependencies.authenticate();
if (!authenticated) {
return Response.json(
{ code: "authentication_required", message: "登录后才能继续原问题。" },
{ status: 401 },
);
}
try {
const handoff = await dependencies.service().load({ userId: authenticated.userId });
return handoff
? Response.json(handoff)
: new Response(null, { status: 204 });
} catch (error) {
return publicFailure(error);
}
},
async post(request: Request) {
const authenticated = await dependencies.authenticate();
if (!authenticated) {
return Response.json(
{ code: "authentication_required", message: "登录后才能保存或继续原问题。" },
{ status: 401 },
);
}
const parsed = commandSchema.safeParse(await request.json().catch(() => null));
if (!parsed.success) {
return Response.json(
{ code: "invalid_command", message: "原问题交接请求格式不正确。" },
{ status: 400 },
);
}
try {
const service = dependencies.service();
const input = { userId: authenticated.userId, ...parsed.data };
const result = parsed.data.type === "attach"
? await service.attach(input)
: await service.claim(input);
return Response.json(result);
} catch (error) {
return publicFailure(error);
}
},
});
}