import 'server-only'; import { getDb, getSql, closeDb, schema } from '@cancerindex/database'; /** Server-side database handle for server components, route handlers and server actions. */ export const db = () => getDb(); export { getDb, getSql, closeDb, schema }; export type { Database } from '@cancerindex/database'; export { sql, eq, and, or, desc, asc, gte, lte, lt, gt, inArray, isNull, isNotNull, ilike, count, ne } from 'drizzle-orm'; import type { SQL } from 'drizzle-orm'; // Tables re-exported explicitly (webpack handles `export *` chains, but explicit names keep the web // bundle's dependency graph obvious and typecheck failures local). export const { cancers, cancerAliases, cancerHierarchy, cancerCodes, anatomicalSites, cancerAnatomy, geographies, sources, ingestRuns, connectorCursors, sourceRecords, provenance, unresolvedLabels, changeEvents, auditLog, genes, geneAliases, variants, variantClinicalSignificance, genomicCohorts, cancerGeneFrequencies, drugs, drugAliases, drugApprovals, clinicalTrials, trialConditions, trialInterventions, trialLocations, publications, publicationEntityEdges, literatureCounts, civicEvidenceItems, knowledgeEdges, epidemiologyObservations, survivalObservations, metricDefinitions, rankingSnapshots, rankings, entityCounters, } = schema; import { DatabaseUnavailableError, isConnectionError } from '@/lib/db-errors'; export { DatabaseUnavailableError, isConnectionError }; /** * Run a query and swallow query-level errors ("relation does not exist", bad column, cast…) so * pages render an EmptyState instead of crashing when a table has not been created on this * environment yet. Connection-level errors are NOT swallowed: they are rethrown as * DatabaseUnavailableError so the route's error.tsx renders (and nothing misleading — a 404 or * an empty state — gets cached by ISR while the database is down). */ export async function safe(fn: () => Promise, fallback: T): Promise { try { return await fn(); } catch (err) { if (err instanceof DatabaseUnavailableError) throw err; if (isConnectionError(err)) { if (process.env.NODE_ENV !== 'production') console.error('[cancerindex/web] database unavailable:', (err as Error).message); throw new DatabaseUnavailableError(err); } if (process.env.NODE_ENV !== 'production') console.error('[cancerindex/web] query failed:', (err as Error).message); return fallback; } } /** Execute a raw SQL query and return plain typed rows (drops the RowList metadata wrapper). */ export async function run(query: SQL): Promise { const res = await getDb().execute(query); return Array.from(res as unknown as Iterable); }