npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cosyte/transform

v0.0.9

Published

HL7 v2 → FHIR R4 transformation library for Node.js and TypeScript: IG-grounded, fail-safe, value-free diagnostics; never a confident wrong FHIR value.

Readme

@cosyte/transform

HL7 v2 → FHIR R4 transformation for Node.js and TypeScript: IG-grounded, fail-safe, value-free diagnostics; never a confident wrong FHIR value.

@cosyte/transform is the healthcare transformation layer of the cosyte suite. Unlike the parsers, it is a consumer: it takes already-parsed @cosyte/hl7 composites and produces validated @cosyte/fhir model nodes, grounded on the official HL7 Version 2 to FHIR Implementation Guide (hl7.fhir.uv.v2mappings).

Status: pre-alpha (0.0.x), published to npm. This release ships the six safety-critical datatype converters and the value-free diagnostic channel, the message-level assembly, HL7 v2 ADT → FHIR Patient + Encounter, the ORU^R01 → FHIR DiagnosticReport + Observation results graph, the order-entry graph (ORM_O01 / OML_O21 → ServiceRequest and RXO → MedicationRequest), the thin IG singles (VXU_V04 → Immunization, SIU_S12 → Appointment, MDM_T02 → DocumentReference), all via toFhir(msg), and terminology value translation of coded fields: route/site, appointment type, order priority, and substitution are now value-translated through their IG mappedVia ConceptMaps via toFhirCodeableConceptVia, fail-safe on any code the IG leaves unmapped. The v2→FHIR direction is feature-complete for the IG-covered message set; deeper terminology, profiles, and the reverse FHIR → v2 direction are not implemented.

Install

npm install @cosyte/transform @cosyte/hl7 @cosyte/fhir

@cosyte/hl7 and @cosyte/fhir are peer dependencies: the transform maps between the models they own. Its own third-party runtime dependencies are zero.

That command does not work yet. This package is published, but @cosyte/fhir is not on the registry, so npm fails with ERESOLVE and refuses to resolve that peer. Until it publishes, consume this package from source or a workspace link.

Convert a datatype

import { toFhirHumanName } from "@cosyte/transform";

const { value, issues } = toFhirHumanName({
  familyName: "Public",
  givenName: "Jane",
  nameTypeCode: "L", // HL7 Table 0200 "Legal name" → FHIR name-use "official"
});
// value: a FHIR HumanName node; issues: [] (clean, fully mapped)

Each converter returns { value, issues }: the FHIR datatype node it could faithfully produce, plus the value-free diagnostics it raised.

The fail-safe rule

Every conversion is grounded on the IG and refuses to guess. On any of these ambiguities:

  • a v2 timestamp with a time-of-day but no timezone (FHIR forbids time without a zone),
  • an assigning authority that can't be resolved to a system URI (never synthesized from a bare namespace, which would merge two patients),
  • a code with an unrecognized or absent coding system,
  • a unit that isn't valid UCUM (magnitudes are never converted),

the converter produces what it can (often reduced in precision) and raises a typed, value-free TransformIssue: a stable code, the v2 location, and the FHIR path, never a value. Render a list of issues as a FHIR OperationOutcome with toOperationOutcome(issues).

The six datatype converters

| Converter | v2 → FHIR | | ----------------------- | -------------------------- | | toFhirDateTime | DTM/TS → dateTime | | toFhirIdentifier | CX → Identifier | | toFhirCodeableConcept | CWE/CE → CodeableConcept | | toFhirHumanName | XPN → HumanName | | toFhirAddress | XAD → Address | | toFhirQuantity | NM + units → Quantity |

Assemble a message

toFhir(msg) takes a parsed @cosyte/hl7 ADT message and returns a FHIR R4 message Bundle: a MessageHeader, then the Patient and Encounter (and RelatedPerson) it describes, plus the value-free issues, each map grounded firsthand on the IG's segment/table ConceptMaps.

import { parseHL7 } from "@cosyte/hl7";
import { toFhir, createNamingSystem } from "@cosyte/transform";

const { bundle, issues } = toFhir(parseHL7(raw), {
  namingSystem: createNamingSystem({ authorities: { HOSP: "urn:oid:1.2.840.114350" } }),
});
// bundle.type === "message"; every reference resolves to a urn:uuid: fullUrl inside the bundle.

| Segment | FHIR resource | key maps | | ------- | --------------- | ------------------------------------------------------------------------ | | MSH | MessageHeader | MSH-9 → eventCoding; MSH-7/10 → Bundle.timestamp/.identifier | | PID | Patient | PID-3/5/7/8/11 → identifier/name/birthDate/gender/address | | PV1 | Encounter | PV1-2 → class/status (HL70004); PV1-19/44/45 → identifier/period | | NK1 | RelatedPerson | NK1-2/3/4 → name/relationship/address |

The fail-safe rule holds at the message level: an unmapped patient class, a naked timestamp, or an unresolvable authority becomes a typed issue, never a fabricated value. A trigger the IG has no message map for is assembled from the segment maps and flagged, never invented; every emitted resource is validated against @cosyte/fhir before it ships.

The same toFhir(msg) handles the other message families: ORU^R01DiagnosticReport (OBR) + Observation (OBX), and the order-entry graph, ORM_O01 / OML_O21 ORC/OBR → ServiceRequest and RXO (+ RXR route) → MedicationRequest, with ServiceRequest.status grounded on the HL70119 → request-status ConceptMap and withheld when it cannot be grounded, and a MedicationRequest whose IG-ungrounded status is the honest unknown rather than a guess. RXE has no STU1 IG map and is flagged, never assembled.

The thin single-trigger families complete the IG-covered message set: VXU_V04 RXA (+ RXR route, ORC) → Immunization (status via the IG's three conditioned rows: a delete action → entered-in-error, an unvalued RXA-20 → completed, else the HL70322 → event-status ConceptMap, with a valued-but-unmapped code withheld), SIU_S12 SCH/AIS/PID → Appointment (status via the HL70278 → appointmentstatus ConceptMap, the Patient wired as the required participant, its IG-unsourced required status a data-absent-reason primitive), and MDM_T02 TXA/OBX → DocumentReference (status grounded only for TXA-19 AVcurrent, the document body base64-encoded verbatim, carried and never interpreted). Timezone-naked instants are dropped and flagged, never assigned a fabricated UTC offset.

toFhirCodeableConceptVia(cwe, map) applies a license-clean IG value ConceptMap (transcribed and verified firsthand against the raw published IG JSON): RXR route/site (HL70162/HL70550), SCH-8 appointment type (HL70277), RXO-9 substitution (HL70161), and OBR-5 priority (HL70485), translating the source table code to its FHIR target coding, additively (the raw coding is preserved alongside the derived one). It is fail-safe by refusal: a code the IG map leaves in its (unmapped) group is flagged, never coerced to a neighbour. Fields whose IG target is SNOMED CT (RXR-4 method, SCH-7 reason) stay structural, because SNOMED is not bundled (BYO ConceptMap), and fields the IG ships no value map for (TXA-2 document type, RXA-5 vaccine code) are carried as-is, never invented.

License

MIT © Cosyte