// app/api/rigs/route.ts import { NextResponse } from "next/server"; import { dxGET, dxPOST, dxDELETE } from "@/lib/directus"; import { requireBearer } from "@/app/api/_lib/auth"; export const runtime = "nodejs"; function bad(msg: string, code = 400) { return NextResponse.json({ error: msg }, { status: code }); } function takeRows(res: any): T[] { if (Array.isArray(res)) return res; if (Array.isArray(res?.data)) return res.data; return []; } export async function GET(req: Request) { try { const bearer = requireBearer(req); // who am i? const me = await dxGET<{ id: string; role?: { id: string; name?: string } }>( "/users/me?fields=id,role.id,role.name", bearer ); const q = new URL(req.url).searchParams; const limit = Math.min(parseInt(q.get("limit") || "50", 10), 100); const fields = [ "id", "name", "notes", "rig_type.id", "rig_type.name", "laser_source.submission_id", "laser_source.make", "laser_source.model", "laser_scan_lens.id", "laser_scan_lens.field_size", "laser_scan_lens.focal_length", "laser_focus_lens.id", "laser_focus_lens.name", "laser_software.id", "laser_software.name", "date_created", "date_updated", ].join(","); // we’ll try multiple filters; first non-empty result wins const base = `&fields=${encodeURIComponent(fields)}&sort=-date_updated&limit=${limit}`; const tries = [ { label: "owner.id", path: `/items/user_rigs?filter[owner][id][_eq]=${encodeURIComponent(me.id)}${base}` }, { label: "owner", path: `/items/user_rigs?filter[owner][_eq]=${encodeURIComponent(me.id)}${base}` }, { label: "user_created", path: `/items/user_rigs?filter[user_created][_eq]=${encodeURIComponent(me.id)}${base}` }, ]; const attempts: Array<{ label: string; count: number }> = []; let picked: string | null = null; let rows: any[] = []; for (const t of tries) { const res = await dxGET(t.path, bearer); const r = takeRows(res); attempts.push({ label: t.label, count: r.length }); if (r.length) { picked = t.label; rows = r; break; } } // last resort: rely entirely on Directus role rule (no filter) if (!rows.length) { const res = await dxGET(`/items/user_rigs?${base.slice(1)}`, bearer); const r = takeRows(res); attempts.push({ label: "(no filter, rely on role rule)", count: r.length }); if (r.length) { picked = "(role rule)"; rows = r; } } if (q.get("debug") === "1") { return NextResponse.json({ meta: { me: { id: me.id, role: me.role?.name || me.role?.id || null }, picked, attempts, }, data: rows, }); } return NextResponse.json(rows); } catch (e: any) { return bad(e?.message || "Failed to load rigs", e?.status || 500); } } export async function POST(req: Request) { try { const bearer = requireBearer(req); const body = await req.json().catch(() => ({})); const name = (body?.name || "").trim(); const rig_type = body?.rig_type; // id const laser_source = body?.laser_source; // submission_id const laser_scan_lens = body?.laser_scan_lens || null; const laser_focus_lens = body?.laser_focus_lens || null; const laser_software = body?.laser_software || null; const notes = (body?.notes || "").trim(); if (!name) return bad("Missing: name"); if (!rig_type) return bad("Missing: rig_type"); if (!laser_source) return bad("Missing: laser_source"); // derive owner from the authenticated user const me = await dxGET<{ id: string }>("/users/me?fields=id", bearer); const payload: any = { owner: me.id, name, rig_type, laser_source, laser_scan_lens, laser_focus_lens, laser_software, notes, }; const res = await dxPOST<{ data: { id: string } }>( "/items/user_rigs", bearer, payload ); return NextResponse.json({ ok: true, id: String(res?.data?.id) }); } catch (e: any) { return bad(e?.message || "Failed to create rig", e?.status || 500); } } export async function DELETE(req: Request) { try { const bearer = requireBearer(req); const url = new URL(req.url); const id = url.searchParams.get("id"); if (!id) return bad("Missing: id"); // ensure the rig belongs to the current user const me = await dxGET<{ id: string }>("/users/me?fields=id", bearer); const rig = await dxGET( `/items/user_rigs/${encodeURIComponent(id)}?fields=id,owner`, bearer ); if (!rig || String(rig.owner) !== String(me.id)) { return bad("Not your rig", 403); } await dxDELETE(`/items/user_rigs/${encodeURIComponent(id)}`, bearer); return NextResponse.json({ ok: true }); } catch (e: any) { return bad(e?.message || "Failed to delete rig", e?.status || 500); } }