Repository navigation
HL7 v2 for Node.js and TypeScript. @cosyte/hl7 parses the messages hospital systems actually send,
vendor quirks included, and hands fields back by name (msg.patient?.mrn) rather than by position
(PID-3.1). It also builds messages and writes them back spec-clean.
npm install @cosyte/hl7@0.1.0Node.js 22 or newer. ESM and CommonJS, with type declarations. No runtime dependencies. MIT.
What 0.1 means
This is the first release whose public API we treat as settled: the exported functions, the message
and helper surfaces, and the warning and finding codes. Renaming a warning code is a breaking change.
While the package is below 1.0, a breaking change bumps the minor version (0.1 to 0.2) and is called
out in the changelog; a fix that changes no public value ships as a patch.
What you can build on
- One-line reads through named helpers (
msg.patient,msg.meta,msg.observations()), dot-paths
(msg.get("PID.5.1")) or structural traversal. - A lenient parser that tolerates what real feeds send and reports each deviation as a warning with a
stable code and a position, never the field's value. Four structural failures are fatal;
{ strict: true }turns every warning into an error for CI. - Eight built-in vendor profiles and
defineProfile()for your own senders. - Parse, modify and
toString()to emit spec-clean HL7, with escape sequences re-emitted byte for byte. parseStreamfor batch files too large to buffer.
What changed
- Five new typed builders:
buildOrm,buildSiu,buildMdm,buildDftandbuildVxu, plus
prior-identity content on the ADT builder for merges. - Typed message overlays.
msg.is("ADT^A01")answers at run time and narrows at compile time, so
the accessors after the check are scoped to that message type's published structure. - Opt-in structure validation.
validateMessageStructure(msg)checks segment order and counts
against HL7's published message structures, which the library now derives from HL7's
machine-readable definitions: 94 message and trigger-event pairs, up from 32. - Clinical status on the helpers. Observations and orders carry
resultStatus(OBX-11 and OBR-25,
classified by HL7's published tables), immunizations carryadministrationStatus, and medications
carryorderControlfrom ORC-1. - Allergies from
IAMas well asAL1, so an ADT^A60 no longer returns an empty list that reads
as "no allergies recorded". - Profiles can name fields on standard segments (
segmentOverrides: { PID: { fields: { siteMrn: 19 } } }), and a profile's field names are checked by the compiler. - Conformance profiles gain condition predicates, value sets bound to a coding system, declared
conformance levels, component rules, and theC(a/b)andBusages. - Schemas for
toJSON().emitMessageSchemaproduces the JSON Schema and Zod description of the
serialized message. - Dates. One conversion surface shared with the other @cosyte parsers (
toObject,toISO,
toDate); vendor date formats gain month names, AM/PM and 12-hour clocks; declared formats now
reach every datetime the library returns. - Segment names are matched regardless of case, so a sender shipping
pidno longer loses the segment.
Upgrading from 0.0.x
buildAdtrefuses a merge event with no prior identity. For the ten triggers whose published
structure requiresMRG(A40, A41, A42, A43, A44, A45, A47, A49, A50 and A51), it used to return a
message carrying aMISSING_EXPECTED_GROUPwarning; it now throws aTypeErrornaming the message
type and the member that would supply the segment. Pass the prior identity.msg.identityEvents()recognizes five more triggers, A45, A47, A49, A50 and A51, which used to
return an empty list.- An order-ambiguous slash date is refused instead of being read in US order. If you relied on
that default, declare it:parseHL7(raw, { dateFormats: ["MM/DD/YYYY"] }). dateFormatsis validated strictly: a format that constructed and never matched now throws where
you wrote it.- Conformance profiles: a usage paired with a cardinality the methodology disallows is refused when
the profile is defined;FindingCodegainsPROFILE_UNDECLARED_CONTENTandUsageCodegainsB
and the conditional form, so exhaustiveswitchstatements need new cases. msg.allergies()now also returns entries fromIAMsegments.Immunizationgains the requiredadministrationStatuskey, so code that buildsImmunization
objects by hand must supply it.
Not covered
- Network transport: MLLP framing is stripped on read, and sending or receiving over a socket belongs
to@cosyte/mllp. - Conversion to FHIR. That is
@cosyte/transform. - HL7 v3 and CDA: the parser reads v2 only. C-CDA documents are
@cosyte/ccda. - Exhaustive coded-value validation: the library validates structure, not every coded value against
every HL7 table.
Links
- Docs: https://docs.cosyte.com/hl7?utm_source=github&utm_medium=release&utm_campaign=cosyte-0-1-launch&utm_content=release-hl7
- Quickstart: https://docs.cosyte.com/hl7/quickstart?utm_source=github&utm_medium=release&utm_campaign=cosyte-0-1-launch&utm_content=release-hl7
- Source: https://github.com/cosyte/hl7
- npm: https://www.npmjs.com/package/@cosyte/hl7/v/0.1.0
- Full changelog: https://github.com/cosyte/hl7/blob/main/CHANGELOG.md