@cosyte/fhir

中文文档
0.1.8发布于 2026/11/10MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 3441

FHIR R4 for Node.js and TypeScript: a resource model that keeps every value exactly as written, JSON and XML codecs, layered validation, and a safety readout for status and negation.

原始使用文档
文档目录11 节
  1. Why this exists
  2. Status
  3. Install
  4. Usage
  5. API
  6. PHI and safety
  7. Documentation
  8. Support
  9. Security
  10. Contributing
  11. License
The Cosyte logo on its own white ground: the icon beside the word Cosyte.

@cosyte/fhir

Read real-world FHIR R4, keep every value exactly as it was written, and validate it against your profiles.

npm version CI License: MIT Node

FHIR R4 for Node.js and TypeScript: a resource model that keeps every value exactly as written, JSON and XML codecs, layered validation, and a safety readout for status and negation.

Why this exists

Reading FHIR correctly takes more than a JSON parse: a decimal written 0.010 has to stay 0.010, an integer64 has to keep every digit, and a status, a modifier, or a negation must never be skipped, because a missed refuted reads as its opposite. We built @cosyte/fhir for the engineer who reads FHIR R4 from a server or an EHR (the format ONC HTI-1 binds §170.315(g)(10) to, with US Core and SMART on FHIR) and has to get those values right without reading the specification first. Type definitions alone describe a resource's shape and check nothing at run time, and JSON.parse turns 0.010 into the number 0.01 and knows nothing about modifiers. This library reads, writes, and validates FHIR R4 with zero runtime dependencies, and tells you with a coded reason what it could not read safely.

Status

The 0.1 line. From 0.1 the public API is settled: the exported names, options, result shapes, and issue codes are the surface we keep stable. While the package is below 1.0, a breaking change ships in a minor version and is called out in the changelog. Upgrading from 0.0.10 changes verdicts: R4's own constraints are now evaluated with no profile supplied, so a document that read valid can read invalid. The changelog sets out each change.

What it covers, against FHIR R4 (4.0.1): reading and writing JSON and XML into one immutable model; validation in layers (structure, cardinality, value domains, R4's own constraints on the eight modeled resource types, Quantity and UCUM, binding strength, and profiles you supply or author with defineProfile, including their FHIRPath invariants); the readSafety and assertSafeToSummarize safety readout; and Bundles, references and streaming Bulk Data NDJSON. R5 and DSTU2 documents can be read, since the model is schema-free, but they are not validated against their own definitions.

Not covered yet: typed per-resource models (the built-in structural schemas cover the base elements plus the eight modeled resource types), type and profile slicing discriminators (reported PROFILE_SLICE_UNCHECKED, and the slices' own constraints are then not checked, since no occurrence is assigned to them), FHIRPath outside the supported subset (reported INVARIANT_UNCHECKED, never passed), bundled terminology or US Core content, spec-clean JSON written from a model read out of XML, unit conversion, and executing a transaction Bundle.

Install

# pnpm (recommended). Also works with: npm install @cosyte/fhir  |  yarn add @cosyte/fhir
pnpm add @cosyte/fhir

Node.js 22 or later, tested on 22, 24, and 26. The package ships dual ESM and CommonJS builds with type declarations for both, so import and require both work and neither needs a compatibility shim. There are zero runtime dependencies, and it imports no Node built-in.

Usage

Read a document, keep its exact values, and get a verdict. The Observation below is synthetic: every value in it is fabricated, and the same document is committed as a test fixture in this repository.

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

The quickstart on docs.cosyte.com/fhir walks the same document step by step, and examples/ holds four runnable programs: read and validate, the safety readout, JSON and XML, and Bundles with Bulk Data NDJSON.

API

Everything ships from one entry point; there are no subpath imports.

  • Read and write. parseResource and serializeResource for JSON, parseResourceXml and serializeResourceXml for XML, over one schema-free model, and nodesEquivalent to compare a model read from one format with a model read from the other. A decimal or an integer64 keeps its exact text (FhirDecimal, FhirInteger64) and never passes through a JavaScript number.
  • Validate. validateResource returns valid, the issues, and toOperationOutcome() to render them as an OperationOutcome. Pass the profiles you load with loadStructureDefinition or author with defineProfile, and a terminology service of your own for code validity.
  • Read status and negation. readSafety surfaces status, modifiers, and negations. assertSafeToSummarize throws FhirSafetyError, carrying locations only, when a resource holds something it cannot summarize honestly, such as a modifierExtension it does not understand.
  • Read measured values. readObservationValue branches on the value[x] type and keeps the UCUM code, and readMedicationDoses reads dose quantities. No unit is ever converted.
  • Bundles and NDJSON. readBundle tells a transaction (all or nothing) from a batch and executes neither, resolveReference resolves relative, absolute, logical, and #fragment references, and streamNdjson reads a Bulk Data export line by line, reporting a malformed line and carrying on.

PHI and safety

FHIR resources carry protected health information, so treat every document you hand this library as PHI.

  • It works in memory. It reads, validates, and writes in memory and nothing else. It opens no socket, writes nothing to disk, and fetches nothing at run time; it has zero runtime dependencies, imports no Node built-in, and calls no terminology service unless you pass one in.
  • Diagnostics carry no values. An issue is a code and a FHIRPath location, never the value it was raised over. A location can repeat an element name the document supplied when that name has the published form of a FHIR name, so treat a location as derived from the document.
  • The XML reader accepts plain XML only. Anything else is refused with a typed FhirXmlError that carries a code and an offset into the input string (in UTF-16 code units, not bytes), never a slice of the document. The reader performs no I/O and resolves no URI. The troubleshooting pages on docs.cosyte.com/fhir list each refusal and its code.
  • Nesting is bounded. Both readers stop at a fixed depth with a typed error, so a deeply nested document fails cleanly rather than exhausting the stack.
  • A status or a negation is not skipped silently. assertSafeToSummarize refuses a resource carrying a modifierExtension it does not understand, and each other shape it cannot summarize honestly, rather than letting a summary walk past it.
  • What you still own. Transport, storage, retention, access control, audit logging, and every log line your own code writes. This library makes no compliance claim on your behalf.

Documentation

  • docs.cosyte.com/fhir: installation, the quickstart, how-to guides, core concepts, current limits, troubleshooting, the API reference, and how we test the package and measure its performance.
  • documentation/capabilities.md: the full capability readout, layer by layer, with what each one checks and what it leaves open.
  • documentation/ in the repository: the capability readout, the FHIRPath coverage measured against the shared R4 conformance suite, and the architecture decisions.
  • CHANGELOG.md: every change, with the breaking ones called out.

Support

Bug reports, questions, and FHIR quirks from the servers and EHRs you connect to belong in GitHub issues, with a minimal reproduction that uses synthetic data only. Ideas and open questions can also go to Discussions. Our support page lists every route.

Need a FHIR R4 integration built, or hosted and run for you? See our integration services.

Security

Report a vulnerability privately, never in a public issue: through GitHub's private vulnerability reporting on this repository, or by email to [email protected]. Use synthetic data only. Our security policy says what is in scope and which versions we support.

Contributing

Pull requests are welcome; every fixture must be synthetic, never a real patient's data.

pnpm install
pnpm build       # dual ESM + CJS + .d.ts
pnpm typecheck
pnpm lint
pnpm test

Every meaningful change gets a changeset (pnpm changeset: minor for new capability or a breaking change while the version is below 1.0, patch for a fix), and its summary becomes the change's entry in CHANGELOG.md. See CONTRIBUTING.md.

License

MIT, copyright Cosyte LLC. See LICENSE. The names of the standards and code systems this package works with belong to their owners; see TRADEMARKS.md.

版本与发布记录

@cosyte/fhir 共发布 10 个版本,首次发布于 2026/08/27;过去 12 个月发布了 10 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.1.8latest2026/11/10今天
0.1.72026/11/092 天前
0.1.62026/11/082 天前
0.1.52026/11/082 天前
0.1.42026/11/082 天前
0.1.32026/11/082 天前

关于 @cosyte/fhir 的常见问题

@cosyte/fhir 是什么?

FHIR R4 for Node.js and TypeScript: a resource model that keeps every value exactly as written, JSON and XML codecs, layered validation, and a safety readout for status and negation.

如何安装 @cosyte/fhir?

在项目目录运行 npm install @cosyte/fhir,或使用 pnpm add / yarn add / bun add。

@cosyte/fhir 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cosyte/fhir 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@cosyte/fhir 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@cosyte/fhir 可以商用吗?

@cosyte/fhir 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@cosyte/fhir 的下载量有多少?

根据 npm 官方下载统计,@cosyte/fhir 在 2026/10/11 – 2026/11/09 这 30 天内被下载 3,441 次,日均约 115 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cosyte/fhir 还在维护吗?

最新版本 0.1.8 发布于 2026/11/10(今天);至今共发布 10 个版本,其中过去 12 个月发布了 10 个;首次发布于 2026/08/27。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。