Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/first-minor-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
"@cosyte/hl7": minor
---

**This is 0.1.0, the first release of `@cosyte/hl7` whose public API we treat as settled.**

What is covered, and what you can build against:

- Parsing HL7 v2 in one line with `parseHL7`: lenient by default, so the deviations real feeds carry
come back as stable warning codes rather than exceptions, with MLLP framing stripped, and a strict
mode for when you want a refusal instead. Batch files and multi-gigabyte streams (`parseStream`)
parse too.
- Reading without the spec: named helpers (`msg.patient`, `msg.visit`, `msg.observations()`,
`msg.allergies()`, `msg.medications()`, `msg.immunizations()` and more), dot-paths, and structural
traversal, with every datetime kept at the precision and zone it arrived with.
- Writing: `setField` and the segment methods mutate explicitly, the typed builders assemble ADT, ORM,
ORU, SIU, MDM, DFT and VXU messages, and the serializer always emits spec-clean HL7.
- Checking: conformance profiles you define and validate against, the opt-in
`validateMessageStructure` against HL7's published message structures, typed overlays that narrow
a message to its type, and JSON Schema and Zod emission for `toJSON()` output.

What the version promises. The exported functions, the message and helper surfaces, and the warning
and finding codes are the surface we keep stable: 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
this changelog; a fix that changes no public value ships as a patch. Upgrading from 0.0.10 is itself
breaking in a few places, each named in the entries below: `buildAdt` now refuses a merge trigger
with no prior identity, and several types and profile rules narrow.

What is not covered. There is no network transport: MLLP framing is stripped on read, and sending
or receiving over a socket belongs to `@cosyte/mllp`. The parser does not convert HL7 v2 to FHIR
(that is `@cosyte/transform`), it reads v2 only (not v3 or CDA), and it validates structure rather
than every coded value against every HL7 table.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1295,9 +1295,9 @@ What lands next starts as a quirk sighting or a real-world edge case on the [iss

### Out of scope (permanently)

- **MLLP framing / network transport**: a future `@cosyte/hl7-mllp` package will cover network IO; this library is parser-only.
- **Network transport**: sending and receiving over MLLP is [`@cosyte/mllp`](https://github.com/cosyte/mllp)'s job; this library is parser-only and only strips MLLP framing on read.
- **HL7 v3 and CDA**: different spec family entirely; not in our plans.
- **FHIR conversion**: a future companion package could bridge, but the conversion is non-trivial and deserves its own repo.
- **FHIR conversion**: [`@cosyte/transform`](https://github.com/cosyte/transform) converts a parsed message to FHIR R4; this library does not.
- **Exhaustive coded-value validation**: we validate structure, not every HL7 table. Integrate a domain validator (e.g. your LIS's internal code registry) for that.

---
Expand Down
15 changes: 8 additions & 7 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ Three runnable TypeScript scripts that demonstrate the one-line-extraction
value prop of `@cosyte/hl7`. Each example reads a synthetic HL7
fixture from `examples/data/`, calls the library, and prints labeled
human-readable output via `console.log`. Run them from the repo root with
`pnpm tsx examples/<file>.ts`, or run all three at once via
`pnpm examples` (wired by Plan 08-05; invokes `scripts/run-examples.ts`).
`pnpm tsx examples/<file>.ts`, or run all three at once with
`pnpm examples`, which runs `scripts/run-examples.ts` and fails if an
example exits non-zero or stops printing its expected output.

All three fixtures use synthetic patient identifiers only, no PHI.

## Files

| Example | Demonstrates | Run |
| --------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------- |
| `extract-patient-info.ts` (EX-01) | Named-helper access: `msg.patient` + `msg.meta` one-liners. | `pnpm tsx examples/extract-patient-info.ts` |
| `read-lab-results.ts` (EX-02) | Collection iteration: `msg.observations()` over an ORU^R01 with 3 OBXs. | `pnpm tsx examples/read-lab-results.ts` |
| `modify-and-resend.ts` (EX-03) | Mutation + round-trip: `msg.setField(...)` then `msg.toString()`. | `pnpm tsx examples/modify-and-resend.ts` |
| Example | Demonstrates | Run |
| ------------------------- | ----------------------------------------------------------------------- | ------------------------------------------- |
| `extract-patient-info.ts` | Named-helper access: `msg.patient` + `msg.meta` one-liners. | `pnpm tsx examples/extract-patient-info.ts` |
| `read-lab-results.ts` | Collection iteration: `msg.observations()` over an ORU^R01 with 3 OBXs. | `pnpm tsx examples/read-lab-results.ts` |
| `modify-and-resend.ts` | Mutation + round-trip: `msg.setField(...)` then `msg.toString()`. | `pnpm tsx examples/modify-and-resend.ts` |

## Fixtures (`examples/data/`)

Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@
"keywords": [
"hl7",
"hl7v2",
"hl7-v2",
"parser",
"builder",
"serializer",
"healthcare",
"interoperability",
"typescript",
"builder",
"serializer",
"adt",
"oru",
"mllp",
"toolkit"
],
"homepage": "https://github.com/cosyte/hl7#readme",
"homepage": "https://docs.cosyte.com/hl7",
"bugs": {
"url": "https://github.com/cosyte/hl7/issues"
},
Expand Down
12 changes: 8 additions & 4 deletions release/0.1.0-readiness.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ changeset in this queue was originally filed asking for `patch`, because the rep
contributor guidance told every contributor to pick `patch` while that ladder held. A queue
classified that way resolves to `0.0.11` no matter what is in it.

What is in it is not a `0.0.11`. Every declaration classified `minor` below adds behaviour a
consumer can call that did not exist before: five new typed message builders, conformance condition
What is in it is not a `0.0.11`. Every declaration classified `minor` below, except the release
statement `first-minor-release.md`, adds behaviour a consumer can call that did not exist before:
five new typed message builders, conformance condition
predicates, coding-system bindings on a value set, a declared profile conformance level, component
rules on a field rule, declared conditional usage with caller-supplied resolutions, a
message-structure registry derived from HL7's published structures instead of hand-transcribed,
Expand Down Expand Up @@ -57,8 +58,8 @@ queue is ready, not that the release may go out today.**

## Pending changesets

- pending: `33`
- minor: `18`
- pending: `34`
- minor: `19`

Every `.md` in `.changeset/` except Changesets' own `README.md` is a pending declaration and is
classified here, and every row here is a file in `.changeset/`; `config.json` is not a declaration.
Expand All @@ -73,6 +74,7 @@ read.
| `brave-comets-certify.md` | `patch` | Corrects release tooling only: it adds the readiness check and the public-export inventory, and it stops the contributor guidance instructing patch-only changesets. Nothing a consumer receives changes. |
| `brave-otters-recount.md` | `patch` | Corrects release tooling and this record: the counts and the break-candidate attributions stated here are recounted from `.changeset/` and `release/public-api.json` instead of read as prose, the inventory becomes a third input the check refuses rather than skips, and the record itself is re-derived from the tree. No export, type, parse behaviour, warning code or serialized byte moves. |
| `brave-turtles-describe.md` | `minor` | Adds schema emission for the serialized projection: `messageJsonSchema`, `messageZodSource`, `emitMessageSchema`, `isSchemaEmitTarget`, `SCHEMA_EMIT_TARGETS`, `SchemaTargetError`, `JSON_SCHEMA_DIALECT` and the `SchemaEmitTarget` / `JsonSchemaDocument` / `JsonSchemaNode` types. Both functions build a description and return it; nothing validates anything, the Zod artifact is source TEXT so no `zod` dependency is added at run time or in development, and the file states no existing export was removed, renamed or re-typed. |
| `first-minor-release.md` | `minor` | States what 0.1 means to someone using the package: what is covered and dependable, what the version promises below 1.0 (a breaking change bumps the minor and is called out in the changelog) and what is not covered. It adds no behaviour of its own; it carries `minor` as the class of the release it describes, which the other `minor` declarations already resolve to, so the target does not move. |
| `first-use-examples-executed.md` | `patch` | Corrects the documentation's first examples: the README usage example and the quickstart's first example now parse a committed synthetic fixture byte for byte, and the test suite reads both out of their pages and executes them against the package, asserting their printed and claimed values; the hand-kept copy of the README example under `examples/` is removed. No export, type, parse behaviour, warning code or serialized byte moves. |
| `great-moons-shave.md` | `patch` | Corrects the repository's own gate tooling only: the em-dash brand gate stops running this repository's copy of the scanner and runs the one shared implementation published in `@cosyte/script-utils`, the copy is deleted, and what the scan leaves out becomes a tracked declaration instead of two patterns inside the scanner. The package script keeps its name, its two modes and its exit codes, and the set of tracked files it reads was enumerated before and after and compared in both directions. The dependency is a devDependency, `dependencies` stays empty, and the published files, exports and types are untouched. |
| `great-otters-author.md` | `minor` | Adds five typed builders mirroring the read helpers, `buildOrm`, `buildSiu`, `buildMdm`, `buildDft` and `buildVxu`, plus `SUPPORTED_BUILDER_MESSAGES`, `supportsBuilderMessage` and `TYPED_BUILDER_COVERAGE`, and optional prior-identity content on the ADT typed init. The support claim is derived from the same published structures the parser checks against rather than asserted. The file names two behaviour changes of its own, both listed under Break candidates below. |
Expand Down Expand Up @@ -220,6 +222,8 @@ holds every name below to the pending queue.
with no published surface.
- `brave-turtles-describe.md` removes, renames and narrows nothing: emission is additive, and the
file states no existing export was removed, renamed or re-typed.
- `first-minor-release.md` removes, renames and narrows nothing: it is the release statement, and
it changes no export, type, parse behaviour, warning code or serialized byte.
- `first-use-examples-executed.md` removes, renames and narrows nothing: it changes the example
message two documentation pages print and adds tests that execute them; no export, type, parse
behaviour, warning code or serialized byte moves.
Expand Down
6 changes: 3 additions & 3 deletions scripts/run-examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* For each example, asserts the process exits 0 and stdout contains a
* known marker string. Exits non-zero if any example fails.
*
* Run from repo root (will be invoked by `pnpm examples` once Plan 08-05
* wires the script into `package.json`):
* Run from repo root, after `pnpm build` (the examples import the built
* package by name):
*
* pnpm tsx scripts/run-examples.ts
* pnpm examples
*
* Security note (Phase 8 threat T-08-01): filenames are passed as argv
* to spawnSync: they are NEVER concatenated into a shell template. Any
Expand Down
Loading