import { REPORTS_ROOT } from "../paths"; import { SONG_KIND } from "./song.mjs"; import { ScaffoldError, scaffoldSong } from "./scaffold-song"; import { scaffoldReportVideo } from "./scaffold.mjs"; import { kindById } from "./kinds.mjs"; import { invalidateProjects } from "../projects"; export { ScaffoldError }; export type NewProjectBody = { kind?: string; slug?: string; title?: string | null; from?: string | null; siteOrigin?: string | null; seed?: string | null; brand?: string | null; }; /** * The one place a "new project" request is dispatched by kind. Here rather * than in the route, so the route never learns what a kind is. */ export async function scaffoldProject(body: NewProjectBody): Promise<{ href: string; [k: string]: unknown }> { const kind = String(body.kind ?? ""); const k = kindById(kind); if (!k) throw new ScaffoldError(`unknown kind "${kind}"`); if (!k.scaffold) throw new ScaffoldError(`a ${k.label} is not scaffolded here`); const slug = String(body.slug ?? "").trim().toLowerCase(); let result: { href: string; [k: string]: unknown }; if (kind === SONG_KIND) { result = await scaffoldSong({ slug, title: body.title }); } else { try { const r = await scaffoldReportVideo({ root: REPORTS_ROOT, slug, title: body.title ?? undefined, from: body.from || null, siteOrigin: body.siteOrigin || null, seed: body.seed || null, brand: body.brand || null, }); result = { ...r, href: `/browse/${r.id}` }; } catch (e) { const msg = e instanceof Error ? e.message : String(e); throw new ScaffoldError(msg, /already exists/.test(msg) ? 409 : 400); } } invalidateProjects(); return result; }