@cosyte/mllp 0.0.1 → 0.0.2

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/dist/index.cjs CHANGED
@@ -27,13 +27,13 @@ var MllpFramingError = class _MllpFramingError extends Error {
27
27
  /**
28
28
  * Up to 64 bytes copied from around the anomaly.
29
29
  *
30
- * This is a **copied** Buffer — isolated from the source buffer so it remains
30
+ * This is a **copied** Buffer, isolated from the source buffer so it remains
31
31
  * valid after the underlying buffer is reused or overwritten.
32
32
  *
33
33
  * **PHI contract (MLLP-9):** the decoder only ever populates this with the single
34
34
  * framing-boundary byte that violated the frame structure (whose hex value the
35
- * `message` already discloses) — never a run of payload content bytes. For anomalies
36
- * whose fault is not a specific byte (`MLLP_FRAME_TOO_LARGE` — the accumulated size),
35
+ * `message` already discloses), never a run of payload content bytes. For anomalies
36
+ * whose fault is not a specific byte (`MLLP_FRAME_TOO_LARGE`, the accumulated size),
37
37
  * the snippet is **empty**: a payload slice on a public error field would leak a
38
38
  * field-body slice of clinical content. Callers constructing this directly are
39
39
  * responsible for the same discipline.
@@ -106,7 +106,7 @@ var FrameReader = class {
106
106
  _opts;
107
107
  _maxFrameSize;
108
108
  _state = "SCANNING_FOR_VT";
109
- /** Reusable accumulator buffer — grown by doubling as needed. */
109
+ /** Reusable accumulator buffer, grown by doubling as needed. */
110
110
  _accumulator = Buffer.allocUnsafe(INITIAL_ACCUMULATOR_SIZE);
111
111
  /** Number of payload bytes written to accumulator in current frame. */
112
112
  _writePos = 0;
@@ -118,7 +118,7 @@ var FrameReader = class {
118
118
  _wsCount = 0;
119
119
  /** Byte offset of the VT byte that started the current frame. */
120
120
  _frameStartOffset = 0;
121
- /** Per-frame warning accumulator — cleared after each _deliverFrame(). */
121
+ /** Per-frame warning accumulator, cleared after each _deliverFrame(). */
122
122
  _frameWarnings = [];
123
123
  /**
124
124
  * Construct a chunked MLLP frame reader.
@@ -242,7 +242,7 @@ var FrameReader = class {
242
242
  this._emitWarning(
243
243
  "MLLP_MISSING_LEADING_VT",
244
244
  this._byteOffset,
245
- `Missing leading VT (0x0B) \u2014 treating byte 0x${byte.toString(16).padStart(2, "0")} at offset ${this._byteOffset} as payload start`
245
+ `Missing leading VT (0x0B), treating byte 0x${byte.toString(16).padStart(2, "0")} at offset ${this._byteOffset} as payload start`
246
246
  );
247
247
  this._frameStartOffset = this._byteOffset;
248
248
  this._state = "READING_PAYLOAD";
@@ -487,8 +487,8 @@ var TlsTransport = class {
487
487
  this._socket.on("data", fn);
488
488
  }
489
489
  /**
490
- * See {@link Transport.onConnect}. Armed on `'secureConnect'` — the TLS
491
- * handshake-complete event — not the raw TCP `'connect'` event.
490
+ * See {@link Transport.onConnect}. Armed on `'secureConnect'`, the TLS
491
+ * handshake-complete event, not the raw TCP `'connect'` event.
492
492
  */
493
493
  onConnect(fn) {
494
494
  this._socket.removeAllListeners("secureConnect");
@@ -569,14 +569,14 @@ var Connection = class extends events.EventEmitter {
569
569
  _lastByteOutAt = null;
570
570
  /** Ring buffer: last MAX_WARNINGS entries (OBS-05). */
571
571
  _warningBuffer = [];
572
- /** Accurate total counts per code — unaffected by ring buffer truncation (OBS-05). */
572
+ /** Accurate total counts per code, unaffected by ring buffer truncation (OBS-05). */
573
573
  _warningsByCode = /* @__PURE__ */ new Map();
574
574
  /** Set to true once the ring buffer overflows (OBS-05). */
575
575
  _warningsTruncated = false;
576
576
  _onWarningFn = null;
577
577
  _drainPromise = null;
578
578
  /**
579
- * beforeClose hook — no-op default that resolves immediately.
579
+ * beforeClose hook, no-op default that resolves immediately.
580
580
  *
581
581
  * Phase 4 (Server) and Phase 5 (Client) override this instance property to
582
582
  * register ACK-drain and send-queue drain logic respectively (D-07/D-08).
@@ -760,7 +760,7 @@ var Connection = class extends events.EventEmitter {
760
760
  * Abruptly destroy the connection, discarding any pending writes.
761
761
  *
762
762
  * Transitions from any non-terminal state directly to `CLOSED` and calls
763
- * `transport.destroy(reason)`. Emits `'close'` event. Idempotent — safe to
763
+ * `transport.destroy(reason)`. Emits `'close'` event. Idempotent, safe to
764
764
  * call multiple times.
765
765
  *
766
766
  * @param reason - Optional error to propagate to the transport.
@@ -860,12 +860,12 @@ var Connection = class extends events.EventEmitter {
860
860
  * Node throws `ERR_UNHANDLED_ERROR` when `'error'` is emitted on an `EventEmitter` with no
861
861
  * listener. Every `'error'` emission in this class is reached from inside a transport callback
862
862
  * (the socket's `'data'`/`'error'` listener), so an unguarded emit would become an **uncaught
863
- * exception that kills the process** — the exact failure the containment above exists to
863
+ * exception that kills the process**, the exact failure the containment above exists to
864
864
  * prevent, merely relocated one frame up the stack.
865
865
  *
866
866
  * `Connection` is a public export and can legitimately be driven with no `'error'` listener
867
867
  * (`MllpServer` and `MllpClient` each attach one; a bare `Connection` need not). The connection
868
- * is still torn down and `'stateChange'`/`'close'` still fire, so a caller is never blind —
868
+ * is still torn down and `'stateChange'`/`'close'` still fire, so a caller is never blind,
869
869
  * they simply do not get the typed error object they never asked for. Mirrors
870
870
  * `MllpServer._emitErrorIfListened`.
871
871
  */
@@ -884,7 +884,7 @@ var Connection = class extends events.EventEmitter {
884
884
  * consumers keep the stable `code` and `byteOffset`), then **destroy this connection only**.
885
885
  *
886
886
  * Why destroy rather than resynchronize: once `push` has thrown, the reader's position within
887
- * the byte stream is no longer trustworthy — the next bytes could be the middle of a message.
887
+ * the byte stream is no longer trustworthy, the next bytes could be the middle of a message.
888
888
  * Guessing where the next frame starts is how a clinical message gets silently mis-split, so
889
889
  * the connection is dropped instead. A server drops that one peer and keeps serving everyone
890
890
  * else.
@@ -896,7 +896,7 @@ var Connection = class extends events.EventEmitter {
896
896
  * engine that is already unwell. A compatibility failure is not a network blip.
897
897
  *
898
898
  * If a peer's quirk is *expected* (trailing junk, keepalive bytes, a missing leading VT), the
899
- * decoder's tolerance opt-ins are the supported answer — they turn the throw into a warning.
899
+ * decoder's tolerance opt-ins are the supported answer, they turn the throw into a warning.
900
900
  */
901
901
  _onFatalFramingError(err) {
902
902
  if (this._state === "CLOSED") return;
@@ -910,13 +910,13 @@ var Connection = class extends events.EventEmitter {
910
910
  this.destroy(err);
911
911
  }
912
912
  /**
913
- * Backstop for a NON-framing throw escaping `FrameReader.push` — i.e. our own bug, or a
913
+ * Backstop for a NON-framing throw escaping `FrameReader.push`, i.e. our own bug, or a
914
914
  * subscriber's, rather than the peer's bytes.
915
915
  *
916
916
  * `_onFrameDecoded` already contains subscriber throws at the dispatch site, so this should be
917
917
  * unreachable. It exists because "unreachable" and "cannot kill the process from inside a
918
918
  * socket `'data'` handler" are different claims, and only the second one is safe to bet a
919
- * clinical interface on. Reported honestly as an internal receive error — never dressed up as
919
+ * clinical interface on. Reported honestly as an internal receive error, never dressed up as
920
920
  * a peer framing fault.
921
921
  */
922
922
  _onInternalReceiveError(err) {
@@ -992,9 +992,9 @@ var UNSAFE_FIELD_SEPARATORS = /* @__PURE__ */ new Set([
992
992
  SEGMENT_SEPARATOR_CR,
993
993
  SEGMENT_SEPARATOR_LF,
994
994
  11,
995
- // VT — MLLP start block
995
+ // VT, MLLP start block
996
996
  28
997
- // FS — MLLP end block
997
+ // FS, MLLP end block
998
998
  ]);
999
999
  function isMshSegmentAt(buf, i) {
1000
1000
  return i + 3 < buf.length && buf[i] === ASCII_M && buf[i + 1] === ASCII_S && buf[i + 2] === ASCII_H && !UNSAFE_FIELD_SEPARATORS.has(buf[i + 3]);
@@ -1227,13 +1227,13 @@ var MllpServer = class extends events.EventEmitter {
1227
1227
  _netServer;
1228
1228
  _connections = /* @__PURE__ */ new Set();
1229
1229
  _opts;
1230
- /** `true` when `ServerOptions.tls` is set — `_netServer` is actually a `tls.Server`. */
1230
+ /** `true` when `ServerOptions.tls` is set, `_netServer` is actually a `tls.Server`. */
1231
1231
  _isTls;
1232
1232
  _listening = false;
1233
- /** Phase 8 — single-flight guard: `true` while a `listen()` call is settling. */
1233
+ /** Phase 8, single-flight guard: `true` while a `listen()` call is settling. */
1234
1234
  _listenInFlight = false;
1235
1235
  /**
1236
- * Phase 8 — settle hook for an in-flight `listen()`. Non-null only while a
1236
+ * Phase 8, settle hook for an in-flight `listen()`. Non-null only while a
1237
1237
  * `listen()` is in flight; invoked by `close()` so a close racing startup
1238
1238
  * rejects the pending `listen()` (typed) instead of leaving it hung with
1239
1239
  * the single-flight guard stuck. Cleared on every settle path.
@@ -1243,7 +1243,7 @@ var MllpServer = class extends events.EventEmitter {
1243
1243
  _host = null;
1244
1244
  _acceptedTotal = 0;
1245
1245
  _closedTotal = 0;
1246
- /** Phase 8 — count of `'tlsClientError'` events since listen(). */
1246
+ /** Phase 8, count of `'tlsClientError'` events since listen(). */
1247
1247
  _tlsClientErrorsTotal = 0;
1248
1248
  /**
1249
1249
  * Construct an MLLP server. Created idle; call `listen()` (or use
@@ -1306,23 +1306,23 @@ var MllpServer = class extends events.EventEmitter {
1306
1306
  * `Object.freeze({ port: actualPort, host: actualHost })`.
1307
1307
  *
1308
1308
  * **Single-flight:** one `listen()` per server lifecycle at a time. A call
1309
- * while the server is already listening — or while another `listen()` is
1310
- * still in flight — rejects with a typed `MllpConnectionError` (concurrent
1309
+ * while the server is already listening, or while another `listen()` is
1310
+ * still in flight, rejects with a typed `MllpConnectionError` (concurrent
1311
1311
  * binds raced each other's post-bind safety checks). Call `close()` before
1312
1312
  * re-listening; sequential `listen()` → `close()` → `listen()` is fine.
1313
1313
  *
1314
1314
  * **`close()` during an in-flight `listen()`** rejects that `listen()` with
1315
1315
  * a typed `MllpConnectionError` (never a hang) and clears the single-flight
1316
- * guard — a subsequent `listen()` on the same server works. This makes
1316
+ * guard, a subsequent `listen()` on the same server works. This makes
1317
1317
  * `Symbol.asyncDispose` (which delegates to `close()`) safe even before a
1318
1318
  * `listen()` has settled. (Exception: `close({ signal })` with an
1319
- * already-aborted signal is a no-op AbortError rejection — the in-flight
1319
+ * already-aborted signal is a no-op AbortError rejection, the in-flight
1320
1320
  * `listen()` is left to settle on its own bind outcome; see `close()`.)
1321
1321
  *
1322
1322
  * @param port - TCP port to bind. Use `0` to let the OS assign an ephemeral port.
1323
1323
  * @param hostOrOpts - Host string or object with `host` and optional `signal`.
1324
1324
  * Default host: `'127.0.0.1'` (Phase 8 bind-safety hardening). Wildcard hosts
1325
- * are rejected unless `ServerOptions.allowWildcardBind: true` — literal
1325
+ * are rejected unless `ServerOptions.allowWildcardBind: true`, literal
1326
1326
  * spellings pre-bind, resolver-only shorthands post-bind via the
1327
1327
  * OS-normalized bound address.
1328
1328
  *
@@ -1342,7 +1342,7 @@ var MllpServer = class extends events.EventEmitter {
1342
1342
  if (this._listening || this._listenInFlight) {
1343
1343
  return Promise.reject(
1344
1344
  new MllpConnectionError(
1345
- this._listening ? "listen() rejected: server is already listening \u2014 call close() before re-listening" : "listen() rejected: another listen() is already in flight on this server",
1345
+ this._listening ? "listen() rejected: server is already listening, call close() before re-listening" : "listen() rejected: another listen() is already in flight on this server",
1346
1346
  {
1347
1347
  cause: new Error("listen already listening or in flight"),
1348
1348
  phase: "connect"
@@ -1353,7 +1353,7 @@ var MllpServer = class extends events.EventEmitter {
1353
1353
  if (isWildcardHost(host) && this._opts.allowWildcardBind !== true) {
1354
1354
  return Promise.reject(
1355
1355
  new MllpConnectionError(
1356
- `refusing to bind wildcard host '${host}' \u2014 set ServerOptions.allowWildcardBind: true to bind all interfaces`,
1356
+ `refusing to bind wildcard host '${host}', set ServerOptions.allowWildcardBind: true to bind all interfaces`,
1357
1357
  {
1358
1358
  cause: new Error("wildcard bind requires allowWildcardBind"),
1359
1359
  phase: "connect"
@@ -1432,7 +1432,7 @@ var MllpServer = class extends events.EventEmitter {
1432
1432
  {
1433
1433
  ok: false,
1434
1434
  error: new MllpConnectionError(
1435
- `refusing to bind wildcard host '${host}' (bound address '${actualHost}') \u2014 set ServerOptions.allowWildcardBind: true to bind all interfaces`,
1435
+ `refusing to bind wildcard host '${host}' (bound address '${actualHost}'), set ServerOptions.allowWildcardBind: true to bind all interfaces`,
1436
1436
  {
1437
1437
  cause: new Error("wildcard bind requires allowWildcardBind"),
1438
1438
  phase: "connect"
@@ -1459,7 +1459,7 @@ var MllpServer = class extends events.EventEmitter {
1459
1459
  }
1460
1460
  };
1461
1461
  const wildcardBound = isWildcardHost(actualHost);
1462
- const wildcardMessage = `MLLP server is bound to ALL network interfaces (host='${actualHost}') \u2014 set a specific bind address unless this is intentional.`;
1462
+ const wildcardMessage = `MLLP server is bound to ALL network interfaces (host='${actualHost}'), set a specific bind address unless this is intentional.`;
1463
1463
  if (wildcardBound) {
1464
1464
  process.emitWarning(wildcardMessage, { code: MLLP_BIND_ALL_INTERFACES });
1465
1465
  }
@@ -1488,18 +1488,18 @@ var MllpServer = class extends events.EventEmitter {
1488
1488
  * Stop accepting new connections and gracefully close all active connections.
1489
1489
  *
1490
1490
  * Sequence (D-06):
1491
- * 1. `net.Server.close()` — stops accepting new connections immediately
1491
+ * 1. `net.Server.close()`, stops accepting new connections immediately
1492
1492
  * 2. If `_connections` is empty: resolves immediately (no drain needed)
1493
- * 3. Calls `_drainAll(drainTimeoutMs)` — Promise.all + side-effect setTimeout
1493
+ * 3. Calls `_drainAll(drainTimeoutMs)`, Promise.all + side-effect setTimeout
1494
1494
  * that force-destroys stragglers after the drain window
1495
1495
  *
1496
1496
  * Calling `close()` while a `listen()` is still in flight proactively
1497
1497
  * settles that `listen()` with a typed `MllpConnectionError` rejection
1498
- * and clears the single-flight guard — the server is immediately
1498
+ * and clears the single-flight guard, the server is immediately
1499
1499
  * re-listenable. `Symbol.asyncDispose` (which delegates here) is
1500
1500
  * therefore safe before `listen()` settles. **Qualification:** a
1501
1501
  * `close({ signal })` whose signal is **already aborted** rejects
1502
- * immediately with `AbortError` and performs no work — it does NOT close
1502
+ * immediately with `AbortError` and performs no work, it does NOT close
1503
1503
  * the server and does NOT settle the in-flight `listen()`, which simply
1504
1504
  * continues and settles on its own bind outcome.
1505
1505
  *
@@ -1551,7 +1551,7 @@ var MllpServer = class extends events.EventEmitter {
1551
1551
  /**
1552
1552
  * Drain all active connections with a shared timeout.
1553
1553
  *
1554
- * Uses Promise.all (not Promise.race) for coordination — the timeout is a
1554
+ * Uses Promise.all (not Promise.race) for coordination, the timeout is a
1555
1555
  * side effect that calls `conn.destroy()` on stragglers after `drainTimeoutMs`.
1556
1556
  * Promise.all resolves when all `conn.close()` promises settle (which happens
1557
1557
  * because `conn.destroy()` transitions connections to CLOSED).
@@ -1574,7 +1574,7 @@ var MllpServer = class extends events.EventEmitter {
1574
1574
  }
1575
1575
  }
1576
1576
  /**
1577
- * Async disposal — delegates to `close()` for `await using` support.
1577
+ * Async disposal, delegates to `close()` for `await using` support.
1578
1578
  *
1579
1579
  * @example
1580
1580
  * ```typescript
@@ -1621,7 +1621,7 @@ var MllpServer = class extends events.EventEmitter {
1621
1621
  };
1622
1622
  }
1623
1623
  /**
1624
- * Emit on `'error'` only when a listener is attached — an unlistened
1624
+ * Emit on `'error'` only when a listener is attached, an unlistened
1625
1625
  * `EventEmitter` `'error'` emission throws (see the class JSDoc error
1626
1626
  * contract). The single guard shared by the optional-tap forwarding sites
1627
1627
  * in this class; the constructor's net.Server forwarder deliberately does
@@ -1631,7 +1631,7 @@ var MllpServer = class extends events.EventEmitter {
1631
1631
  /**
1632
1632
  * Emit a server event, containing a throwing subscriber.
1633
1633
  *
1634
- * Every event this server emits is reachable from a callback we do not own — the `net.Server`
1634
+ * Every event this server emits is reachable from a callback we do not own, the `net.Server`
1635
1635
  * `'connection'` listener, the `tls.Server` `'tlsClientError'` listener, a socket's `'data'`
1636
1636
  * listener (via `Connection`), or the `catch` block of a `void`-ed async ACK task. A throwing
1637
1637
  * subscriber would therefore unwind into that callback and kill the process (or reject a void-ed
@@ -1737,7 +1737,7 @@ var MllpServer = class extends events.EventEmitter {
1737
1737
  }
1738
1738
  /**
1739
1739
  * Extract a minimal, content-free peer-certificate summary (Phase 8, ATNA
1740
- * ITI-19 mutual authentication) — CN strings, expiry, and the verification
1740
+ * ITI-19 mutual authentication), CN strings, expiry, and the verification
1741
1741
  * outcome (`authorized`) only; never the full certificate object. Returns
1742
1742
  * `null` when no peer certificate was presented (e.g. `clientAuth: 'WANT'`
1743
1743
  * with no client cert).
@@ -1755,7 +1755,7 @@ var MllpServer = class extends events.EventEmitter {
1755
1755
  subjectCN: asCn(cert.subject?.CN),
1756
1756
  issuerCN: asCn(cert.issuer?.CN),
1757
1757
  validTo: cert.valid_to ?? null,
1758
- // Verification outcome — under 'WANT' a certificate can be present yet
1758
+ // Verification outcome, under 'WANT' a certificate can be present yet
1759
1759
  // UNVERIFIED (see PeerCertificateSummary.authorized JSDoc).
1760
1760
  authorized: socket.authorized === true
1761
1761
  });
@@ -1767,12 +1767,12 @@ var MllpServer = class extends events.EventEmitter {
1767
1767
  * then dispatches: resolve ⇒ `AA`; throw/reject ⇒ a negative ACK (`AE` by default,
1768
1768
  * `AR` via {@link MllpAckError}). A positive ACK can never precede a successful commit.
1769
1769
  *
1770
- * Without an `onMessage` handler, `'AA'` degrades to a **transport-accept** — `AA`
1770
+ * Without an `onMessage` handler, `'AA'` degrades to a **transport-accept**, `AA`
1771
1771
  * meaning "bytes received and framed", not "application-processed".
1772
1772
  *
1773
1773
  * A handler failure is **expected flow**, not a server error: it produces a negative
1774
1774
  * ACK and a `'nack'` event. The thrown error's message is never placed on the wire or
1775
- * in the event (it may carry PHI) — only the static `ackCode` and the inbound control
1775
+ * in the event (it may carry PHI), only the static `ackCode` and the inbound control
1776
1776
  * metadata reach the peer.
1777
1777
  */
1778
1778
  async _sendCommitAck(payload, meta, conn) {
@@ -1804,18 +1804,18 @@ var MllpServer = class extends events.EventEmitter {
1804
1804
  }
1805
1805
  /**
1806
1806
  * Resolve the auto-ACK code for a message the server would otherwise acknowledge
1807
- * **positively** (`AA`) — the no-handler transport-accept and the post-commit success
1807
+ * **positively** (`AA`), the no-handler transport-accept and the post-commit success
1808
1808
  * paths. Fail-safe: downgrade to `AE` and emit a PHI-safe `'nack'` whenever the message
1809
1809
  * cannot carry a correlatable positive ACK, so `AA` never names a control ID the sender
1810
1810
  * cannot match (→ timeout → resend → **duplicate clinical message**).
1811
1811
  *
1812
1812
  * Two independent disqualifiers, one from the bytes and one from the frame:
1813
1813
  *
1814
- * - **`rawAckUncorrelatable(payload)`** — no readable `MSH`, an empty MSH-10, or a
1814
+ * - **`rawAckUncorrelatable(payload)`**, no readable `MSH`, an empty MSH-10, or a
1815
1815
  * batch/concatenated-message shape. This is the SAME predicate `buildRawAck` enforces
1816
1816
  * on the wire; it is re-checked here so the downgrade is **observable** (a `'nack'`
1817
1817
  * event) rather than a silent code change inside the builder.
1818
- * - **`MLLP_TRAILING_BYTES`** in the frame's warnings — a mid-payload `VT` made the
1818
+ * - **`MLLP_TRAILING_BYTES`** in the frame's warnings, a mid-payload `VT` made the
1819
1819
  * decoder discard accumulated bytes and deliver only the fragment after it. The
1820
1820
  * clinical message was destroyed in transit, so even a fragment that happens to carry
1821
1821
  * a readable MSH must not be positively acknowledged. This condition is invisible to
@@ -1824,7 +1824,7 @@ var MllpServer = class extends events.EventEmitter {
1824
1824
  * accumulating the delivered frame, so it is frame-scoped: it names *this* payload's own
1825
1825
  * discard, never a neighbouring frame's trailing junk.
1826
1826
  *
1827
- * `'discarded-bytes'` takes precedence in the reason when both hold — it is the root cause.
1827
+ * `'discarded-bytes'` takes precedence in the reason when both hold, it is the root cause.
1828
1828
  */
1829
1829
  _resolveAutoAckPositive(payload, meta, conn) {
1830
1830
  const discarded = meta.warnings.some((w) => w.code === "MLLP_TRAILING_BYTES");
@@ -1859,7 +1859,7 @@ var MllpServer = class extends events.EventEmitter {
1859
1859
  /**
1860
1860
  * The custom-builder path for `autoAck: fn`. Awaits the builder and dispatches its
1861
1861
  * Buffer as the ACK; the caller owns MSA-1. A builder error is re-emitted as `'error'`
1862
- * on the connection — the server never crashes (D-04).
1862
+ * on the connection, the server never crashes (D-04).
1863
1863
  */
1864
1864
  async _sendCustomAck(fn, payload, meta, conn) {
1865
1865
  try {
@@ -1873,7 +1873,7 @@ var MllpServer = class extends events.EventEmitter {
1873
1873
  /**
1874
1874
  * Frame an ACK payload and write it to the connection. `Connection.send()` returns
1875
1875
  * `false` under backpressure (socket write buffer full); that drops the ACK and emits
1876
- * a `MllpConnectionError({ phase: 'send' })` on the connection (D-04) — the peer will
1876
+ * a `MllpConnectionError({ phase: 'send' })` on the connection (D-04), the peer will
1877
1877
  * time out waiting and may retry. The server never crashes.
1878
1878
  */
1879
1879
  _dispatchAck(conn, ackPayload) {
@@ -1938,7 +1938,7 @@ var Correlator = class {
1938
1938
  _sendSeq = 0;
1939
1939
  _queueBytes = 0;
1940
1940
  /**
1941
- * PLAN-06 — count of pending entries with `sentAt !== null` (D-26 / B-01).
1941
+ * PLAN-06, count of pending entries with `sentAt !== null` (D-26 / B-01).
1942
1942
  * Maintained at every site that mutates `entry.sentAt` or removes a
1943
1943
  * flushed entry: `markFlushed`, `remove`, `matchAck`, `expireDue`, `clear`.
1944
1944
  */
@@ -1974,7 +1974,7 @@ var Correlator = class {
1974
1974
  /**
1975
1975
  * Enqueue a new send awaiting its ACK. Returns the assigned
1976
1976
  * `correlationKey`, or `null` if `maxInFlight` is reached (caller awaits
1977
- * drain — PLAN-05's `pipeline:false`).
1977
+ * drain, PLAN-05's `pipeline:false`).
1978
1978
  */
1979
1979
  enqueue(frame, controlIdOrNull, resolve, reject) {
1980
1980
  if (this._pending.size >= this._opts.maxInFlight) return null;
@@ -1993,7 +1993,7 @@ var Correlator = class {
1993
1993
  return key;
1994
1994
  }
1995
1995
  /**
1996
- * Record write-flush timestamp (CLIENT-04 — clock starts at flush, NOT
1996
+ * Record write-flush timestamp (CLIENT-04, clock starts at flush, NOT
1997
1997
  * at `send()` call). No-op if key is unknown (e.g. removed by abort).
1998
1998
  */
1999
1999
  markFlushed(key, now) {
@@ -2063,7 +2063,7 @@ var Correlator = class {
2063
2063
  /**
2064
2064
  * Sweep live entries; expire those past `sentAt + ackTimeoutMs`.
2065
2065
  * Fires `onTimeout(entry, elapsedMs)`; entries move to graveyard (D-04).
2066
- * Driven externally by `MllpClient`'s periodic sweep tick — Correlator
2066
+ * Driven externally by `MllpClient`'s periodic sweep tick, Correlator
2067
2067
  * itself owns no timers (D-03).
2068
2068
  */
2069
2069
  expireDue(now) {
@@ -2086,7 +2086,7 @@ var Correlator = class {
2086
2086
  /**
2087
2087
  * Reject every live entry with `reason` (insertion order) and clear
2088
2088
  * the live store. Graveyard is left intact (ages out via lazy eviction).
2089
- * Used by FIFO reconnect-reject (D-07 — PLAN-04 wraps in MllpConnectionError)
2089
+ * Used by FIFO reconnect-reject (D-07, PLAN-04 wraps in MllpConnectionError)
2090
2090
  * and `MllpClient.close()` to cancel pending sends.
2091
2091
  */
2092
2092
  clear(reason) {
@@ -2267,7 +2267,7 @@ var MllpClient = class extends events.EventEmitter {
2267
2267
  /** 0-indexed attempt counter for the current reconnect cycle. */
2268
2268
  _attempt = 0;
2269
2269
  /**
2270
- * W-02 — total reconnect attempts since construction. Read by PLAN-06 for
2270
+ * W-02, total reconnect attempts since construction. Read by PLAN-06 for
2271
2271
  * `getStats().reconnectAttempts`. Incremented at the entry of every
2272
2272
  * `_handleDisconnect` invocation that proceeds to schedule a backoff.
2273
2273
  */
@@ -2289,7 +2289,7 @@ var MllpClient = class extends events.EventEmitter {
2289
2289
  _onBackpressure;
2290
2290
  /** Pipeline flag; default `true` (parallel up to highWaterMark). */
2291
2291
  _pipeline;
2292
- /** Dead-peer idle timer (Plan 05 — D-11). `null` when not armed. */
2292
+ /** Dead-peer idle timer (Plan 05, D-11). `null` when not armed. */
2293
2293
  _deadPeerTimer = null;
2294
2294
  /** True once the self-'ack' listener that resets the dead-peer timer
2295
2295
  * has been attached. Guards against duplicate listeners on reconnect. */
@@ -2303,13 +2303,13 @@ var MllpClient = class extends events.EventEmitter {
2303
2303
  /** Listener-removal handle for the abort listener bound in connect(). */
2304
2304
  _abortListener = null;
2305
2305
  /**
2306
- * Test-only seam — when set, `_beginReconnectAttempt` builds the new
2306
+ * Test-only seam, when set, `_beginReconnectAttempt` builds the new
2307
2307
  * Connection through this factory instead of opening a real net.Socket.
2308
2308
  *
2309
2309
  * @internal
2310
2310
  */
2311
2311
  _reconnectFactory = null;
2312
- // ── PLAN-06 — observability counters for getStats (OBS-01, D-26) ─────────
2312
+ // ── PLAN-06, observability counters for getStats (OBS-01, D-26) ─────────
2313
2313
  /** Total successful `conn.send()` flushes since construction. */
2314
2314
  _sentTotal = 0;
2315
2315
  /** Total ACKs resolved since construction. */
@@ -2363,9 +2363,9 @@ var MllpClient = class extends events.EventEmitter {
2363
2363
  return this._connection?.state ?? this._state;
2364
2364
  }
2365
2365
  /**
2366
- * Open a TCP (or TLS — Phase 8) connection to the configured `host:port`
2366
+ * Open a TCP (or TLS, Phase 8) connection to the configured `host:port`
2367
2367
  * and attach a Phase 3 {@link Connection} to it. Resolves once the FSM
2368
- * enters `CONNECTED` — for TLS, on `'secureConnect'` (handshake complete,
2368
+ * enters `CONNECTED`, for TLS, on `'secureConnect'` (handshake complete,
2369
2369
  * including certificate verification when it is on).
2370
2370
  *
2371
2371
  * Rejects with:
@@ -2385,11 +2385,11 @@ var MllpClient = class extends events.EventEmitter {
2385
2385
  *
2386
2386
  * **TLS 1.3 + mutual TLS caveat (RFC 8446 §4.4.2):** `connect()` resolving
2387
2387
  * does NOT guarantee that a `clientAuth: 'MUST'` server accepted your
2388
- * client certificate. Under TLS 1.3 the client's handshake — and its
2389
- * `'secureConnect'` — can complete before the server finishes validating
2388
+ * client certificate. Under TLS 1.3 the client's handshake, and its
2389
+ * `'secureConnect'`, can complete before the server finishes validating
2390
2390
  * the certificate; a rejection then surfaces moments later as a typed
2391
2391
  * post-connect error (`'error'` event with an `ERR_SSL_*`/alert cause,
2392
- * classified **permanent** — no auto-reconnect loop). ACK correlation via
2392
+ * classified **permanent**, no auto-reconnect loop). ACK correlation via
2393
2393
  * {@link MllpClient.send} remains the delivery guarantee: no send resolves
2394
2394
  * without its ACK, so a rejected session can never silently "deliver".
2395
2395
  *
@@ -2473,7 +2473,7 @@ var MllpClient = class extends events.EventEmitter {
2473
2473
  *
2474
2474
  * Plaintext (`ClientOptions.tls` unset): a `net.Socket` wrapped in
2475
2475
  * `NetTransport`. TLS (Phase 8): a `tls.TLSSocket` wrapped in
2476
- * `TlsTransport` — verification defaults **on**
2476
+ * `TlsTransport`, verification defaults **on**
2477
2477
  * (`rejectUnauthorized: !allowUnverified`), floor `minVersion: 'TLSv1.2'`
2478
2478
  * (the IHE ATNA ITI-19 BCP195 floor), `servername` defaulting to
2479
2479
  * `ClientOptions.host`.
@@ -2504,12 +2504,12 @@ var MllpClient = class extends events.EventEmitter {
2504
2504
  * Wrap a connect-phase socket error as `MllpConnectionError`, classifying
2505
2505
  * TLS failures (Phase 8) into the additive `connectionCause`:
2506
2506
  *
2507
- * - `'tls-verify'` — certificate-verification failures
2507
+ * - `'tls-verify'`, certificate-verification failures
2508
2508
  * ({@link isTlsVerificationErrorCode}).
2509
- * - `'tls-handshake'` — TLS-**protocol**-shaped failures only
2509
+ * - `'tls-handshake'`, TLS-**protocol**-shaped failures only
2510
2510
  * ({@link isTlsProtocolError}): `ERR_SSL_*`, `EPROTO`, OpenSSL
2511
2511
  * alert-bearing errors.
2512
- * - **No `connectionCause`** — pure TCP-level failures (`ECONNREFUSED`,
2512
+ * - **No `connectionCause`**, pure TCP-level failures (`ECONNREFUSED`,
2513
2513
  * `ETIMEDOUT`, …) even on a TLS-configured connection; these carry the
2514
2514
  * same shape as plaintext connect failures.
2515
2515
  */
@@ -2537,7 +2537,7 @@ var MllpClient = class extends events.EventEmitter {
2537
2537
  /**
2538
2538
  * Emit a client event, containing a throwing subscriber.
2539
2539
  *
2540
- * Every event this client emits is reached from a callback we do not own — a socket's
2540
+ * Every event this client emits is reached from a callback we do not own, a socket's
2541
2541
  * `'connect'`/`'secureConnect'`/`'data'`/`'error'` listener, or a backoff timer. A throwing
2542
2542
  * subscriber would unwind into it and kill the process, and on several paths it would also skip
2543
2543
  * the work queued after the emit (the `resolve()` of `connect()`, the backoff scheduling).
@@ -2551,7 +2551,7 @@ var MllpClient = class extends events.EventEmitter {
2551
2551
  }
2552
2552
  /**
2553
2553
  * Emit the per-connection insecure-TLS warning (Phase 8) when
2554
- * `tls.allowUnverified === true` — fires on EVERY successful
2554
+ * `tls.allowUnverified === true`, fires on EVERY successful
2555
2555
  * `secureConnect`, initial connect and every reconnect. Emits both a frozen
2556
2556
  * `'securityWarning'` event and `process.emitWarning`. No-op for plaintext
2557
2557
  * connections or when verification is on.
@@ -2560,7 +2560,7 @@ var MllpClient = class extends events.EventEmitter {
2560
2560
  const tlsOpt = this._opts.tls;
2561
2561
  if (tlsOpt === void 0 || tlsOpt === true) return;
2562
2562
  if (tlsOpt.allowUnverified !== true) return;
2563
- const message = "MLLP TLS certificate verification is DISABLED (allowUnverified: true) \u2014 this connection does not authenticate the peer.";
2563
+ const message = "MLLP TLS certificate verification is DISABLED (allowUnverified: true), this connection does not authenticate the peer.";
2564
2564
  const warning = Object.freeze({
2565
2565
  code: MLLP_TLS_VERIFY_DISABLED,
2566
2566
  message,
@@ -2574,7 +2574,7 @@ var MllpClient = class extends events.EventEmitter {
2574
2574
  /**
2575
2575
  * Wire a Connection's events through to this MllpClient. Every re-emitted
2576
2576
  * payload is `Object.freeze`'d before emission (D-25), even though the
2577
- * Connection layer already freezes — defense-in-depth, harmless on
2577
+ * Connection layer already freezes, defense-in-depth, harmless on
2578
2578
  * already-frozen objects.
2579
2579
  *
2580
2580
  * Builds the unified `Correlator` (D-03/A1) bound to this Connection and
@@ -2588,7 +2588,7 @@ var MllpClient = class extends events.EventEmitter {
2588
2588
  this._correlator = new Correlator({
2589
2589
  mode: this._correlateByControlId ? "controlId" : "fifo",
2590
2590
  ackTimeoutMs: this._ackTimeoutMs,
2591
- // Plan 05 — pipeline:false collapses the in-flight set to ≤1 (D-06).
2591
+ // Plan 05, pipeline:false collapses the in-flight set to ≤1 (D-06).
2592
2592
  maxInFlight: this._pipeline ? Number.POSITIVE_INFINITY : 1,
2593
2593
  onWarning: (code, ctx) => {
2594
2594
  this._aggregatedWarningsByCode[code] = (this._aggregatedWarningsByCode[code] ?? 0) + 1;
@@ -2687,7 +2687,7 @@ var MllpClient = class extends events.EventEmitter {
2687
2687
  }
2688
2688
  }
2689
2689
  /**
2690
- * Arm (or re-arm) the dead-peer idle timer (Plan 05 — CLIENT-08, D-11).
2690
+ * Arm (or re-arm) the dead-peer idle timer (Plan 05, CLIENT-08, D-11).
2691
2691
  * No-op when `deadPeerTimeoutMs` is unset.
2692
2692
  */
2693
2693
  _armDeadPeerTimer() {
@@ -2701,7 +2701,7 @@ var MllpClient = class extends events.EventEmitter {
2701
2701
  this._deadPeerTimer.unref();
2702
2702
  }
2703
2703
  /**
2704
- * Clear the dead-peer idle timer (Plan 05 — D-14 timer cleanup on
2704
+ * Clear the dead-peer idle timer (Plan 05, D-14 timer cleanup on
2705
2705
  * every transition out of CONNECTED).
2706
2706
  */
2707
2707
  _clearDeadPeerTimer() {
@@ -2711,13 +2711,13 @@ var MllpClient = class extends events.EventEmitter {
2711
2711
  }
2712
2712
  }
2713
2713
  /**
2714
- * Disconnect handler — Plan 04 reconnect FSM core.
2714
+ * Disconnect handler, Plan 04 reconnect FSM core.
2715
2715
  *
2716
2716
  * Implements:
2717
2717
  * - CLIENT-17 hybrid in-flight handling (D-08): controlId mode preserves
2718
2718
  * pending sends for resend; FIFO mode rejects in-flight with
2719
2719
  * `connectionCause: 'in-flight-orphan'` and queued with `'fifo-unsafe'`.
2720
- * - CLIENT-18 classifier-first (Composition A — D-16): permanent errors
2720
+ * - CLIENT-18 classifier-first (Composition A, D-16): permanent errors
2721
2721
  * transition straight to CLOSED without invoking `retryStrategy`.
2722
2722
  * - W-01 backoff-reset on recent success: first disconnect after a
2723
2723
  * successful ACK on the prior session resets `_attempt` to 0.
@@ -2725,7 +2725,7 @@ var MllpClient = class extends events.EventEmitter {
2725
2725
  * - D-15 frozen RetryContext + D-17 null-return halts.
2726
2726
  * - D-19 default exponential strategy.
2727
2727
  *
2728
- * Invoked from the SINGLE `_onStateChange` hook — no parallel listener
2728
+ * Invoked from the SINGLE `_onStateChange` hook, no parallel listener
2729
2729
  * (B-04). Idempotent across same-cycle re-entry: cycle-start flag
2730
2730
  * coordinates first-disconnect vs subsequent-within-cycle behavior.
2731
2731
  */
@@ -2914,7 +2914,7 @@ var MllpClient = class extends events.EventEmitter {
2914
2914
  this._reconnectCycleStartedAt = null;
2915
2915
  }
2916
2916
  /**
2917
- * Test seam — install a factory that produces the next reconnect Connection.
2917
+ * Test seam, install a factory that produces the next reconnect Connection.
2918
2918
  *
2919
2919
  * @internal
2920
2920
  */
@@ -2922,7 +2922,7 @@ var MllpClient = class extends events.EventEmitter {
2922
2922
  this._reconnectFactory = factory;
2923
2923
  }
2924
2924
  /**
2925
- * Test seam — capture or rebind the connect-signal mid-flight (W-07).
2925
+ * Test seam, capture or rebind the connect-signal mid-flight (W-07).
2926
2926
  *
2927
2927
  * @internal
2928
2928
  */
@@ -2952,7 +2952,7 @@ var MllpClient = class extends events.EventEmitter {
2952
2952
  * anchor and passes it to `matchAck` for keyed lookup.
2953
2953
  *
2954
2954
  * Called from the SINGLE `'message'` listener registered in `_attachConnection`.
2955
- * No parallel listener is registered — downstream plans extend at the named
2955
+ * No parallel listener is registered, downstream plans extend at the named
2956
2956
  * anchor (B-04).
2957
2957
  */
2958
2958
  _onAckPayload(ackPayload, byteOffset) {
@@ -2991,9 +2991,9 @@ var MllpClient = class extends events.EventEmitter {
2991
2991
  }
2992
2992
  /**
2993
2993
  * Emit a frozen `'drain'` event when the queue depth and bytes fall below
2994
- * both configured caps (Plan 05 — D-24). Called from `_onAckMatched`
2994
+ * both configured caps (Plan 05, D-24). Called from `_onAckMatched`
2995
2995
  * (every successful ACK) and from the Correlator's `onTimeout` callback
2996
- * (every expired send) — both code paths free a live-store slot.
2996
+ * (every expired send), both code paths free a live-store slot.
2997
2997
  */
2998
2998
  _maybeEmitDrain() {
2999
2999
  const corr = this._correlator;
@@ -3068,7 +3068,7 @@ var MllpClient = class extends events.EventEmitter {
3068
3068
  * ```
3069
3069
  *
3070
3070
  * @param payload Raw bytes; MLLP framing is added internally via `encodeFrame`.
3071
- * @param opts.signal AbortSignal — aborting cancels the ACK wait (CLIENT-11).
3071
+ * @param opts.signal AbortSignal, aborting cancels the ACK wait (CLIENT-11).
3072
3072
  */
3073
3073
  send(payload, opts) {
3074
3074
  const signal = opts?.signal;
@@ -3156,7 +3156,7 @@ var MllpClient = class extends events.EventEmitter {
3156
3156
  });
3157
3157
  }
3158
3158
  /**
3159
- * 'wait'-mode backpressure handler (Plan 05 — CLIENT-07/CLIENT-11).
3159
+ * 'wait'-mode backpressure handler (Plan 05, CLIENT-07/CLIENT-11).
3160
3160
  *
3161
3161
  * Awaits one of three terminating signals, in order:
3162
3162
  * - `'drain'` event → re-enter `send()` (the gate will now pass).
@@ -3218,7 +3218,7 @@ var MllpClient = class extends events.EventEmitter {
3218
3218
  this._clearDeadPeerTimer();
3219
3219
  }
3220
3220
  /**
3221
- * **Test seam** — attach an externally-built {@link Connection} directly,
3221
+ * **Test seam**, attach an externally-built {@link Connection} directly,
3222
3222
  * bypassing the `net.createConnection` + `NetTransport` path. Used by
3223
3223
  * lifecycle tests driving `InMemoryTransport.pair()` for determinism.
3224
3224
  *
@@ -3297,7 +3297,7 @@ var MllpClient = class extends events.EventEmitter {
3297
3297
  }
3298
3298
  }
3299
3299
  /**
3300
- * Abruptly destroy the client — force-transitions the underlying Connection
3300
+ * Abruptly destroy the client, force-transitions the underlying Connection
3301
3301
  * to `CLOSED` immediately. No-op if no Connection is attached. Idempotent.
3302
3302
  *
3303
3303
  * @example
@@ -3323,7 +3323,7 @@ var MllpClient = class extends events.EventEmitter {
3323
3323
  /**
3324
3324
  * Returns a JSON-serializable observability snapshot (OBS-01, D-26).
3325
3325
  *
3326
- * All fields are plain values — no Buffers, no class instances, no Maps,
3326
+ * All fields are plain values, no Buffers, no class instances, no Maps,
3327
3327
  * no circular refs. Safe to `JSON.stringify` directly.
3328
3328
  *
3329
3329
  * `inFlight` is the count of correlator entries with `sentAt !== null`
@@ -3367,7 +3367,7 @@ var MllpClient = class extends events.EventEmitter {
3367
3367
  };
3368
3368
  }
3369
3369
  /**
3370
- * Async disposal — delegates to {@link MllpClient.close} for `await using` support.
3370
+ * Async disposal, delegates to {@link MllpClient.close} for `await using` support.
3371
3371
  *
3372
3372
  * @example
3373
3373
  * ```typescript
@@ -3423,7 +3423,7 @@ async function createStarterClient(opts) {
3423
3423
  }
3424
3424
 
3425
3425
  // src/index.ts
3426
- var VERSION = "0.0.1";
3426
+ var VERSION = "0.0.2";
3427
3427
 
3428
3428
  exports.Connection = Connection;
3429
3429
  exports.FrameReader = FrameReader;