Syv nye API-endepunkter for kunnskapsgrafen: Entities: - GET/POST /api/entities — list, søk (name+aliases), filtrer på type - GET/PATCH/DELETE /api/entities/:id — hent (m/edge_count), oppdater, slett - GET /api/entities/:id/edges — relasjoner med retningsfilter Graf: - POST /api/graph/edges — opprett relasjon (upsert) - DELETE /api/graph/edges/:id — slett relasjon - GET /api/graph/search — fulltekstsøk (entiteter + transkripsjoner FTS) - GET /api/graph/traverse/:nodeId — recursive CTE, D3.js/Vis.js-format Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
73 lines
2.6 KiB
TypeScript
73 lines
2.6 KiB
TypeScript
import { json, error } from '@sveltejs/kit';
|
|
import type { RequestHandler } from './$types';
|
|
import { sql } from '$lib/server/db';
|
|
|
|
/** GET /api/entities/:entityId — Hent entitet med edge-count */
|
|
export const GET: RequestHandler = async ({ params, locals }) => {
|
|
if (!locals.workspace || !locals.user) error(401);
|
|
|
|
const [entity] = await sql`
|
|
SELECT e.id, e.name, e.type, e.aliases, e.avatar_url,
|
|
n.created_at, n.updated_at,
|
|
(SELECT COUNT(*) FROM graph_edges ge
|
|
WHERE ge.source_id = e.id OR ge.target_id = e.id) AS edge_count
|
|
FROM entities e
|
|
JOIN nodes n ON n.id = e.id
|
|
WHERE e.id = ${params.entityId} AND n.workspace_id = ${locals.workspace.id}
|
|
`;
|
|
if (!entity) error(404, 'Entitet ikke funnet');
|
|
|
|
return json(entity);
|
|
};
|
|
|
|
/** PATCH /api/entities/:entityId — Oppdater entitet */
|
|
export const PATCH: RequestHandler = async ({ params, request, locals }) => {
|
|
if (!locals.workspace || !locals.user) error(401);
|
|
|
|
const updates = await request.json();
|
|
|
|
const [existing] = await sql`
|
|
SELECT e.id FROM entities e
|
|
JOIN nodes n ON n.id = e.id
|
|
WHERE e.id = ${params.entityId} AND n.workspace_id = ${locals.workspace.id}
|
|
`;
|
|
if (!existing) error(404, 'Entitet ikke funnet');
|
|
|
|
if (updates.type) {
|
|
const validTypes = ['person', 'organisasjon', 'sted', 'tema', 'konsept'];
|
|
if (!validTypes.includes(updates.type)) {
|
|
error(400, `type må være en av: ${validTypes.join(', ')}`);
|
|
}
|
|
}
|
|
|
|
const [updated] = await sql`
|
|
UPDATE entities SET
|
|
name = COALESCE(${updates.name?.trim() ?? null}, name),
|
|
type = COALESCE(${updates.type ?? null}, type),
|
|
aliases = CASE WHEN ${updates.aliases !== undefined} THEN ${updates.aliases ?? []} ELSE aliases END,
|
|
avatar_url = CASE WHEN ${updates.avatar_url !== undefined} THEN ${updates.avatar_url ?? null} ELSE avatar_url END
|
|
WHERE id = ${params.entityId}
|
|
RETURNING id, name, type, aliases, avatar_url,
|
|
(SELECT created_at FROM nodes WHERE id = entities.id) AS created_at,
|
|
(SELECT updated_at FROM nodes WHERE id = entities.id) AS updated_at
|
|
`;
|
|
|
|
return json(updated);
|
|
};
|
|
|
|
/** DELETE /api/entities/:entityId — Slett entitet */
|
|
export const DELETE: RequestHandler = async ({ params, locals }) => {
|
|
if (!locals.workspace || !locals.user) error(401);
|
|
|
|
const [entity] = await sql`
|
|
SELECT e.id FROM entities e
|
|
JOIN nodes n ON n.id = e.id
|
|
WHERE e.id = ${params.entityId} AND n.workspace_id = ${locals.workspace.id}
|
|
`;
|
|
if (!entity) error(404, 'Entitet ikke funnet');
|
|
|
|
// Slett node (cascader til entities + graph_edges)
|
|
await sql`DELETE FROM nodes WHERE id = ${params.entityId}`;
|
|
|
|
return new Response(null, { status: 204 });
|
|
};
|