spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1import type { Database } from '@cancerindex/database';2import { computeTrialIntelligence } from './trial-intelligence.js';3import { computeTrialSiteCounts } from './trial-sites.js';4import { computeDrugPipeline } from './drug-pipeline.js';5import { computeResearchGap } from './research-gap.js';67export interface IntelligenceResult {8 trialIntelligenceRows: number;9 trialSiteCountryRows: number;10 drugPipelineRows: number;11 researchGapRows: number;12 ms: number;13}1415/**16 * Derived "intelligence" layer (SPEC §10-11, §15, §34): recomputed after counters, before rankings.17 * Each part is independent and deterministic; a failure in one part is reported, not hidden, and18 * does not prevent the others from running.19 */20export async function computeIntelligence(db: Database, log: (msg: string, extra?: Record<string, unknown>) => void = () => {}): Promise<IntelligenceResult> {21 const t0 = Date.now();22 const out: IntelligenceResult = { trialIntelligenceRows: 0, trialSiteCountryRows: 0, drugPipelineRows: 0, researchGapRows: 0, ms: 0 };23 const errors: string[] = [];24 try {25 const r = await computeTrialIntelligence(db);26 out.trialIntelligenceRows = r.rows;27 log('trial intelligence computed', { ...r });28 } catch (e) {29 errors.push(`trial-intelligence: ${(e as Error).message}`);30 }31 try {32 const r = await computeTrialSiteCounts(db);33 out.trialSiteCountryRows = r.rows;34 log('trial site country counts computed', { ...r });35 } catch (e) {36 errors.push(`trial-sites: ${(e as Error).message}`);37 }38 try {39 const r = await computeDrugPipeline(db);40 out.drugPipelineRows = r.rows;41 log('drug pipeline computed', { ...r });42 } catch (e) {43 errors.push(`drug-pipeline: ${(e as Error).message}`);44 }45 try {46 const r = await computeResearchGap(db);47 out.researchGapRows = r.rows;48 log('research gap components computed', { ...r });49 } catch (e) {50 errors.push(`research-gap: ${(e as Error).message}`);51 }52 out.ms = Date.now() - t0;53 if (errors.length) throw new Error(`intelligence partially failed: ${errors.join(' | ')}`);54 return out;55}56