import type { GraphMeta, SelectionQueryMeta, SelectionQueryResult, SelectionTriple, SelectionTripleResult, SelectionTripleTerm, } from "./types"; function numberArray(value: unknown): number[] { if (!Array.isArray(value)) return []; const out: number[] = []; for (const item of value) { if (typeof item === "number") out.push(item); } return out; } function tripleTerm(value: unknown): SelectionTripleTerm | null { if (!value || typeof value !== "object") return null; const record = value as Record; if (typeof record.type !== "string" || typeof record.value !== "string") return null; return { type: record.type, value: record.value, lang: typeof record.lang === "string" ? record.lang : undefined, }; } function tripleArray(value: unknown): SelectionTriple[] { if (!Array.isArray(value)) return []; const out: SelectionTriple[] = []; for (const item of value) { if (!item || typeof item !== "object") continue; const record = item as Record; const s = tripleTerm(record.s); const p = tripleTerm(record.p); const o = tripleTerm(record.o); if (!s || !p || !o) continue; out.push({ s, p, o, subject_id: typeof record.subject_id === "number" ? record.subject_id : undefined, predicate_id: typeof record.predicate_id === "number" ? record.predicate_id : undefined, object_id: typeof record.object_id === "number" ? record.object_id : undefined, }); } return out; } export async function fetchSelectionQueries(signal?: AbortSignal): Promise { const res = await fetch("/api/selection_queries", { signal }); if (!res.ok) throw new Error(`GET /api/selection_queries failed: ${res.status}`); const data = await res.json(); return Array.isArray(data) ? (data as SelectionQueryMeta[]) : []; } export async function runSelectionQuery( queryId: string, selectedIds: number[], graphMeta: GraphMeta | null, signal: AbortSignal ): Promise { const body = { query_id: queryId, selected_ids: selectedIds, node_limit: typeof graphMeta?.node_limit === "number" ? graphMeta.node_limit : undefined, edge_limit: typeof graphMeta?.edge_limit === "number" ? graphMeta.edge_limit : undefined, graph_query_id: typeof graphMeta?.graph_query_id === "string" ? graphMeta.graph_query_id : undefined, }; const res = await fetch("/api/selection_query", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body), signal, }); if (!res.ok) throw new Error(`POST /api/selection_query failed: ${res.status}`); const data = await res.json(); return { queryId: typeof data?.query_id === "string" ? data.query_id : queryId, selectedIds: numberArray(data?.selected_ids), neighborIds: numberArray(data?.neighbor_ids), }; } export async function runSelectionTripleQuery( queryId: string, selectedIds: number[], graphMeta: GraphMeta | null, signal: AbortSignal ): Promise { const body = { query_id: queryId, selected_ids: selectedIds, node_limit: typeof graphMeta?.node_limit === "number" ? graphMeta.node_limit : undefined, edge_limit: typeof graphMeta?.edge_limit === "number" ? graphMeta.edge_limit : undefined, graph_query_id: typeof graphMeta?.graph_query_id === "string" ? graphMeta.graph_query_id : undefined, }; const res = await fetch("/api/selection_triples", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body), signal, }); if (!res.ok) throw new Error(`POST /api/selection_triples failed: ${res.status}`); const data = await res.json(); return { queryId: typeof data?.query_id === "string" ? data.query_id : queryId, selectedIds: numberArray(data?.selected_ids), triples: tripleArray(data?.triples), }; }