mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-07-28 11:14:37 +02:00
Generate app/data/{conditions,natural_remedies,home_remedies}.ts from the
repo-root collections/*.json via `npm run gen:curated-data`, so the JSON is the
only file edited by hand. The generated modules keep the data compiled into the
image (no runtime file read, no path fragility, which is why the data was a TS
constant), and curated_data_sync.standalone.ts fails CI if a generated module
ever drifts from its JSON.
This removes the burden of hand-keeping the .json mirror and the .ts constant in
sync. Follow-up to the review discussion on #1040.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
80 lines
2.9 KiB
TypeScript
80 lines
2.9 KiB
TypeScript
/**
|
|
* Generates the curated drug-reference data modules
|
|
* (`app/data/{conditions,natural_remedies,home_remedies}.ts`) from the
|
|
* single-source JSON in the repo-root `collections/` directory.
|
|
*
|
|
* npm run gen:curated-data (from admin/)
|
|
*
|
|
* The JSON files are the ONLY thing a human edits. The generated `.ts` modules
|
|
* keep the data compiled into the image (no runtime file read, no path
|
|
* fragility), and `tests/standalone/curated_data_sync.standalone.ts` fails CI if
|
|
* a generated module ever drifts from its JSON. This removes the old burden of
|
|
* hand-keeping the `.json` mirror and the `.ts` constant in sync
|
|
* (Crosstalk-Solutions/project-nomad#1040 follow-up).
|
|
*/
|
|
import { readFileSync, writeFileSync } from 'node:fs'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { dirname, resolve } from 'node:path'
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url)) // admin/scripts
|
|
const collectionsDir = resolve(here, '../../collections')
|
|
const dataDir = resolve(here, '../app/data')
|
|
|
|
interface Spec {
|
|
name: string
|
|
exportName: string
|
|
typeName: string
|
|
provenance: string
|
|
}
|
|
|
|
const SPECS: Spec[] = [
|
|
{
|
|
name: 'conditions',
|
|
exportName: 'CONDITIONS_FILE',
|
|
typeName: 'ConditionsFile',
|
|
provenance:
|
|
'Curated "when to use what" condition spine (Phase 1). US-government / public-domain sourcing.',
|
|
},
|
|
{
|
|
name: 'natural_remedies',
|
|
exportName: 'NATURAL_REMEDIES_FILE',
|
|
typeName: 'NaturalRemediesFile',
|
|
provenance:
|
|
'Hand-curated subset of NCCIH "Herbs at a Glance" (nccih.nih.gov), mapped to the condition spine. ' +
|
|
'US-government / public domain; attribution lives in the file `source` field and the UI caveat.',
|
|
},
|
|
{
|
|
name: 'home_remedies',
|
|
exportName: 'HOME_REMEDIES_FILE',
|
|
typeName: 'NaturalRemediesFile',
|
|
provenance:
|
|
'Non-herbal home-care / self-care measures from US-government public-domain pages ' +
|
|
'(CDC, NIH/NLM MedlinePlus, FDA); each entry carries its own sourceUrl.',
|
|
},
|
|
]
|
|
|
|
for (const spec of SPECS) {
|
|
const json = JSON.parse(readFileSync(resolve(collectionsDir, `${spec.name}.json`), 'utf8'))
|
|
|
|
const banner =
|
|
`/* eslint-disable */\n` +
|
|
`/**\n` +
|
|
` * GENERATED FILE — DO NOT EDIT.\n` +
|
|
` *\n` +
|
|
` * Single source of truth: collections/${spec.name}.json\n` +
|
|
` * Regenerate after editing the JSON: \`npm run gen:curated-data\` (from admin/).\n` +
|
|
` * curated_data_sync.standalone.ts fails CI if this file drifts from the JSON.\n` +
|
|
` *\n` +
|
|
` * ${spec.provenance}\n` +
|
|
` */\n`
|
|
|
|
const module =
|
|
`import type { ${spec.typeName} } from '../../types/conditions.js'\n\n` +
|
|
`export const ${spec.exportName}: ${spec.typeName} = ${JSON.stringify(json, null, 2)}\n`
|
|
|
|
writeFileSync(resolve(dataDir, `${spec.name}.ts`), banner + module)
|
|
console.log(`generated app/data/${spec.name}.ts ← collections/${spec.name}.json`)
|
|
}
|
|
|
|
console.log('\nDone. Run `npm run format` is applied by the gen script; commit both the JSON and the generated .ts.')
|