@cosyte/mllp 0.0.4 → 0.0.6
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 +129 -0
- package/dist/ack-from-hl7/index.cjs.map +1 -1
- package/dist/ack-from-hl7/index.mjs.map +1 -1
- package/dist/index.cjs +53 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +132 -9
- package/dist/index.d.ts +132 -9
- package/dist/index.mjs +53 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -2007,8 +2007,8 @@ var Correlator = class {
|
|
|
2007
2007
|
* removed from live store. Caller calls `entry.resolve(ackPayload)`.
|
|
2008
2008
|
* - controlId: keyed lookup by `controlIdFromAck`. Live-store hit returns
|
|
2009
2009
|
* the entry; graveyard hit fires `MLLP_ACK_AFTER_TIMEOUT` warning
|
|
2010
|
-
* and returns `null`; otherwise fires
|
|
2011
|
-
*
|
|
2010
|
+
* and returns `null`; otherwise fires `onUnmatchedAck` with the id's
|
|
2011
|
+
* **byte length** and returns `null`.
|
|
2012
2012
|
*
|
|
2013
2013
|
* Triggers lazy graveyard eviction.
|
|
2014
2014
|
*
|
|
@@ -2031,7 +2031,7 @@ var Correlator = class {
|
|
|
2031
2031
|
}
|
|
2032
2032
|
if (controlIdFromAck === null) {
|
|
2033
2033
|
if (this._opts.onUnmatchedAck !== void 0) {
|
|
2034
|
-
this._opts.onUnmatchedAck(
|
|
2034
|
+
this._opts.onUnmatchedAck(null);
|
|
2035
2035
|
}
|
|
2036
2036
|
return null;
|
|
2037
2037
|
}
|
|
@@ -2046,7 +2046,9 @@ var Correlator = class {
|
|
|
2046
2046
|
if (grave !== void 0) {
|
|
2047
2047
|
const elapsedSinceSendMs = this._opts.now() - grave.timedOutAt;
|
|
2048
2048
|
this._opts.onWarning("MLLP_ACK_AFTER_TIMEOUT", {
|
|
2049
|
-
|
|
2049
|
+
// The LENGTH, never the id. Control IDs are decoded `latin1`, a 1:1
|
|
2050
|
+
// byte to code-unit map, so `.length` is a byte count.
|
|
2051
|
+
controlIdBytes: grave.controlId === null ? null : grave.controlId.length,
|
|
2050
2052
|
elapsedSinceSendMs,
|
|
2051
2053
|
byteOffset: byteOffsetFromAck
|
|
2052
2054
|
});
|
|
@@ -2054,7 +2056,7 @@ var Correlator = class {
|
|
|
2054
2056
|
return null;
|
|
2055
2057
|
}
|
|
2056
2058
|
if (this._opts.onUnmatchedAck !== void 0) {
|
|
2057
|
-
this._opts.onUnmatchedAck(controlIdFromAck);
|
|
2059
|
+
this._opts.onUnmatchedAck(controlIdFromAck.length);
|
|
2058
2060
|
}
|
|
2059
2061
|
return null;
|
|
2060
2062
|
}
|
|
@@ -2129,11 +2131,32 @@ var Correlator = class {
|
|
|
2129
2131
|
}
|
|
2130
2132
|
};
|
|
2131
2133
|
|
|
2134
|
+
// src/client/ack-diagnostics.ts
|
|
2135
|
+
var ACK_DIAGNOSTIC_MESSAGES = Object.freeze({
|
|
2136
|
+
MLLP_ACK_UNMATCHED_CONTROL_ID: "Inbound ACK control ID matched no in-flight send and no timed-out send; the ACK was dropped. Field values are withheld: MSA-2 is inbound payload content and this diagnostic goes to a log. The inbound bytes are on the 'message' event; controlIdBytes gives the length.",
|
|
2137
|
+
MLLP_ACK_AFTER_TIMEOUT: "ACK arrived after its send had already timed out; the ACK was dropped. Field values are withheld: a control ID is payload content and this diagnostic goes to a log. The outbound bytes are the payload you passed to send(); controlIdBytes gives the length."
|
|
2138
|
+
});
|
|
2139
|
+
function ackDiagnosticMessage(code) {
|
|
2140
|
+
return ACK_DIAGNOSTIC_MESSAGES[code];
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2132
2143
|
// src/client/error.ts
|
|
2133
2144
|
var MllpTimeoutError = class _MllpTimeoutError extends Error {
|
|
2134
2145
|
name = "MllpTimeoutError";
|
|
2135
|
-
/**
|
|
2136
|
-
|
|
2146
|
+
/**
|
|
2147
|
+
* Byte length of the timed-out send's MSH-10 control ID, or `undefined` when
|
|
2148
|
+
* there was none to read (FIFO mode, or a payload with no MSH-10).
|
|
2149
|
+
*
|
|
2150
|
+
* **The control ID itself is deliberately not here.** An `Error` is a
|
|
2151
|
+
* diagnostic surface: it is logged, and its `stack` is what an error reporter
|
|
2152
|
+
* ships off the box. MSH-10 is payload content, and a scanner that returns
|
|
2153
|
+
* the wrong field returns payload content of some other kind, which is how a
|
|
2154
|
+
* patient identifier reaches a log line. Nothing is lost by withholding it,
|
|
2155
|
+
* because this error rejects the very `send()` whose payload the caller
|
|
2156
|
+
* passed in, so the caller already holds the bytes. Control IDs are decoded
|
|
2157
|
+
* `latin1`, a 1:1 byte to code-unit map, so this count is a byte count.
|
|
2158
|
+
*/
|
|
2159
|
+
messageControlIdBytes;
|
|
2137
2160
|
/** Milliseconds elapsed between write-flush and timeout fire. */
|
|
2138
2161
|
elapsedMs;
|
|
2139
2162
|
/** Epoch ms timestamp recorded at write-flush callback. */
|
|
@@ -2141,12 +2164,12 @@ var MllpTimeoutError = class _MllpTimeoutError extends Error {
|
|
|
2141
2164
|
/**
|
|
2142
2165
|
* Construct an MLLP timeout error.
|
|
2143
2166
|
*
|
|
2144
|
-
* @param message - Human-readable error message.
|
|
2145
|
-
* @param opts - Timeout context (
|
|
2167
|
+
* @param message - Human-readable error message. Structural facts only, never field content.
|
|
2168
|
+
* @param opts - Timeout context (control-id byte length, elapsed time, flush timestamp).
|
|
2146
2169
|
*/
|
|
2147
2170
|
constructor(message, opts) {
|
|
2148
2171
|
super(message);
|
|
2149
|
-
this.
|
|
2172
|
+
this.messageControlIdBytes = opts.messageControlIdBytes;
|
|
2150
2173
|
this.elapsedMs = opts.elapsedMs;
|
|
2151
2174
|
this.sentAt = opts.sentAt;
|
|
2152
2175
|
if (Error.captureStackTrace) {
|
|
@@ -2589,31 +2612,34 @@ var MllpClient = class extends events.EventEmitter {
|
|
|
2589
2612
|
maxInFlight: this._pipeline ? Number.POSITIVE_INFINITY : 1,
|
|
2590
2613
|
onWarning: (code, ctx) => {
|
|
2591
2614
|
this._aggregatedWarningsByCode[code] = (this._aggregatedWarningsByCode[code] ?? 0) + 1;
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
);
|
|
2615
|
+
const warning = Object.freeze({
|
|
2616
|
+
code,
|
|
2617
|
+
byteOffset: ctx.byteOffset,
|
|
2618
|
+
message: ackDiagnosticMessage(code),
|
|
2619
|
+
controlIdBytes: ctx.controlIdBytes,
|
|
2620
|
+
elapsedSinceSendMs: ctx.elapsedSinceSendMs,
|
|
2621
|
+
connectionId: this._connection?.connectionId ?? conn.connectionId,
|
|
2622
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
2623
|
+
});
|
|
2624
|
+
this._emitContained("warning", warning);
|
|
2602
2625
|
},
|
|
2603
|
-
onUnmatchedAck: (
|
|
2626
|
+
onUnmatchedAck: (controlIdBytes) => {
|
|
2604
2627
|
if (this.listenerCount("error") === 0) return;
|
|
2605
2628
|
const err = new MllpFramingError(
|
|
2606
2629
|
"MLLP_ACK_UNMATCHED_CONTROL_ID",
|
|
2607
2630
|
0,
|
|
2608
2631
|
Buffer.alloc(0),
|
|
2609
|
-
|
|
2632
|
+
ackDiagnosticMessage("MLLP_ACK_UNMATCHED_CONTROL_ID")
|
|
2610
2633
|
);
|
|
2611
2634
|
safeEmitError(
|
|
2612
2635
|
this,
|
|
2613
2636
|
Object.freeze({
|
|
2614
2637
|
connectionId: this._connection?.connectionId ?? conn.connectionId,
|
|
2615
2638
|
error: err,
|
|
2616
|
-
|
|
2639
|
+
// The peer's MSA-2 byte LENGTH. The bytes themselves used to be
|
|
2640
|
+
// here and on the message above; a peer sending a one-megabyte
|
|
2641
|
+
// MSA-2 produced a one-megabyte Error.message, straight into a log.
|
|
2642
|
+
controlIdBytes
|
|
2617
2643
|
})
|
|
2618
2644
|
);
|
|
2619
2645
|
},
|
|
@@ -2621,7 +2647,7 @@ var MllpClient = class extends events.EventEmitter {
|
|
|
2621
2647
|
this._timedOutTotal += 1;
|
|
2622
2648
|
entry.reject(
|
|
2623
2649
|
new MllpTimeoutError(`ACK timeout after ${elapsedMs}ms`, {
|
|
2624
|
-
|
|
2650
|
+
messageControlIdBytes: entry.controlId?.length,
|
|
2625
2651
|
elapsedMs,
|
|
2626
2652
|
sentAt: entry.sentAt ?? 0
|
|
2627
2653
|
})
|
|
@@ -3174,7 +3200,7 @@ var MllpClient = class extends events.EventEmitter {
|
|
|
3174
3200
|
cleanup();
|
|
3175
3201
|
reject(
|
|
3176
3202
|
new MllpTimeoutError(`waiting for drain timed out after ${ackTimeoutMs}ms`, {
|
|
3177
|
-
|
|
3203
|
+
messageControlIdBytes: void 0,
|
|
3178
3204
|
elapsedMs: ackTimeoutMs,
|
|
3179
3205
|
sentAt: Date.now()
|
|
3180
3206
|
})
|
|
@@ -3412,7 +3438,7 @@ async function createStarterClient(opts) {
|
|
|
3412
3438
|
}
|
|
3413
3439
|
|
|
3414
3440
|
// src/index.ts
|
|
3415
|
-
var VERSION = "0.0.
|
|
3441
|
+
var VERSION = "0.0.6";
|
|
3416
3442
|
|
|
3417
3443
|
exports.Connection = Connection;
|
|
3418
3444
|
exports.FrameReader = FrameReader;
|
|
@@ -3428,6 +3454,7 @@ exports.MllpTimeoutError = MllpTimeoutError;
|
|
|
3428
3454
|
exports.NetTransport = NetTransport;
|
|
3429
3455
|
exports.TlsTransport = TlsTransport;
|
|
3430
3456
|
exports.VERSION = VERSION;
|
|
3457
|
+
exports.ackDiagnosticMessage = ackDiagnosticMessage;
|
|
3431
3458
|
exports.buildRawAck = buildRawAck;
|
|
3432
3459
|
exports.createClient = createClient;
|
|
3433
3460
|
exports.createServer = createServer;
|