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.0 KB · 71 lines typescript
Raw Blame History
1/**2 * CancerIndex stable public identifiers (CLAUDE.md §6).3 *4 *   CI-CAN-00000001   cancer entity5 *   CI-GENE-00000001  gene6 *   CI-VAR-00000001   variant7 *   CI-DRUG-00000001  drug8 *   CI-TRIAL-00000001 clinical trial9 *   CI-PUB-00000001   publication10 *   CI-BIO-00000001   biomarker11 *   CI-STUDY-00000001 genomic study / cohort12 *   CI-METRIC-00000001 metric definition13 *   CI-SOURCE-00000001 source14 *   CI-ORG-00000001   organization15 *   CI-TRT-00000001   treatment / regimen16 *   CI-ANAT-00000001  anatomical site17 *   CI-GEO-00000001   geography18 *   CI-PROV-00000001  provenance record19 *20 * IDs are minted from a database sequence per namespace (see @cancerindex/database `mintId`) and21 * are never reused. Database auto-increment integers are never exposed publicly.22 */23export const ID_NAMESPACES = [24  'CAN',25  'GENE',26  'VAR',27  'DRUG',28  'TRIAL',29  'PUB',30  'BIO',31  'STUDY',32  'METRIC',33  'SOURCE',34  'ORG',35  'TRT',36  'ANAT',37  'GEO',38  'PROV',39  'EDGE',40  'RANK',41] as const;42export type IdNamespace = (typeof ID_NAMESPACES)[number];4344export const ID_WIDTH = 8;4546export function formatId(ns: IdNamespace, n: number): string {47  if (!Number.isInteger(n) || n < 1) throw new Error(`invalid id number ${n}`);48  return `CI-${ns}-${String(n).padStart(ID_WIDTH, '0')}`;49}5051const ID_RE = /^CI-([A-Z]+)-(\d{8,})$/;5253export function parseId(id: string): { ns: IdNamespace; n: number } | null {54  const m = ID_RE.exec(id);55  if (!m) return null;56  const ns = m[1] as IdNamespace;57  if (!ID_NAMESPACES.includes(ns)) return null;58  return { ns, n: Number(m[2]) };59}6061export function isCiId(id: string, ns?: IdNamespace): boolean {62  const p = parseId(id);63  return !!p && (ns ? p.ns === ns : true);64}6566/** Ingest run identifiers: ING-CLINICALTRIALS-20260908-000019 (CLAUDE.md §176). */67export function formatRunId(connectorId: string, date: Date, seq: number): string {68  const d = date.toISOString().slice(0, 10).replace(/-/g, '');69  return `ING-${connectorId.toUpperCase().replace(/[^A-Z0-9]/g, '')}-${d}-${String(seq).padStart(6, '0')}`;70}71