import { projectRef } from "@/lib/projects"; import { articleTarget, projectTargetFor, TargetError } from "./targets.mjs"; // The app's side of lib/annotations/targets.mjs: a request's `article` or // `project` parameter to a target, using the app's memoised project walk. // Everything about WHERE a note may be written is decided in targets.mjs. export type Target = Awaited> | Awaited>; export async function targetFrom(params: { article?: string | null; project?: string | null }): Promise { if (params.article && params.project) throw new TargetError("pass article or project, not both"); if (params.article) return articleTarget(params.article); if (params.project) { const p = await projectRef(params.project); if (!p) throw new TargetError(`no project ${params.project}`, 404); return projectTargetFor(p); } throw new TargetError("pass ?article=/ or ?project="); } /** A thrown error as a response: typed refusals keep their status, the rest are 500s. */ export function errorResponse(err: unknown): Response { const status = typeof (err as { status?: unknown })?.status === "number" ? (err as { status: number }).status : null; const name = (err as Error)?.name; const code = status ?? (name === "NoteError" ? 400 : 500); return Response.json({ error: err instanceof Error ? err.message : String(err) }, { status: code }); }