/** * /api/relations — read typed relations for an entity. * * GET /api/relations?class=person&id=j-edgar-hoover * → Returns relations where this entity is source OR target, * grouped by relation_type and direction. */ import { NextRequest } from "next/server"; import { pgQuery } from "@/lib/retrieval/db"; export const runtime = "nodejs"; export const dynamic = "force-dynamic"; function json(data: unknown, status = 200) { return new Response(JSON.stringify(data), { status, headers: { "content-type": "application/json" }, }); } interface Relation { source_class: string; source_id: string; relation_type: string; target_class: string; target_id: string; evidence_ref: string | null; confidence: string; } export async function GET(req: NextRequest) { const u = new URL(req.url); const cls = u.searchParams.get("class") ?? ""; const id = u.searchParams.get("id") ?? ""; if (!cls || !id) return json({ error: "class and id required" }, 400); try { const outgoing = await pgQuery( `SELECT source_class, source_id, relation_type, target_class, target_id, evidence_ref, confidence FROM public.relations WHERE source_class = $1 AND source_id = $2 ORDER BY confidence DESC, relation_type, target_class, target_id LIMIT 200`, [cls, id], ); const incoming = await pgQuery( `SELECT source_class, source_id, relation_type, target_class, target_id, evidence_ref, confidence FROM public.relations WHERE target_class = $1 AND target_id = $2 ORDER BY confidence DESC, relation_type, source_class, source_id LIMIT 200`, [cls, id], ); return json({ outgoing, incoming }); } catch (e) { return json({ error: "db_unavailable", message: (e as Error).message }, 503); } }