pediatric-ai-scribe-v3/package.json
Daniel 18550e263f feat(client): port age→weight + BSA + dose + GCS; shared/clinical module
First batch of real calculator ports, routed through a new
shared/clinical/calculators.ts module that both the server tree and
the React client can import. Kept strictly to the simplest, closed-form
formulas — tables (Rosner BP, Fenton LMS, AAP 2022 bili, Bhutani, CDC
BMI) stay in the vanilla viewer until per-table vector files land.

shared/clinical/calculators.ts
  Verbatim ports from public/js/calc-math.js:
    • parseAgeMonths / formatAgeMonths — legacy age-string parser
    • estimateWeightFromAgeMonths — APLS (Luscombe 2007) + Best Guess
      (Tinning 2007) weight-for-age. Cross-checked line-by-line against
      calc-math.js:14-39; identical branches, formulas, and roundTo
      behavior.
    • calculateMostellerBsa — sqrt(h·w/3600), Mosteller 1987.
    • calculateWeightBasedDose — generic mg/kg with optional max cap
      and mg/mL → mL conversion.
    • calculateGcs — 1-15 sum with 8/12 severity thresholds.

shared/clinical/calculators.test.ts
  Vitest unit coverage for each helper. Numeric assertions match the
  legacy function outputs (3y APLS → 14 kg; 20 kg, 110 cm → 0.782 m²;
  15 kg × 100 mg/kg capped at 500 mg, etc.). For these closed-form
  formulas the hand-verified expected values are equivalent to a
  vanilla-captured vector file — table-driven calculators still need
  a JSON fixture before they port.

client/src/pages/Bedside.tsx
  Top-level age-to-weight estimator now runs in React
  (BedsideWeightEstimator). Formula dropdown switches between APLS
  and Best Guess live; weight field accepts a manual override. The
  15 clinical dosing sub-modules still fall through to the legacy
  viewer via LegacyPanel.

client/src/pages/Calculators.tsx
  BSA, Weight-Based Dosing, and GCS panels render real React forms
  backed by the shared helpers. PILLS gain a `ported` flag so the
  four covered panels (bsa, dose, gcs, + the already-shipped pills)
  swap out of the legacy fallback while the others remain linked
  out. Result blocks carry data-testid hooks for parity tests.

Config + dep hygiene picked up along the way
  • client/tsconfig.app.json: @shared/* path alias, exclude test files
    from the React tsc pass.
  • tsconfig.json: exclude **/*.test.ts from the backend tsc pass.
  • package.json: declare google-auth-library and jszip explicitly —
    both were already required() in src/utils/ttsGoogle.ts and
    src/routes/learningAI.ts but missing from dependencies, which
    would break a clean `npm install`. Also adds engines: node >=20
    and convenience verify / verify:full scripts.
  • knip.json: quiet now-expected ignoreDependencies / ignoreBinaries
    entries for marp-cli, tiptap, cap, etc.
  • .gitignore: ignore the .codex CLI marker.

e2e/tests/bedside-react.spec.js
  Adds the age→weight parity test: 3y APLS → 14 kg, 3y Best Guess →
  16 kg, weight field mirrors the estimator output.

e2e/tests/calculators-react.spec.js
  Adds BSA (20 kg, 110 cm → 0.782 m²), dose cap (15 kg × 100 mg/kg,
  max 500 mg → 500 mg capped), and GCS (15 → 10 when motor drops
  to 1) parity tests.

Client tsc -b + backend tsc --noEmit + vite build all clean.
Bundle 476.48 kB / 135.44 kB gzipped.

Co-Authored-By: Codex + vendor model Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 01:11:58 +02:00

90 lines
3.1 KiB
JSON

{
"name": "pediatric-ai-scribe",
"version": "6.35.0",
"description": "AI-powered pediatric clinical documentation platform",
"main": "dist/server.js",
"engines": {
"node": ">=20"
},
"scripts": {
"start": "node dist/server.js",
"prebuild": "rm -rf dist",
"build": "tsc",
"typecheck": "tsc --noEmit",
"verify": "npm run typecheck && npm test && npm run test:node && npm run lint:refs && npm run lint:dead && npm --prefix client run build",
"verify:full": "npm run verify && npm run e2e",
"dev": "ts-node-dev --respawn --transpile-only server.ts",
"test": "vitest run",
"test:node": "node --test test/",
"test:coverage": "vitest run --coverage",
"e2e": "./scripts/e2e.sh",
"lint:refs": "node scripts/lint-references.js",
"lint:dead": "knip --no-config-hints",
"maint:check": "node scripts/maintenance.js check",
"maint:reindex": "node scripts/maintenance.js reindex",
"migrate": "node-pg-migrate",
"migrate:up": "node-pg-migrate up",
"migrate:down": "node-pg-migrate down 1",
"migrate:status": "node -e \"const{Pool}=require('pg');const p=new Pool({connectionString:process.env.DATABASE_URL});p.query('SELECT id,name,run_on FROM pgmigrations ORDER BY id').then(r=>{console.table(r.rows);p.end();}).catch(e=>{console.error(e.message);process.exit(1);})\"",
"migrate:new": "node-pg-migrate create"
},
"dependencies": {
"@marp-team/marp-cli": "^4.3.1",
"@marp-team/marp-core": "^4.3.0",
"@tiptap/core": "^3.20.4",
"@tiptap/extension-color": "^3.20.4",
"@tiptap/extension-link": "^3.20.4",
"@tiptap/extension-text-align": "^3.20.4",
"@tiptap/extension-text-style": "^3.20.4",
"@tiptap/extension-underline": "^3.20.4",
"@tiptap/starter-kit": "^3.20.4",
"argon2": "^0.41.1",
"axios": "^1.7.7",
"bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.21.0",
"express-rate-limit": "^7.4.0",
"google-auth-library": "^9.15.1",
"helmet": "^8.0.0",
"jszip": "^3.10.1",
"jsonwebtoken": "^9.0.2",
"mammoth": "^1.8.0",
"multer": "^1.4.5-lts.1",
"node-pg-migrate": "^7.7.0",
"nodemailer": "^8.0.5",
"openai": "^4.73.0",
"openid-client": "^6.8.2",
"pdf-parse": "^1.1.1",
"pg": "^8.13.0",
"pptxgenjs": "^4.0.1",
"qrcode": "^1.5.4",
"speakeasy": "^2.0.0"
},
"optionalDependencies": {
"@aws-sdk/client-bedrock": "^3.700.0",
"@aws-sdk/client-bedrock-runtime": "^3.700.0",
"@aws-sdk/client-s3": "^3.700.0",
"@aws-sdk/client-transcribe-streaming": "^3.1017.0",
"@aws-sdk/s3-request-presigner": "^3.700.0",
"@google-cloud/vertexai": "^1.9.0"
},
"devDependencies": {
"@tsconfig/node20": "^20.1.9",
"@types/bcrypt": "^6.0.0",
"@types/cookie-parser": "^1.4.10",
"@types/cors": "^2.8.19",
"@types/express": "^4.17.25",
"@types/jsonwebtoken": "^9.0.10",
"@types/ms": "^2.1.0",
"@types/multer": "^2.1.0",
"@types/node": "^25.6.0",
"@vitest/coverage-v8": "^4.1.5",
"knip": "^6.6.2",
"ts-node-dev": "^2.0.0",
"typescript": "^6.0.3",
"vitest": "^4.1.5",
"zod": "^4.3.6"
}
}