diff --git a/package.json b/package.json index 2d8f20a..e3b0d18 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,10 @@ "name": "pediatric-ai-scribe", "version": "6.21.0", "description": "AI-powered pediatric clinical documentation platform", - "main": "server.js", + "main": "dist/server.js", "scripts": { - "start": "node server.js", + "start": "node dist/server.js", + "prebuild": "rm -rf dist", "build": "tsc", "typecheck": "tsc --noEmit", "dev": "ts-node-dev --respawn --transpile-only server.ts", diff --git a/server.js b/server.ts similarity index 100% rename from server.js rename to server.ts diff --git a/shared/types.ts b/shared/types.ts new file mode 100644 index 0000000..802b8e2 --- /dev/null +++ b/shared/types.ts @@ -0,0 +1,234 @@ +// ============================================================ +// SHARED TYPES — consumed by both server (src/routes/*.ts) and +// client (client/src/*). A response-shape change here breaks the +// build on both sides until they agree. +// +// This is the single most important file in the TypeScript +// migration. Three of the bugs we hit before this point were +// response-shape mismatches (refine returned `content` vs +// `refined`, sick-visit endpoint path mismatch, hospital-course +// key mismatch). Typing the wire protocol makes them compile-time +// errors. +// +// Keep this file strictly about wire protocol — no DB row shapes, +// no server-internal helpers. Anything that crosses the network. +// ============================================================ + +// ── Envelope ───────────────────────────────────────────────── +// Every route returns either `{success: true, ...extraFields}` or +// `{success: false, error: string}`. The generic `T` is the shape +// of the extra fields on success. Client code does: +// const r: ApiResponse = await fetch(...).then(r => r.json()); +// if (r.success) console.log(r.hpi); +// else showToast(r.error); +export interface ApiErr { + success: false; + error: string; +} +export type ApiResponse = ({ success: true } & T) | ApiErr; + +// Model tag accompanies every AI response — LiteLLM pass-through. +export interface WithModel { + model: string; +} + +// ── AI generation responses ────────────────────────────────── +// Keys match exactly what each route returns today. Do not rename +// without updating the server-side res.json() call in the same commit. + +// /api/generate-hpi-encounter +// /api/generate-hpi-dictation +export interface HpiOk extends WithModel { + hpi: string; +} + +// /api/generate-soap +export interface SoapOk extends WithModel { + soap: string; +} + +// /api/sick-visit/note (NOT /api/generate-sick-visit — that path does not exist) +// /api/well-visit/note +export interface VisitNoteOk extends WithModel { + note: string; +} + +// /api/generate-hospital-course +export interface HospitalCourseOk extends WithModel { + hospitalCourse: string; + format?: string; +} + +// /api/generate-chart-review +export interface ChartReviewOk extends WithModel { + review: string; +} + +// /api/generate-pe-narrative +export interface PeNarrativeOk extends WithModel { + narrative: string; + summary: { + normal: number; + abnormal: number; + notAssessed: number; + }; +} + +// /api/generate-milestone-narrative +export interface MilestoneNarrativeOk extends WithModel { + narrative: string; + summary: { + achieved: number; + notAchieved: number; + notAssessed: number; + }; +} + +// /api/generate-milestone-summary +export interface MilestoneSummaryOk extends WithModel { + summary: string; +} + +// /api/well-visit/shadess +export interface ShadessOk extends WithModel { + assessment: string; +} + +// /api/refine +export interface RefineOk extends WithModel { + refined: string; +} + +// /api/shorten (via refine.js router) +export interface ShortenOk extends WithModel { + shortened: string; +} + +// /api/clarify and /hospital-course/clarify +export interface ClarifyOk extends WithModel { + questions: string; +} + +// /api/suggest-billing-codes +export interface BillingCodesOk extends WithModel { + icd10: Array<{ code: string; description: string; reason?: string }>; + cpt: Array<{ code: string; description: string; reason?: string }>; +} + +// /api/transcribe +export interface TranscribeOk { + text: string; + provider: string; + duration: number; +} + +// /api/tts +export interface TtsOk { + audioBase64: string; +} + +// /api/models +export interface ModelsOk { + models: Array<{ id: string; label?: string }>; +} + +// ── Auth ───────────────────────────────────────────────────── +export interface AuthUser { + id: number; + email: string; + name: string; + role?: string; + isVerified?: boolean; + has2FA?: boolean; +} + +// /api/auth/login (two-phase: may also return requires2FA / needsVerification) +export interface LoginOk { + token: string; + user: AuthUser; + sessionId?: string; +} + +export interface LoginRequires2FA { + success: true; + requires2FA: true; +} + +export interface LoginNeedsVerification { + success: true; + needsVerification: true; +} + +// /api/auth/me +export interface MeOk { + user: AuthUser; +} + +// ── Sessions ───────────────────────────────────────────────── +export interface SessionRow { + id: string; + userAgent?: string; + ipAddress?: string; + createdAt: string; + lastUsedAt?: string; +} +export interface SessionsOk { + sessions: SessionRow[]; + currentSessionId: string | null; +} + +// ── Extensions (pagers/directory) ──────────────────────────── +export interface Extension { + id: number; + location: string; + name: string; + number: string; + type: 'extension' | 'pager'; + notes?: string; + deletedAt?: string | null; +} +export interface ExtensionsListOk { + items: Extension[]; +} + +// ── Memories (saved templates / style hints) ───────────────── +export interface Memory { + id: number; + category: string; + name: string; + content: string; +} +export interface MemoriesListOk { + items: Memory[]; +} + +// ── Learning hub ───────────────────────────────────────────── +export interface LearningContentItem { + id: number | string; + slug?: string; + title: string; + category?: string; + excerpt?: string; + body?: string; +} +export interface LearningFeedOk { + content: LearningContentItem[]; + total?: number; +} + +// ── Encounters (saved drafts) ──────────────────────────────── +export interface EncounterSummary { + id: number; + label: string; + type: 'encounter' | 'dictation' | 'hospital' | 'chart' | 'wellvisit' | 'sickvisit' | 'soap'; + createdAt: string; + updatedAt: string; +} +export interface EncountersListOk { + items: EncounterSummary[]; +} + +// ── Health ─────────────────────────────────────────────────── +export interface HealthOk { + ok: boolean; +} diff --git a/tsconfig.json b/tsconfig.json index bde40cd..0ecf971 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,6 +23,7 @@ } }, "include": [ + "server.ts", "server.js", "src/**/*.js", "src/**/*.ts",