@cosyte/mllp 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +80 -0
- package/README.md +21 -5
- package/dist/ack-from-hl7/index.cjs +1 -1
- package/dist/ack-from-hl7/index.cjs.map +1 -1
- package/dist/ack-from-hl7/index.d.cts +4 -5
- package/dist/ack-from-hl7/index.d.ts +4 -5
- package/dist/ack-from-hl7/index.mjs +1 -1
- package/dist/ack-from-hl7/index.mjs.map +1 -1
- package/dist/{index-DAZ4BvJE.d.cts → index-CD8V2Mtk.d.cts} +1 -1
- package/dist/{index-DAZ4BvJE.d.ts → index-CD8V2Mtk.d.ts} +1 -1
- package/dist/index.cjs +92 -103
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +216 -234
- package/dist/index.d.ts +216 -234
- package/dist/index.mjs +92 -103
- package/dist/index.mjs.map +1 -1
- package/dist/testing/index.d.cts +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,38 @@ begins its public history at `0.0.x`, per the cosyte version ladder (`0.0.x` unt
|
|
|
14
14
|
|
|
15
15
|
### Added
|
|
16
16
|
|
|
17
|
+
- **Public-surface gate (`scripts/check-no-internal-refs.sh`, `pnpm check:no-internal-refs`, and
|
|
18
|
+
`.github/workflows/no-internal-refs.yml`, check-run context `no-internal-refs`).** Enforces the
|
|
19
|
+
founder directive of 2026-07-27 (meta-repo `documentation/conventions.md`, "No internal project
|
|
20
|
+
bookkeeping on a public surface"): a consumer surface says what the software does and what
|
|
21
|
+
changed, never our item identifiers, phase and plan language, ADR numbers, meta-repo paths or
|
|
22
|
+
process commentary. `PUBLIC-SURFACE-HYGIENE`.
|
|
23
|
+
Ported from `ncpdp`'s copy rather than `hl7`'s, which carries three fixes the original lacks
|
|
24
|
+
(the `src/` string-literal fourth pass, the plural `phases?` stem, and `/` in the ADR separator
|
|
25
|
+
class), plus rule 7 (prose roadmap citation) from `cli`, the only sibling that has it.
|
|
26
|
+
**The recorded figure for this repo was "mllp 4" and was wrong by two orders of magnitude.**
|
|
27
|
+
Measured on the base commit `a34998a` with the final rule set, over four surfaces: public
|
|
28
|
+
markdown + npm metadata **4**, `src/` doc comments **389 rows / 376 locations across 18 of the
|
|
29
|
+
29 tracked source files the gate scans**, `src/` string literals **0**, and the built
|
|
30
|
+
declarations **440 rows across all eight `.d.ts`/`.d.cts` files** of the three published entry
|
|
31
|
+
points plus the shared type chunk. All four are now **0**, re-derived on both trees after the
|
|
32
|
+
rule set was final. The "4" was the public-markdown surface alone.
|
|
33
|
+
Three rule additions are this repo's own, each forced by a measured false positive rather than
|
|
34
|
+
by taste: a repo-local identifier vocabulary (`PLAN`/`CLIENT`/`SERVER`/`FRAME`/`LIFE`/`OBS`/
|
|
35
|
+
`WARN`/`ERR`/`SC` plus the single-letter `D`/`W`/`B`/`T` decision labels) that no sibling has
|
|
36
|
+
and that was the overwhelming majority of the mass; a compound-adjective guard on the phase
|
|
37
|
+
rule, because `two-phase` (HL7 enhanced acknowledgement mode) and `connect-phase` are ordinary
|
|
38
|
+
vocabulary; and `where|are|was|were|during|at` on the ordinary-English lookahead, because
|
|
39
|
+
`ConnectionErrorPhase` is a **published** API field whose own doc comment reads "phase where
|
|
40
|
+
the error occurred".
|
|
41
|
+
A **scanner-blindness self-test** refuses the run if the `grep` on `PATH` silently skips a file
|
|
42
|
+
(the `-I` / `--ignore-files` behaviour of `ugrep` and of any wrapper forcing them), which is the
|
|
43
|
+
fourth distinct mechanism by which gates of this family have reported OK over live violations.
|
|
44
|
+
**Each surface figure above counts rows these seven rules match**, which is not the same as a
|
|
45
|
+
claim that no internal reference of any kind survives. The gate reads this repository's sources
|
|
46
|
+
and published docs; it does not read the built declarations it protects, and no rule detects
|
|
47
|
+
prose that merely describes how the software came to exist.
|
|
48
|
+
|
|
17
49
|
- **Em-dash brand gate (`scripts/check-no-emdash.sh`, `pnpm check:no-emdash`, and
|
|
18
50
|
`.github/workflows/no-emdash.yml`).** Enforces the founder directive that bans `U+2014`
|
|
19
51
|
outright (`knowledgebase/06-brand/voice-and-tone.md`: "No em dashes. Ever."), which names
|
|
@@ -78,6 +110,26 @@ begins its public history at `0.0.x`, per the cosyte version ladder (`0.0.x` unt
|
|
|
78
110
|
`InMemoryTransport.pair()`; the receive example's fictional `respond`/`buildAck` → the real
|
|
79
111
|
`createServer({ onMessage })`). Bumps the `@cosyte/vitest-config` devDependency to `^0.0.2` for the
|
|
80
112
|
`/snippets` export. Docs and tests only: no runtime or public-API change.
|
|
113
|
+
- **README header swapped from the per-package banner to the shared Cosyte lockup.** Both sides of
|
|
114
|
+
this swap happened inside one unreleased window, so no published version carries the banner and
|
|
115
|
+
the release notes for this version describe only the lockup. It is recorded here, where build
|
|
116
|
+
history belongs, rather than dropped. The banner
|
|
117
|
+
(`cosyte-banner-mllp-1200x300.png`) baked the package name and its one line summary into the
|
|
118
|
+
artwork, and the `# @cosyte/mllp` H1 and the blockquote directly beneath it repeat both, so the
|
|
119
|
+
same two strings appeared three times in the first four lines of the page. The header is now a
|
|
120
|
+
`<picture>` carrying the theme-aware Cosyte lockup tile (`cosyte-lockup-tile-on-dark-1200x300.png`
|
|
121
|
+
and its `-on-light` counterpart), which reads "Cosyte" rather than the package name, so the
|
|
122
|
+
duplication goes and the heading stays untouched. The `<picture>` element was deliberately avoided
|
|
123
|
+
when the banner landed, on the grounds that npm sanitizer behaviour was unverified; that has since
|
|
124
|
+
been verified rather than assumed. On GitHub in dark mode `currentSrc` resolves to the on-dark tile
|
|
125
|
+
with parent element `PICTURE`, and on npm the `<img>` is hoisted out of the `<picture>` by GitHub's
|
|
126
|
+
anchor wrapper so the light fallback renders, which is the correct cut there because npmjs.com has
|
|
127
|
+
no dark mode. The block was copied programmatically out of `hl7`'s README rather than retyped, and
|
|
128
|
+
both URLs were fetched live (`200 image/png`) rather than trusted from the stored
|
|
129
|
+
`published-urls.json` declaration, since a typo in either is a 404 on a public package page. The
|
|
130
|
+
alt text now describes the artwork rather than the package, because a screen reader on the npm page
|
|
131
|
+
should hear what the image is and the package summary is already the next line. Docs only: no
|
|
132
|
+
runtime or public-API change.
|
|
81
133
|
- **`docs-content/installation.md` publish-status note corrected (README-ORG-SWEEP).** The Status
|
|
82
134
|
callout said the package was "not yet published to npm" and that the install command was "the shape
|
|
83
135
|
it will take at first publish": stale now that `@cosyte/mllp` is published on npm at `0.0.1` and
|
|
@@ -87,6 +139,34 @@ begins its public history at `0.0.x`, per the cosyte version ladder (`0.0.x` unt
|
|
|
87
139
|
|
|
88
140
|
### Fixed
|
|
89
141
|
|
|
142
|
+
- **Three doc comments that had outlived the code they described**, all of which shipped into the
|
|
143
|
+
published type declarations. The `'reconnecting'` payload was documented as carrying
|
|
144
|
+
`connectionId` only, while `MllpClient` populates `attempt` and `delayMs` when it schedules a
|
|
145
|
+
reconnect; a bare `Connection` does emit `connectionId` alone, which is why the false sentence
|
|
146
|
+
was CUT rather than replaced with a blanket promise. `MllpServer.getStats()` was documented as
|
|
147
|
+
returning 0 for `totalBytesIn`/`totalBytesOut`, which it aggregates across live connections; and
|
|
148
|
+
`createStarterServer` was documented as a stub while being fully implemented. The `createClient`
|
|
149
|
+
examples also showed `send()` commented out as not yet available. `PUBLIC-SURFACE-HYGIENE`.
|
|
150
|
+
|
|
151
|
+
- **`docs-content/installation.md` said the package is published at `0.0.1`.** It was `0.0.2`,
|
|
152
|
+
verified against the registry. The number is now gone from that status line rather than
|
|
153
|
+
corrected: a pinned version on a live page has a one-release half-life, and the changeset in this
|
|
154
|
+
very change bumps the package again, so writing today's number back would have reproduced the
|
|
155
|
+
defect. The ladder statement beside it already tells a reader what they need. A stale claim on a
|
|
156
|
+
page published to docs.cosyte.com, and a reminder that no pattern finds a statement that was true
|
|
157
|
+
when it was written. `PUBLIC-SURFACE-HYGIENE`.
|
|
158
|
+
|
|
159
|
+
- **`Connection.beforeClose` no longer claims the server and client register drain logic through
|
|
160
|
+
it.** They do not: `MllpServer` assigns an explicit no-op and `MllpClient` never assigns the hook
|
|
161
|
+
at all, and its `close()` REJECTS pending sends rather than draining them. The doc now describes
|
|
162
|
+
the hook as what it is: a replaceable pre-close step, promising no drain. **The falsehood is older
|
|
163
|
+
than this change** (it read as a phase-labelled plan before), but stripping the phase label turned
|
|
164
|
+
a plan into a flat present-tense assertion about two exported classes, which is worse; a refuter
|
|
165
|
+
caught it. On a healthcare transport the difference matters, because it told a consumer `close()`
|
|
166
|
+
drains in-flight ACKs. Fixed alongside it, and PRE-EXISTING: a missing separator between an
|
|
167
|
+
internal design label and the following clause on the exported `isTransientConnectionError` JSDoc,
|
|
168
|
+
which left a malformed sentence in the shipped declarations. `PUBLIC-SURFACE-HYGIENE`.
|
|
169
|
+
|
|
90
170
|
- **`ack-from-hl7`: a non-text `encoding` override is now rejected on a `Buffer` inbound too, not just
|
|
91
171
|
the text path, and this fixes a flaky `verify` failure (MLLP-ACK-NONTEXT-CODEC-BUFFER).**
|
|
92
172
|
MLLP-ACK-NONTEXT-CODEC-FRAME (below) spared the `Buffer` path on the belief that a lossy `Buffer`
|
package/README.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
<picture>
|
|
2
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://cosyte.com/tile/cosyte-lockup-tile-on-dark-1200x300.png">
|
|
3
|
+
<img alt="Cosyte: a plus mark set in two overlapping rounded squares, one solid and one outlined, beside the Cosyte wordmark" src="https://cosyte.com/tile/cosyte-lockup-tile-on-light-1200x300.png">
|
|
4
|
+
</picture>
|
|
5
|
+
|
|
1
6
|
# @cosyte/mllp
|
|
2
7
|
|
|
3
8
|
> Send and receive HL7 v2 over a production-grade MLLP connection in a few lines, with framing, ACK correlation, auto-reconnect, and backpressure handled for you.
|
|
@@ -23,8 +28,15 @@ pnpm add @cosyte/mllp
|
|
|
23
28
|
```ts
|
|
24
29
|
import { createStarterServer } from "@cosyte/mllp";
|
|
25
30
|
|
|
26
|
-
//
|
|
27
|
-
|
|
31
|
+
// Auto-ACK is on by default: the server awaits your handler (the durable-commit
|
|
32
|
+
// step) before it answers, so a positive ACK can never precede the commit.
|
|
33
|
+
// A throw answers a negative ACK instead.
|
|
34
|
+
const server = await createStarterServer({
|
|
35
|
+
port: 2575,
|
|
36
|
+
onMessage: async (payload) => {
|
|
37
|
+
await db.commit(payload);
|
|
38
|
+
},
|
|
39
|
+
});
|
|
28
40
|
```
|
|
29
41
|
|
|
30
42
|
```ts
|
|
@@ -48,7 +60,7 @@ const server = createServer({ tls: { cert: certPem, key: keyPem } });
|
|
|
48
60
|
await server.listen(2575, "127.0.0.1");
|
|
49
61
|
|
|
50
62
|
// Server: mutual TLS (ATNA ITI-19)
|
|
51
|
-
const
|
|
63
|
+
const mutualTlsServer = createServer({
|
|
52
64
|
tls: { cert: certPem, key: keyPem, ca: clientCaPem, clientAuth: "MUST" },
|
|
53
65
|
});
|
|
54
66
|
```
|
|
@@ -58,7 +70,7 @@ const server = createServer({
|
|
|
58
70
|
const client = createClient({ host: "mllp.example.com", port: 2575, tls: { ca: caPem } });
|
|
59
71
|
|
|
60
72
|
// Client: mutual TLS
|
|
61
|
-
const
|
|
73
|
+
const mutualTlsClient = createClient({
|
|
62
74
|
host: "mllp.example.com",
|
|
63
75
|
port: 2575,
|
|
64
76
|
tls: { ca: caPem, cert: clientCertPem, key: clientKeyPem },
|
|
@@ -84,7 +96,11 @@ const server = createServer({
|
|
|
84
96
|
});
|
|
85
97
|
```
|
|
86
98
|
|
|
87
|
-
Handler resolves ⇒ `AA
|
|
99
|
+
Handler resolves ⇒ `AA`, **unless the inbound could not carry a correlatable positive ACK** (no
|
|
100
|
+
readable `MSH`, an empty `MSH-10`, a batch or concatenated payload, or trailing bytes the framer
|
|
101
|
+
discarded). In that case the commit still happened, but the ACK is downgraded to `AE` and a `nack`
|
|
102
|
+
event names the reason, because a positive ACK the sender cannot match is one it will resend.
|
|
103
|
+
Handler throws ⇒ `AE` (or `AR` via `MllpAckError`). **A positive ACK cannot
|
|
88
104
|
precede a successful commit.** `autoAck: 'AA'` *without* a handler is documented as a
|
|
89
105
|
transport-accept: "received and framed", not "processed".
|
|
90
106
|
|
|
@@ -25,7 +25,7 @@ var MllpFramingError = class _MllpFramingError extends Error {
|
|
|
25
25
|
* This is a **copied** Buffer, isolated from the source buffer so it remains
|
|
26
26
|
* valid after the underlying buffer is reused or overwritten.
|
|
27
27
|
*
|
|
28
|
-
* **PHI contract
|
|
28
|
+
* **PHI contract:** the decoder only ever populates this with the single
|
|
29
29
|
* framing-boundary byte that violated the frame structure (whose hex value the
|
|
30
30
|
* `message` already discloses), never a run of payload content bytes. For anomalies
|
|
31
31
|
* whose fault is not a specific byte (`MLLP_FRAME_TOO_LARGE`, the accumulated size),
|