spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1import 'server-only';2import { getDb, getSql, closeDb, schema } from '@cancerindex/database';34/** Server-side database handle for server components, route handlers and server actions. */5export const db = () => getDb();6export { getDb, getSql, closeDb, schema };7export type { Database } from '@cancerindex/database';8export { sql, eq, and, or, desc, asc, gte, lte, lt, gt, inArray, isNull, isNotNull, ilike, count, ne } from 'drizzle-orm';9import type { SQL } from 'drizzle-orm';1011// Tables re-exported explicitly (webpack handles `export *` chains, but explicit names keep the web12// bundle's dependency graph obvious and typecheck failures local).13export const {14 cancers,15 cancerAliases,16 cancerHierarchy,17 cancerCodes,18 anatomicalSites,19 cancerAnatomy,20 geographies,21 sources,22 ingestRuns,23 connectorCursors,24 sourceRecords,25 provenance,26 unresolvedLabels,27 changeEvents,28 auditLog,29 genes,30 geneAliases,31 variants,32 variantClinicalSignificance,33 genomicCohorts,34 cancerGeneFrequencies,35 drugs,36 drugAliases,37 drugApprovals,38 clinicalTrials,39 trialConditions,40 trialInterventions,41 trialLocations,42 publications,43 publicationEntityEdges,44 literatureCounts,45 civicEvidenceItems,46 knowledgeEdges,47 epidemiologyObservations,48 survivalObservations,49 metricDefinitions,50 rankingSnapshots,51 rankings,52 entityCounters,53} = schema;5455import { DatabaseUnavailableError, isConnectionError } from '@/lib/db-errors';56export { DatabaseUnavailableError, isConnectionError };5758/**59 * Run a query and swallow query-level errors ("relation does not exist", bad column, cast…) so60 * pages render an EmptyState instead of crashing when a table has not been created on this61 * environment yet. Connection-level errors are NOT swallowed: they are rethrown as62 * DatabaseUnavailableError so the route's error.tsx renders (and nothing misleading — a 404 or63 * an empty state — gets cached by ISR while the database is down).64 */65export async function safe<T>(fn: () => Promise<T>, fallback: T): Promise<T> {66 try {67 return await fn();68 } catch (err) {69 if (err instanceof DatabaseUnavailableError) throw err;70 if (isConnectionError(err)) {71 if (process.env.NODE_ENV !== 'production') console.error('[cancerindex/web] database unavailable:', (err as Error).message);72 throw new DatabaseUnavailableError(err);73 }74 if (process.env.NODE_ENV !== 'production') console.error('[cancerindex/web] query failed:', (err as Error).message);75 return fallback;76 }77}7879/** Execute a raw SQL query and return plain typed rows (drops the RowList metadata wrapper). */80export async function run<T>(query: SQL): Promise<T[]> {81 const res = await getDb().execute(query);82 return Array.from(res as unknown as Iterable<T>);83}84