Skip to main content

fhir-dsl

Type-safe FHIR queries in TypeScript, with types generated straight from the official FHIR StructureDefinitions and any Implementation Guide you point it at.

What you get

  • Compile-time checked queries — resource types, search parameters, operators, includes, chained params, _has, composites, and profile fields are all narrowed by TypeScript before you ever hit the network.
  • A generator, not a schema download@fhir-dsl/cli emits real .ts files into your repo from FHIR R4/R4B/R5/R6 plus any hl7.fhir.* IG package; optional Standard Schema validators (zod or zero-dep native) come with the same flag.
  • A Kysely-style fluent builder — immutable, composable, with .include() / .revinclude() / .whereChained() / .has() / .transaction() / .batch() / .operation() plus $if / $call escape hatches.
  • Typed FHIRPath — proxy-based expression builder with autocomplete on every step, native UCUM-aware Quantity comparisons (5 'mg' = 0.005 'g' is true), setValue / createPatch write-back, and a synchronous resolver hook for terminology functions.
  • Unified error handling — every error in the monorepo extends FhirDslError with a kind discriminator, structured context, and toJSON() for transport-safe serialisation. A Result<T, E> + tryAsync toolkit gives Effect-style typed handling without try/catch.

Stability

v1.0.0 shipped on 2026-05-01. The public surface across all 10 packages is locked at the surface-v1.0.0 tag — minor releases add to it, patch releases fix bugs in it, breaking changes wait for v2. The CI gate (pnpm audit:export-surface:check) blocks accidental drift on every PR.

60 seconds in

import { createClient } from "./fhir/r4";

const fhir = createClient({
baseUrl: "https://hapi.fhir.org/baseR4",
});

const result = await fhir
.search("Patient")
.where("family", "eq", "Smith")
.where("birthdate", "ge", "1990-01-01")
.include("general-practitioner")
.sort("birthdate", "desc")
.count(10)
.execute();

// result.data: Patient[]
// result.included: (Practitioner | Organization)[]
// result.total?: number
for (const p of result.data) console.log(p.name?.[0]?.family);

The ./fhir/r4 import is produced by one CLI call — see Quick Start.

Next

  • Installation — packages, peer versions, and the full generate flag set.
  • Quick Start — under five minutes from install to typed response.
  • Core Concepts — how the schema, search-param discriminator, and profile narrowing thread together.
  • Error HandlingFhirDslError contract and the Result<T, E> toolkit.
  • FHIRPath + Query Builder — server-side _filter, post-fetch projection, write-back, terminology hooks, UCUM-aware Quantity comparisons.
  • Roadmap — what shipped on the v1.x line and what's queued for v2.