FHIR

Read and write FHIR without losing a decimal.

@cosyte/fhir reads FHIR R4 JSON and XML into an immutable model and writes it back without dropping a trailing zero, a primitive extension or a status flag, then validates structure, cardinality and the profiles you supply. Its README lists exactly what is built and what is not yet.

@cosyte/fhir
npm install @cosyte/fhir

Need it integrated? Talk to us.

The standard

FHIR is HL7's resource-based standard, and US rules now require it.

  • FHIR is a standard for health care data exchange published by HL7. FHIR solutions are built from modular components called resources. Source: HL7 FHIR specification, summary
  • ONC's certification criterion (g)(10) requires certified health IT to answer requests for a single patient's data, and for multiple patients' data as a group, through a standardized FHIR API. It names the US Core Implementation Guide STU 6.1.0. Source: ONC test method, 170.315(g)(10)
  • US Core is based on FHIR R4 and defines the minimum constraints on FHIR resources that make up the US Core profiles. Source: HL7 US Core Implementation Guide
  • CMS-0057-F requires Medicare Advantage organizations, state Medicaid and CHIP fee-for-service programs, Medicaid managed care plans, CHIP managed care entities and Qualified Health Plan issuers on the Federally Facilitated Exchanges to implement FHIR APIs. Its Prior Authorization API must be implemented beginning January 1, 2027. Source: CMS fact sheet, CMS-0057-F

@cosyte/fhir

A no-data-loss core first, then validation in layers.

A FHIR document should come back out exactly as it went in, and a validator should say where a problem is without repeating the patient data that caused it. That is the order this toolkit was built in.

  • decimal and integer64 values are string-backed and never pass through a JavaScript number, so 0.010 stays 0.010.
  • A JSON codec and a zero-dependency XML codec over the same model. The XML reader refuses any DTD or non-predefined entity rather than resolving it.
  • Validation in layers: structure, cardinality, value domains, and the R4 base constraints of the eight resource types it models.
  • Profiles you supply, such as US Core, validated from their StructureDefinitions: slicing, fixed and pattern values, and FHIRPath invariants through a bounded subset.
  • Status, negation and unknown modifier extensions fail closed, so a record never reads as more certain than it is.
  • Bundles with transaction and batch semantics, reference resolution with a cycle guard, and Bulk Data NDJSON streaming with per-line error isolation.
  • Diagnostics shaped like OperationOutcome and free of values: a code and a location, never the value.
read-and-validate.tsts
import { parseResource, readObservationValue, validateResource } from "@cosyte/fhir";

const document = `{
  "resourceType": "Observation",
  "id": "syn-0001",
  "status": "final",
  "code": { "coding": [{ "system": "http://loinc.org", "code": "8480-6" }] },
  "subject": { "reference": "Patient/syn-0001" },
  "effectiveDateTime": "2026-01-05",
  "valueQuantity": {
    "value": 120.0,
    "unit": "mmHg",
    "system": "http://unitsofmeasure.org",
    "code": "mm[Hg]"
  }
}`;

const { resource, issues } = parseResource(document);

// The magnitude was written 120.0: the read keeps that exact form and says the protection mattered.
issues.map((issue) => issue.code); // => ["DECIMAL_PRECISION_AT_RISK"]

// Branch on the value[x] type before touching a magnitude, and compare on the UCUM code.
const reading = readObservationValue(resource);
reading?.type; // => "Quantity"
reading?.quantity?.value?.raw; // => "120.0"
reading?.quantity?.code; // => "mm[Hg]"

validateResource(resource).valid; // => true

From the @cosyte/fhir README on GitHub, verbatim. Every value in it is synthetic.

Limits

What it does not do.

Its README is specific about what is not built yet. The main points:

  • No typed per-resource models yet. The built-in structural schema covers the base elements and Patient; other resource types validate against a schema or profile you supply.
  • Slicing by type or profile discriminator, and reslicing, are not validated yet. They report PROFILE_SLICE_UNCHECKED.
  • No US Core package and no terminology content is bundled, so there is no value-set membership check without a terminology service you supply.
  • It never converts a unit and never evaluates a reference range.
  • FHIRPath is a bounded subset. An expression outside it reports INVARIANT_UNCHECKED instead of passing.
  • The XHTML inside a narrative is carried as a string, not validated. RDF and Turtle are out of scope.
  • Typed cross-format transcoding, emitting spec-clean JSON booleans and numbers from an XML-read model, is not done yet.

The full status and limits, in the README

Alternatives

What else you could use.

Each description comes from the project’s own documentation or npm listing, linked below.

Java library

HAPI FHIR

Describes itself as a complete implementation of the HL7 FHIR standard for healthcare interoperability in Java, under the Apache Software License 2.0. If your stack is on the JVM, look there first.

Source: HAPI FHIR

TypeScript library

Medplum JS client (@medplum/core)

A pure TypeScript library for calling a FHIR server, with FHIR validation and operations, FHIRPath evaluation and no external dependencies, under Apache-2.0. It includes an HTTP client, which @cosyte/fhir does not.

Source: npm, @medplum/core

JavaScript library

fhir-tool

An ISC-licensed library for handling FHIR resources: serialization between JSON and XML, validation and FHIRPath evaluation.

Source: npm, fhir-tool

JavaScript library

SMART on FHIR JavaScript client

A JavaScript library for connecting SMART apps to FHIR servers, in modern browsers and on Node 18 or later. Use it for the SMART launch and the server calls.

Source: SMART Health IT, client-js

TypeScript types

@types/fhir

Community-maintained TypeScript type definitions for FHIR. Types check your code at compile time; they do not parse or validate a document at run time.

Source: npm, @types/fhir

Converter

Microsoft FHIR Converter

Converts HL7 v2, C-CDA, JSON and FHIR STU3 data to FHIR R4 with Liquid templates, through the $convert-data operation of Azure's FHIR service.

Source: Microsoft Learn, $convert-data

Works with

  • @cosyte/transformMaps HL7 v2 messages to FHIR R4 resources. Its README publishes measured conformance against R4 and US Core, findings included.
  • Terminology@cosyte/terminology resolves code systems and translates codes through the ConceptMaps you supply.
  • De-identification@cosyte/deid applies a HIPAA Safe Harbor policy to a FHIR R4 resource.
  • @cosyte/synthGenerates spec-clean synthetic FHIR R4 and US Core resources and Bundles for your tests.

Try @cosyte/fhir on your own messages.

It is free and MIT-licensed. If it saves you a day, a star on GitHub helps other engineers find it.

Need it integrated? Talk to us, or see what our integration services cover.