import { TRIM_SETS, readCatalogue, readTrims, writeTrims, type TrimEntry } from "@/lib/trim"; export const dynamic = "force-dynamic"; // The catalogue and the trims for one set. // // The set is a KEY into a registry, never a path. The client never names the // stem, the hook directory or the trims file -- which is what keeps a request // from being able to point the editor at arbitrary audio, and what keeps // `hooks-verb` from being overridable from outside (see lib/trim.ts). export async function GET(_request: Request, ctx: { params: Promise<{ set: string }> }) { const { set: id } = await ctx.params; const set = TRIM_SETS[id]; if (!set) return Response.json({ error: "no such trim set" }, { status: 404 }); const [catalogue, trims] = await Promise.all([readCatalogue(set), readTrims(set)]); return Response.json( { set: { id: set.id, label: set.label, hookDir: set.hookDir, stem: set.stem }, hooks: catalogue.hooks, sr: catalogue.sr ?? 48000, trims, }, { headers: { "cache-control": "no-store" } }, ); } export async function PUT(request: Request, ctx: { params: Promise<{ set: string }> }) { const { set: id } = await ctx.params; const set = TRIM_SETS[id]; if (!set) return Response.json({ error: "no such trim set" }, { status: 404 }); let body: { trims?: TrimEntry[] }; try { body = await request.json(); } catch { return Response.json({ error: "bad json" }, { status: 400 }); } if (!Array.isArray(body.trims)) return Response.json({ error: "trims must be an array" }, { status: 400 }); // Only files the catalogue knows about. A trim for a hook that does not exist // would be copied through silently by apply-hook-trims and never noticed. const known = new Set((await readCatalogue(set)).hooks.map((h) => h.file)); const unknown = body.trims.filter((t) => !known.has(t.file)).map((t) => t.file); if (unknown.length) { return Response.json({ error: `not in the catalogue: ${unknown.join(", ")}` }, { status: 400 }); } const written = await writeTrims(set, body.trims); return Response.json({ ok: true, trims: written }, { headers: { "cache-control": "no-store" } }); }