SPB Git forge

spb/cancerindex

Public
37commits 1branches 0releases
2.9 MBsize
maindefault branch
10 days agolast push
TypeScript 97.2% SQL 1.5% CSS 0.6% JavaScript 0.5%
2.7 KB · 68 lines typescript
Raw Blame History
1import 'server-only';2import { run, sql, safe } from '@/lib/db';3import type { ProvenanceInfo } from '@/components/ui/source-badge';45export interface ProvRow {6  id: number;7  source_id: string;8  source_slug: string;9  source_name: string;10  source_url: string | null;11  dataset: string | null;12  dataset_version: string | null;13  retrieved_at: Date;14  evidence_type: string;15  license: string | null;16  pmid: string | null;17  ingest_run_id: string | null;18  source_record_id: string | null;19  methodology: string | null;20  population: string | null;21  geography: string | null;22}2324/** Load provenance rows (joined with the source) for a set of ids, keyed by id. */25export async function loadProvenance(ids: Array<number | null | undefined>): Promise<Map<number, ProvRow>> {26  const uniq = [...new Set(ids.filter((i): i is number => typeof i === 'number' && Number.isFinite(i)))];27  if (uniq.length === 0) return new Map();28  const rows = await safe(29    () =>30      run<ProvRow>(sql`31        SELECT p.id, p.source_id, s.slug AS source_slug, s.name AS source_name, p.source_url, p.dataset, p.dataset_version,32               p.retrieved_at, p.evidence_type, coalesce(p.license, s.license) AS license, p.pmid, p.ingest_run_id, p.source_record_id,33               p.methodology, p.population, p.geography34        FROM provenance p JOIN sources s ON s.id = p.source_id35        WHERE p.id IN ${sql`(${sql.join(uniq.map((i) => sql`${i}`), sql`, `)})`}`),36    [] as ProvRow[],37  );38  return new Map(rows.map((r) => [Number(r.id), r]));39}4041export function toInfo(p: ProvRow | undefined, layer: ProvenanceInfo['layer'] = 'normalized'): ProvenanceInfo | null {42  if (!p) return null;43  return {44    sourceSlug: p.source_slug,45    sourceName: p.source_name,46    dataset: p.dataset,47    datasetVersion: p.dataset_version,48    retrievedAt: p.retrieved_at,49    sourceUrl: p.source_url,50    layer,51    license: p.license,52    evidenceType: p.evidence_type,53    pmid: p.pmid,54    ingestRunId: p.ingest_run_id,55  };56}5758/** Minimal source lookup for badges when only a source_id is known. */59export async function sourceInfoById(ids: Array<string | null | undefined>): Promise<Map<string, { slug: string; name: string; license: string | null }>> {60  const uniq = [...new Set(ids.filter((i): i is string => !!i))];61  if (uniq.length === 0) return new Map();62  const rows = await safe(63    () => run<{ id: string; slug: string; name: string; license: string | null }>(sql`SELECT id, slug, name, license FROM sources WHERE id IN (${sql.join(uniq.map((i) => sql`${i}`), sql`, `)})`),64    [] as Array<{ id: string; slug: string; name: string; license: string | null }>,65  );66  return new Map(rows.map((r) => [r.id, { slug: r.slug, name: r.name, license: r.license }]));67}68