@cosyte/hl7 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 +287 -0
- package/README.md +14 -6
- package/dist/index.cjs +187 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +314 -267
- package/dist/index.d.ts +314 -267
- package/dist/index.mjs +187 -122
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -36,7 +36,7 @@ var ProfileDefinitionError = class extends Error {
|
|
|
36
36
|
profileName;
|
|
37
37
|
/**
|
|
38
38
|
* Construct a new `ProfileDefinitionError`. `profileName` is optional so
|
|
39
|
-
*
|
|
39
|
+
* callers may omit it when the offending profile cannot be named
|
|
40
40
|
* (e.g. during initial validation before a name is parsed).
|
|
41
41
|
*
|
|
42
42
|
* @internal
|
|
@@ -253,7 +253,104 @@ var KNOWN_SEGMENTS = /* @__PURE__ */ new Set([
|
|
|
253
253
|
"CSS"
|
|
254
254
|
]);
|
|
255
255
|
|
|
256
|
+
// src/parser/charset.ts
|
|
257
|
+
function normalizeLabel(raw) {
|
|
258
|
+
return raw.trim().replace(/\s+/gu, " ").toUpperCase();
|
|
259
|
+
}
|
|
260
|
+
function decodeEntry(canonical, decoder) {
|
|
261
|
+
return { canonical, treatment: "decode", decoder };
|
|
262
|
+
}
|
|
263
|
+
function verbatimEntry(canonical) {
|
|
264
|
+
return { canonical, treatment: "verbatim", decoder: "" };
|
|
265
|
+
}
|
|
266
|
+
function buildTable() {
|
|
267
|
+
const table = /* @__PURE__ */ new Map();
|
|
268
|
+
const add = (aliases, entry) => {
|
|
269
|
+
for (const alias of aliases) table.set(normalizeLabel(alias), entry);
|
|
270
|
+
};
|
|
271
|
+
add(["ASCII", "US-ASCII", "ISO IR6"], decodeEntry("ASCII", "utf-8"));
|
|
272
|
+
add(["UTF-8", "UTF8", "UNICODE UTF-8", "UNICODE"], decodeEntry("UTF-8", "utf-8"));
|
|
273
|
+
add(["8859/1", "ISO-8859-1", "ISO 8859-1", "ISO8859-1"], decodeEntry("8859/1", "latin1"));
|
|
274
|
+
for (const n of [2, 3, 4, 5, 6, 7, 8, 10, 13, 14, 15, 16]) {
|
|
275
|
+
add(
|
|
276
|
+
[`8859/${n}`, `ISO-8859-${n}`, `ISO 8859-${n}`, `ISO8859-${n}`],
|
|
277
|
+
decodeEntry(`8859/${n}`, `iso-8859-${n}`)
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
add(["8859/9", "ISO-8859-9", "ISO 8859-9", "ISO8859-9"], verbatimEntry("8859/9"));
|
|
281
|
+
add(["8859/11", "ISO-8859-11", "ISO 8859-11", "ISO8859-11"], verbatimEntry("8859/11"));
|
|
282
|
+
add(["ISO IR14", "JIS X 0201"], verbatimEntry("ISO IR14"));
|
|
283
|
+
add(["ISO IR87", "JIS X 0208"], verbatimEntry("ISO IR87"));
|
|
284
|
+
add(["ISO IR159", "JIS X 0212"], verbatimEntry("ISO IR159"));
|
|
285
|
+
add(["GB 18030-2000", "GB18030", "GB 18030"], verbatimEntry("GB 18030-2000"));
|
|
286
|
+
add(["KS X 1001", "KSX1001", "KS C 5601"], verbatimEntry("KS X 1001"));
|
|
287
|
+
add(["CNS 11643-1992", "CNS 11643"], verbatimEntry("CNS 11643-1992"));
|
|
288
|
+
add(["BIG-5", "BIG5"], verbatimEntry("BIG-5"));
|
|
289
|
+
add(["UNICODE UTF-16", "UTF-16"], verbatimEntry("UNICODE UTF-16"));
|
|
290
|
+
add(["UNICODE UTF-32", "UTF-32"], verbatimEntry("UNICODE UTF-32"));
|
|
291
|
+
return table;
|
|
292
|
+
}
|
|
293
|
+
var CHARSET_TABLE = buildTable();
|
|
294
|
+
var DEFAULT_RESOLUTION = Object.freeze({
|
|
295
|
+
canonical: "ASCII",
|
|
296
|
+
treatment: "decode",
|
|
297
|
+
decoder: "utf-8",
|
|
298
|
+
recognized: true
|
|
299
|
+
});
|
|
300
|
+
function resolveCharset(raw) {
|
|
301
|
+
if (raw === void 0) return DEFAULT_RESOLUTION;
|
|
302
|
+
const key = normalizeLabel(raw);
|
|
303
|
+
if (key === "") return DEFAULT_RESOLUTION;
|
|
304
|
+
const entry = CHARSET_TABLE.get(key);
|
|
305
|
+
if (entry !== void 0) {
|
|
306
|
+
return {
|
|
307
|
+
canonical: entry.canonical,
|
|
308
|
+
treatment: entry.treatment,
|
|
309
|
+
decoder: entry.decoder,
|
|
310
|
+
recognized: true
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
return { canonical: key, treatment: "verbatim", decoder: "", recognized: false };
|
|
314
|
+
}
|
|
315
|
+
function canonicalCharset(raw) {
|
|
316
|
+
return resolveCharset(raw).canonical;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/parser/tokens.ts
|
|
320
|
+
var DERIVED_TOKEN_SHAPES = {
|
|
321
|
+
/**
|
|
322
|
+
* HL7 v2 Ch. 2 §2.5 segment identifier: three characters, the first
|
|
323
|
+
* alphabetic.
|
|
324
|
+
*
|
|
325
|
+
* Two deliberate tightenings, each measured rather than assumed. The first
|
|
326
|
+
* version allowed four characters as "vendor tolerance", which was invented
|
|
327
|
+
* rather than grounded: all 91 `KNOWN_SEGMENTS` are exactly three, and
|
|
328
|
+
* `defineProfile` independently validates custom Z-segments to
|
|
329
|
+
* `/^Z[A-Z0-9]{2}$/`, so nothing legitimate is longer. The second requires a
|
|
330
|
+
* leading letter, which every known segment and every legal Z-segment
|
|
331
|
+
* satisfies, and which excludes a **bare numeric** residue. That matters out
|
|
332
|
+
* of proportion to its size: a forged line reading `120` is a glucose, a
|
|
333
|
+
* blood pressure or a dose, which is the most clinical meaning three
|
|
334
|
+
* characters can carry.
|
|
335
|
+
*/
|
|
336
|
+
segmentId: /^[A-Za-z][A-Za-z0-9]{2}$/,
|
|
337
|
+
/** MSH-9 message type / trigger, e.g. `ADT^A01` or `A40`. */
|
|
338
|
+
messageType: /^[A-Za-z0-9]{1,8}(?:\^[A-Za-z0-9]{1,8}){0,2}$/,
|
|
339
|
+
/** MSH-12 version ID, e.g. `2.5` or `2.5.1`. */
|
|
340
|
+
version: /^[0-9]{1,2}(?:\.[0-9]{1,3}){0,3}$/
|
|
341
|
+
};
|
|
342
|
+
function safeDerivedToken(value, kind) {
|
|
343
|
+
return DERIVED_TOKEN_SHAPES[kind].test(value) ? value : WITHHELD;
|
|
344
|
+
}
|
|
345
|
+
var WITHHELD = "<withheld>";
|
|
346
|
+
function boundedIdentifier(value, kind) {
|
|
347
|
+
return value === "" ? "" : safeDerivedToken(value, kind);
|
|
348
|
+
}
|
|
349
|
+
|
|
256
350
|
// src/parser/warnings.ts
|
|
351
|
+
function safeCharsetLabel(value) {
|
|
352
|
+
return resolveCharset(value).recognized ? value : WITHHELD;
|
|
353
|
+
}
|
|
257
354
|
var WARNING_CODES = {
|
|
258
355
|
MLLP_FRAMING_STRIPPED: "MLLP_FRAMING_STRIPPED",
|
|
259
356
|
FIELD_WHITESPACE_TRIMMED: "FIELD_WHITESPACE_TRIMMED",
|
|
@@ -338,28 +435,28 @@ function timestampFallbackFormat(position, matchedFormat) {
|
|
|
338
435
|
function segmentCase(position, observed) {
|
|
339
436
|
return {
|
|
340
437
|
code: WARNING_CODES.SEGMENT_CASE,
|
|
341
|
-
message: `Segment identifier "${observed}" is not uppercase; normalized to "${observed.toUpperCase()}".`,
|
|
438
|
+
message: `Segment identifier "${safeDerivedToken(observed, "segmentId")}" is not uppercase; normalized to "${safeDerivedToken(observed.toUpperCase(), "segmentId")}".`,
|
|
342
439
|
position
|
|
343
440
|
};
|
|
344
441
|
}
|
|
345
442
|
function extraFields(position, segmentName2, extraCount) {
|
|
346
443
|
return {
|
|
347
444
|
code: WARNING_CODES.EXTRA_FIELDS,
|
|
348
|
-
message: `Segment "${segmentName2}" has ${String(extraCount)} more field(s) than the profile declares.`,
|
|
445
|
+
message: `Segment "${safeDerivedToken(segmentName2, "segmentId")}" has ${String(extraCount)} more field(s) than the profile declares.`,
|
|
349
446
|
position
|
|
350
447
|
};
|
|
351
448
|
}
|
|
352
449
|
function unknownSegment(position, segmentName2) {
|
|
353
450
|
return {
|
|
354
451
|
code: WARNING_CODES.UNKNOWN_SEGMENT,
|
|
355
|
-
message: `Unknown segment "${segmentName2}": not in HL7 spec and no profile claim.`,
|
|
452
|
+
message: `Unknown segment "${safeDerivedToken(segmentName2, "segmentId")}": not in HL7 spec and no profile claim.`,
|
|
356
453
|
position
|
|
357
454
|
};
|
|
358
455
|
}
|
|
359
456
|
function duplicateRequiredSegment(position, segmentName2) {
|
|
360
457
|
return {
|
|
361
458
|
code: WARNING_CODES.DUPLICATE_REQUIRED_SEGMENT,
|
|
362
|
-
message: `Required singleton segment "${segmentName2}" appears more than once.`,
|
|
459
|
+
message: `Required singleton segment "${safeDerivedToken(segmentName2, "segmentId")}" appears more than once.`,
|
|
363
460
|
position
|
|
364
461
|
};
|
|
365
462
|
}
|
|
@@ -373,42 +470,42 @@ function encodingMismatch(position, detail) {
|
|
|
373
470
|
function missingRequiredField(position, segmentName2, fieldIndex) {
|
|
374
471
|
return {
|
|
375
472
|
code: WARNING_CODES.MISSING_REQUIRED_FIELD,
|
|
376
|
-
message: `Required field ${segmentName2}-${String(fieldIndex)} is missing or empty.`,
|
|
473
|
+
message: `Required field ${safeDerivedToken(segmentName2, "segmentId")}-${String(fieldIndex)} is missing or empty.`,
|
|
377
474
|
position
|
|
378
475
|
};
|
|
379
476
|
}
|
|
380
477
|
function missingExpectedGroup(position, messageType, groupName, anchorSegments) {
|
|
381
478
|
return {
|
|
382
479
|
code: WARNING_CODES.MISSING_EXPECTED_GROUP,
|
|
383
|
-
message: `Message type "${messageType}" is missing its expected "${groupName}" segment group (no ${anchorSegments.join("/")}); message may be truncated or misrouted.`,
|
|
480
|
+
message: `Message type "${safeDerivedToken(messageType, "messageType")}" is missing its expected "${groupName}" segment group (no ${anchorSegments.join("/")}); message may be truncated or misrouted.`,
|
|
384
481
|
position
|
|
385
482
|
};
|
|
386
483
|
}
|
|
387
484
|
function outOfOrderSegment(position, segmentName2) {
|
|
388
485
|
return {
|
|
389
486
|
code: WARNING_CODES.OUT_OF_ORDER_SEGMENT,
|
|
390
|
-
message: `Segment "${segmentName2}" appears out of the order declared by the active profile.`,
|
|
487
|
+
message: `Segment "${safeDerivedToken(segmentName2, "segmentId")}" appears out of the order declared by the active profile.`,
|
|
391
488
|
position
|
|
392
489
|
};
|
|
393
490
|
}
|
|
394
491
|
function versionMismatch(position, declared, expected) {
|
|
395
492
|
return {
|
|
396
493
|
code: WARNING_CODES.VERSION_MISMATCH,
|
|
397
|
-
message: `HL7 version mismatch: message declares "${declared}", expected "${expected}".`,
|
|
494
|
+
message: `HL7 version mismatch: message declares "${safeDerivedToken(declared, "version")}", expected "${expected}".`,
|
|
398
495
|
position
|
|
399
496
|
};
|
|
400
497
|
}
|
|
401
498
|
function unknownCharset(position, requested) {
|
|
402
499
|
return {
|
|
403
500
|
code: WARNING_CODES.UNKNOWN_CHARSET,
|
|
404
|
-
message: `Unrecognized character set "${requested}"; not decoded, bytes read as latin1.`,
|
|
501
|
+
message: `Unrecognized character set "${safeCharsetLabel(requested)}"; not decoded, bytes read as latin1.`,
|
|
405
502
|
position
|
|
406
503
|
};
|
|
407
504
|
}
|
|
408
505
|
function unsupportedCharset(position, code) {
|
|
409
506
|
return {
|
|
410
507
|
code: WARNING_CODES.UNSUPPORTED_CHARSET,
|
|
411
|
-
message: `Character set "${code}" was not decoded; bytes read as latin1.`,
|
|
508
|
+
message: `Character set "${safeCharsetLabel(code)}" was not decoded; bytes read as latin1.`,
|
|
412
509
|
position
|
|
413
510
|
};
|
|
414
511
|
}
|
|
@@ -423,7 +520,7 @@ function mergeMissingPriorOrSurvivor(position, eventType, missing) {
|
|
|
423
520
|
const detail = missing === "prior" ? "no MRG segment carries a usable prior (non-surviving) identifier" : "no PID segment carries a usable surviving identifier";
|
|
424
521
|
return {
|
|
425
522
|
code: WARNING_CODES.MERGE_MISSING_PRIOR_OR_SURVIVOR,
|
|
426
|
-
message: `Identity event "${eventType}" is missing its ${missing} role: ${detail}. Surfacing what is present; the MRG->PID merge direction is not guessed.`,
|
|
523
|
+
message: `Identity event "${safeDerivedToken(eventType, "messageType")}" is missing its ${missing} role: ${detail}. Surfacing what is present; the MRG->PID merge direction is not guessed.`,
|
|
427
524
|
position
|
|
428
525
|
};
|
|
429
526
|
}
|
|
@@ -469,69 +566,6 @@ function emitIfFramed(result, emit, position) {
|
|
|
469
566
|
}
|
|
470
567
|
}
|
|
471
568
|
|
|
472
|
-
// src/parser/charset.ts
|
|
473
|
-
function normalizeLabel(raw) {
|
|
474
|
-
return raw.trim().replace(/\s+/gu, " ").toUpperCase();
|
|
475
|
-
}
|
|
476
|
-
function decodeEntry(canonical, decoder) {
|
|
477
|
-
return { canonical, treatment: "decode", decoder };
|
|
478
|
-
}
|
|
479
|
-
function verbatimEntry(canonical) {
|
|
480
|
-
return { canonical, treatment: "verbatim", decoder: "" };
|
|
481
|
-
}
|
|
482
|
-
function buildTable() {
|
|
483
|
-
const table = /* @__PURE__ */ new Map();
|
|
484
|
-
const add = (aliases, entry) => {
|
|
485
|
-
for (const alias of aliases) table.set(normalizeLabel(alias), entry);
|
|
486
|
-
};
|
|
487
|
-
add(["ASCII", "US-ASCII", "ISO IR6"], decodeEntry("ASCII", "utf-8"));
|
|
488
|
-
add(["UTF-8", "UTF8", "UNICODE UTF-8", "UNICODE"], decodeEntry("UTF-8", "utf-8"));
|
|
489
|
-
add(["8859/1", "ISO-8859-1", "ISO 8859-1", "ISO8859-1"], decodeEntry("8859/1", "latin1"));
|
|
490
|
-
for (const n of [2, 3, 4, 5, 6, 7, 8, 10, 13, 14, 15, 16]) {
|
|
491
|
-
add(
|
|
492
|
-
[`8859/${n}`, `ISO-8859-${n}`, `ISO 8859-${n}`, `ISO8859-${n}`],
|
|
493
|
-
decodeEntry(`8859/${n}`, `iso-8859-${n}`)
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
add(["8859/9", "ISO-8859-9", "ISO 8859-9", "ISO8859-9"], verbatimEntry("8859/9"));
|
|
497
|
-
add(["8859/11", "ISO-8859-11", "ISO 8859-11", "ISO8859-11"], verbatimEntry("8859/11"));
|
|
498
|
-
add(["ISO IR14", "JIS X 0201"], verbatimEntry("ISO IR14"));
|
|
499
|
-
add(["ISO IR87", "JIS X 0208"], verbatimEntry("ISO IR87"));
|
|
500
|
-
add(["ISO IR159", "JIS X 0212"], verbatimEntry("ISO IR159"));
|
|
501
|
-
add(["GB 18030-2000", "GB18030", "GB 18030"], verbatimEntry("GB 18030-2000"));
|
|
502
|
-
add(["KS X 1001", "KSX1001", "KS C 5601"], verbatimEntry("KS X 1001"));
|
|
503
|
-
add(["CNS 11643-1992", "CNS 11643"], verbatimEntry("CNS 11643-1992"));
|
|
504
|
-
add(["BIG-5", "BIG5"], verbatimEntry("BIG-5"));
|
|
505
|
-
add(["UNICODE UTF-16", "UTF-16"], verbatimEntry("UNICODE UTF-16"));
|
|
506
|
-
add(["UNICODE UTF-32", "UTF-32"], verbatimEntry("UNICODE UTF-32"));
|
|
507
|
-
return table;
|
|
508
|
-
}
|
|
509
|
-
var CHARSET_TABLE = buildTable();
|
|
510
|
-
var DEFAULT_RESOLUTION = Object.freeze({
|
|
511
|
-
canonical: "ASCII",
|
|
512
|
-
treatment: "decode",
|
|
513
|
-
decoder: "utf-8",
|
|
514
|
-
recognized: true
|
|
515
|
-
});
|
|
516
|
-
function resolveCharset(raw) {
|
|
517
|
-
if (raw === void 0) return DEFAULT_RESOLUTION;
|
|
518
|
-
const key = normalizeLabel(raw);
|
|
519
|
-
if (key === "") return DEFAULT_RESOLUTION;
|
|
520
|
-
const entry = CHARSET_TABLE.get(key);
|
|
521
|
-
if (entry !== void 0) {
|
|
522
|
-
return {
|
|
523
|
-
canonical: entry.canonical,
|
|
524
|
-
treatment: entry.treatment,
|
|
525
|
-
decoder: entry.decoder,
|
|
526
|
-
recognized: true
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
return { canonical: key, treatment: "verbatim", decoder: "", recognized: false };
|
|
530
|
-
}
|
|
531
|
-
function canonicalCharset(raw) {
|
|
532
|
-
return resolveCharset(raw).canonical;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
569
|
// src/parser/normalize.ts
|
|
536
570
|
var CHARSET_POSITION = { segmentIndex: 0, fieldIndex: 18 };
|
|
537
571
|
function preserveVerbatim(input) {
|
|
@@ -926,8 +960,8 @@ function analyzeMessageStructure(messageCode, triggerEvent, presentSegmentNames)
|
|
|
926
960
|
if (def === void 0) {
|
|
927
961
|
return Object.freeze({
|
|
928
962
|
recognized: false,
|
|
929
|
-
messageCode,
|
|
930
|
-
triggerEvent,
|
|
963
|
+
messageCode: boundedIdentifier(messageCode, "segmentId"),
|
|
964
|
+
triggerEvent: boundedIdentifier(triggerEvent, "segmentId"),
|
|
931
965
|
expectedGroups: Object.freeze([]),
|
|
932
966
|
missingGroups: Object.freeze([])
|
|
933
967
|
});
|
|
@@ -1861,11 +1895,11 @@ var Field = class {
|
|
|
1861
1895
|
isNull;
|
|
1862
1896
|
/** Reference to the underlying `RawField.repetitions` (no defensive copy). */
|
|
1863
1897
|
repetitions;
|
|
1864
|
-
/** The 5 encoding characters for this message. Exposed for composite parsers
|
|
1898
|
+
/** The 5 encoding characters for this message. Exposed for composite parsers. @internal */
|
|
1865
1899
|
enc;
|
|
1866
1900
|
/** Position of this field in the parent message: used for position-aware error messages. @internal */
|
|
1867
1901
|
position;
|
|
1868
|
-
/** The full `RawField` this wrapper wraps. Exposed for composite parsers
|
|
1902
|
+
/** The full `RawField` this wrapper wraps. Exposed for composite parsers. @internal */
|
|
1869
1903
|
raw;
|
|
1870
1904
|
/**
|
|
1871
1905
|
* Construct a new `Field`. Called internally by `Segment.field(n)`; user
|
|
@@ -1882,7 +1916,7 @@ var Field = class {
|
|
|
1882
1916
|
/**
|
|
1883
1917
|
* First-repetition, first-component, first-subcomponent value as a decoded
|
|
1884
1918
|
* string: unescaped ONCE by the tokenizer on parse, returned verbatim here
|
|
1885
|
-
* (never re-unescaped
|
|
1919
|
+
* (never re-unescaped). Returns `""` when the field is
|
|
1886
1920
|
* empty or HL7 null. Equivalent to `msg.get('SEG.N')` for a top-level access.
|
|
1887
1921
|
*
|
|
1888
1922
|
* @example
|
|
@@ -1913,7 +1947,7 @@ var Field = class {
|
|
|
1913
1947
|
* vendor-quirk control id containing an unescaped delimiter (`ID^X`) must
|
|
1914
1948
|
* not be truncated to its first component.
|
|
1915
1949
|
*
|
|
1916
|
-
* **Byte-verbatim for parsed content
|
|
1950
|
+
* **Byte-verbatim for parsed content.** The parse pipeline stores
|
|
1917
1951
|
* *decoded* content, but also records the original wire bytes of any escape
|
|
1918
1952
|
* whose decode is not byte-faithful (`RawComponent.rawSubcomponents`), so
|
|
1919
1953
|
* re-serialization preserves the sender's exact escape bytes: hex escapes
|
|
@@ -2159,7 +2193,24 @@ var EMPTY_REP = Object.freeze({
|
|
|
2159
2193
|
|
|
2160
2194
|
// src/model/segment.ts
|
|
2161
2195
|
var Segment = class {
|
|
2162
|
-
/**
|
|
2196
|
+
/**
|
|
2197
|
+
* Segment identifier: three characters with a leading letter, e.g. `"PID"`,
|
|
2198
|
+
* `"OBX"`, `"ZPI"`.
|
|
2199
|
+
*
|
|
2200
|
+
* **Bounded, and it is `"<withheld>"` when the raw name is not that shape.**
|
|
2201
|
+
* A line with no field separator has its whole content read as a segment
|
|
2202
|
+
* name, so an unescaped line break inside a narrative field forges a
|
|
2203
|
+
* "segment" whose name is clinical text. This field presents itself as a
|
|
2204
|
+
* structural identifier and consumers interpolate it into labels, loci and
|
|
2205
|
+
* reports, so it never carries that text. `""` still means absent, which is
|
|
2206
|
+
* a different fact from withheld.
|
|
2207
|
+
*
|
|
2208
|
+
* Use {@link Segment.raw}`.name` when you need the verbatim text: it is the
|
|
2209
|
+
* unbounded value, and it is what serialization emits, so the byte-verbatim
|
|
2210
|
+
* round-trip is unaffected. One consequence worth knowing: a segment whose
|
|
2211
|
+
* raw name fails the shape (a 4-character vendor Z-segment, which HL7 v2
|
|
2212
|
+
* Ch. 2 §2.5 does not permit) is not matched by `msg.segments(name)`.
|
|
2213
|
+
*/
|
|
2163
2214
|
type;
|
|
2164
2215
|
/** Reference to the underlying `RawSegment.fields`: 1-indexed per HL7 convention. */
|
|
2165
2216
|
fields;
|
|
@@ -2167,7 +2218,7 @@ var Segment = class {
|
|
|
2167
2218
|
enc;
|
|
2168
2219
|
/** Absolute index of this segment in `Hl7Message.rawSegments[]`. Used for position tracking. @internal */
|
|
2169
2220
|
absoluteIndex;
|
|
2170
|
-
/** The full `RawSegment` this wrapper wraps. Exposed for mutation methods
|
|
2221
|
+
/** The full `RawSegment` this wrapper wraps. Exposed for mutation methods. @internal */
|
|
2171
2222
|
raw;
|
|
2172
2223
|
/**
|
|
2173
2224
|
* Lookup map from profile-declared field name → 1-indexed HL7 position.
|
|
@@ -2184,7 +2235,7 @@ var Segment = class {
|
|
|
2184
2235
|
* should obtain `Segment` instances via `msg.segments(type)` or
|
|
2185
2236
|
* `msg.allSegments()`.
|
|
2186
2237
|
*
|
|
2187
|
-
* The optional `customFields` parameter is the per-segment
|
|
2238
|
+
* The optional `customFields` parameter is the per-segment portion of the
|
|
2188
2239
|
* applied profile's merged `customSegments` map (PROF-07 / D-16). When
|
|
2189
2240
|
* supplied, `get(name)` resolves names against it; otherwise `get(name)`
|
|
2190
2241
|
* always returns `undefined`.
|
|
@@ -2192,7 +2243,7 @@ var Segment = class {
|
|
|
2192
2243
|
*/
|
|
2193
2244
|
constructor(raw, enc, absoluteIndex, customFields) {
|
|
2194
2245
|
this.raw = raw;
|
|
2195
|
-
this.type = raw.name;
|
|
2246
|
+
this.type = boundedIdentifier(raw.name, "segmentId");
|
|
2196
2247
|
this.fields = raw.fields;
|
|
2197
2248
|
this.enc = enc;
|
|
2198
2249
|
this.absoluteIndex = absoluteIndex;
|
|
@@ -3879,11 +3930,20 @@ var Hl7Message = class {
|
|
|
3879
3930
|
* Raw positional tree produced by the parser. 1-indexed per HL7 convention
|
|
3880
3931
|
* (`fields[0]` is the segment-name / MSH separator placeholder slot). Use
|
|
3881
3932
|
* `segments(type)` / `allSegments()` for typed wrapper access: this field
|
|
3882
|
-
* is exposed for advanced callers that need the raw tree directly
|
|
3883
|
-
* future serialization phase 5).
|
|
3933
|
+
* is exposed for advanced callers that need the raw tree directly.
|
|
3884
3934
|
*/
|
|
3885
3935
|
rawSegments;
|
|
3886
3936
|
encodingCharacters;
|
|
3937
|
+
/**
|
|
3938
|
+
* HL7 version the model asserts for this message, from MSH-12.1.1, e.g.
|
|
3939
|
+
* `"2.5"` or `"2.5.1"`.
|
|
3940
|
+
*
|
|
3941
|
+
* **Bounded, and it is `"<withheld>"` when MSH-12 does not hold a version.**
|
|
3942
|
+
* Same reasoning as {@link Segment.type}: it presents as an identifier and
|
|
3943
|
+
* consumers label with it. `meta.version` keeps MSH-12 exactly as it
|
|
3944
|
+
* arrived, and is what version-scoped field selection reads, so this bound
|
|
3945
|
+
* changes no parsing behaviour.
|
|
3946
|
+
*/
|
|
3887
3947
|
version;
|
|
3888
3948
|
warnings;
|
|
3889
3949
|
profile;
|
|
@@ -3896,7 +3956,7 @@ var Hl7Message = class {
|
|
|
3896
3956
|
dateFormats;
|
|
3897
3957
|
/**
|
|
3898
3958
|
* Merged `customSegments` map from the applied profile, stored so
|
|
3899
|
-
* `allSegments()` can hand per-segment
|
|
3959
|
+
* `allSegments()` can hand per-segment portions to `Segment` constructors
|
|
3900
3960
|
* (D-16). Undefined when no profile was applied.
|
|
3901
3961
|
* @internal
|
|
3902
3962
|
*/
|
|
@@ -3905,40 +3965,40 @@ var Hl7Message = class {
|
|
|
3905
3965
|
* Lazily built cache of Segment wrappers keyed by segment type. Built on
|
|
3906
3966
|
* first `segments(type)` call and filtered from `_allSegments` so
|
|
3907
3967
|
* individual Segment instances are identical across both caches (D-11).
|
|
3908
|
-
*
|
|
3968
|
+
* The mutation methods drop this cache wholesale.
|
|
3909
3969
|
* @internal
|
|
3910
3970
|
*/
|
|
3911
3971
|
_segmentsByType;
|
|
3912
3972
|
/**
|
|
3913
3973
|
* Lazily built cache of every Segment wrapper in document order. Built on
|
|
3914
|
-
* first `segments(type)` / `allSegments()` call.
|
|
3974
|
+
* first `segments(type)` / `allSegments()` call. The mutation methods
|
|
3915
3975
|
* drop this cache wholesale.
|
|
3916
3976
|
* @internal
|
|
3917
3977
|
*/
|
|
3918
3978
|
_allSegments;
|
|
3919
3979
|
/**
|
|
3920
|
-
* Lazily built `Meta` view (
|
|
3980
|
+
* Lazily built `Meta` view (memoized). Dropped wholesale
|
|
3921
3981
|
* by `invalidateCaches`. `Meta` is always defined (D-03: MSH absence
|
|
3922
3982
|
* throws `NO_MSH_SEGMENT` at parse time) so no null-sentinel is needed.
|
|
3923
3983
|
* @internal
|
|
3924
3984
|
*/
|
|
3925
3985
|
_meta;
|
|
3926
3986
|
/**
|
|
3927
|
-
* Lazily built `MessageStructure` view
|
|
3987
|
+
* Lazily built `MessageStructure` view. Dropped wholesale by
|
|
3928
3988
|
* `invalidateCaches`. Always defined: `analyzeMessageStructure` returns an
|
|
3929
3989
|
* `recognized: false` summary for unmodelled types rather than absence.
|
|
3930
3990
|
* @internal
|
|
3931
3991
|
*/
|
|
3932
3992
|
_structure;
|
|
3933
3993
|
/**
|
|
3934
|
-
* Lazily built `Patient | undefined` view (
|
|
3994
|
+
* Lazily built `Patient | undefined` view (memoized). Uses
|
|
3935
3995
|
* a null-sentinel cache because `undefined` means "not yet computed" while
|
|
3936
3996
|
* `null` means "computed, absent". D-04: no PID → public value `undefined`.
|
|
3937
3997
|
* @internal
|
|
3938
3998
|
*/
|
|
3939
3999
|
_patient;
|
|
3940
4000
|
/**
|
|
3941
|
-
* Lazily built `Visit | undefined` view (
|
|
4001
|
+
* Lazily built `Visit | undefined` view (memoized). Same
|
|
3942
4002
|
* null-sentinel convention as `_patient`. HELPERS-03: no PV1 → public
|
|
3943
4003
|
* value `undefined`.
|
|
3944
4004
|
* @internal
|
|
@@ -3954,7 +4014,7 @@ var Hl7Message = class {
|
|
|
3954
4014
|
constructor(init) {
|
|
3955
4015
|
this.rawSegments = init.segments;
|
|
3956
4016
|
this.encodingCharacters = init.encodingCharacters;
|
|
3957
|
-
this.version = init.version;
|
|
4017
|
+
this.version = boundedIdentifier(init.version, "version");
|
|
3958
4018
|
this.warnings = Object.freeze(init.warnings.slice());
|
|
3959
4019
|
this.profile = init.profile;
|
|
3960
4020
|
if (init.customSegments !== void 0) this._customSegments = init.customSegments;
|
|
@@ -3962,8 +4022,8 @@ var Hl7Message = class {
|
|
|
3962
4022
|
}
|
|
3963
4023
|
/**
|
|
3964
4024
|
* Resolve a dot-path (e.g. `PID.5.1`, `OBX[2].5`, `PID.3[0].1`) to its
|
|
3965
|
-
* decoded leaf string (unescaped once at parse: never re-unescaped on
|
|
3966
|
-
*
|
|
4025
|
+
* decoded leaf string (unescaped once at parse: never re-unescaped on
|
|
4026
|
+
* read). Returns `undefined` when the path doesn't
|
|
3967
4027
|
* resolve: never throws on missing path (MODEL-05). Throws `TypeError`
|
|
3968
4028
|
* on malformed path syntax (e.g. `"pid.5"`, empty string).
|
|
3969
4029
|
*
|
|
@@ -3998,7 +4058,7 @@ var Hl7Message = class {
|
|
|
3998
4058
|
* Return the cached array of `Segment` wrappers for `segmentType` in
|
|
3999
4059
|
* document order. The returned array identity and the individual Segment
|
|
4000
4060
|
* instances are both stable across calls (D-11). Invalidated wholesale
|
|
4001
|
-
* by
|
|
4061
|
+
* by the mutation methods.
|
|
4002
4062
|
*
|
|
4003
4063
|
* @example
|
|
4004
4064
|
* ```ts
|
|
@@ -4021,7 +4081,7 @@ var Hl7Message = class {
|
|
|
4021
4081
|
* Iterate every `Segment` in document order (MSH first, then every
|
|
4022
4082
|
* subsequent segment). Cached per-message; same array reference and same
|
|
4023
4083
|
* Segment instances on repeat calls (D-11). Invalidated wholesale by
|
|
4024
|
-
*
|
|
4084
|
+
* the mutation methods.
|
|
4025
4085
|
*
|
|
4026
4086
|
* @example
|
|
4027
4087
|
* ```ts
|
|
@@ -4055,7 +4115,7 @@ var Hl7Message = class {
|
|
|
4055
4115
|
* @example
|
|
4056
4116
|
* ```ts
|
|
4057
4117
|
* console.log(msg.meta.type); // "ADT^A01"
|
|
4058
|
-
* console.log(msg.meta.timestamp?.raw); // fidelity TS
|
|
4118
|
+
* console.log(msg.meta.timestamp?.raw); // fidelity TS
|
|
4059
4119
|
* console.log(msg.meta.controlId); // "MSG001"
|
|
4060
4120
|
* ```
|
|
4061
4121
|
*/
|
|
@@ -4063,8 +4123,8 @@ var Hl7Message = class {
|
|
|
4063
4123
|
return this._meta ??= buildMeta(this);
|
|
4064
4124
|
}
|
|
4065
4125
|
/**
|
|
4066
|
-
* Structural-conformance summary for the common message types
|
|
4067
|
-
*
|
|
4126
|
+
* Structural-conformance summary for the common message types: a
|
|
4127
|
+
* misroute/truncation safety net, NOT a conformance validator.
|
|
4068
4128
|
* Reports, per the message's recognized (MSH-9.1, MSH-9.2) type, which
|
|
4069
4129
|
* Required segment groups are present and which are entirely absent
|
|
4070
4130
|
* (`missingGroups`: the same set the parser flags as
|
|
@@ -4132,7 +4192,7 @@ var Hl7Message = class {
|
|
|
4132
4192
|
}
|
|
4133
4193
|
/**
|
|
4134
4194
|
* Every OBR as an Order with its OBX children grouped positionally (D-12) and
|
|
4135
|
-
* its TQ1 / legacy embedded-TQ (ORC-7) `timings` (
|
|
4195
|
+
* its TQ1 / legacy embedded-TQ (ORC-7) `timings` (the repeat pattern is
|
|
4136
4196
|
* surfaced verbatim, never resolved to a schedule). D-05: returns `[]` when no
|
|
4137
4197
|
* OBR present. D-06: not memoized.
|
|
4138
4198
|
*
|
|
@@ -4148,7 +4208,7 @@ var Hl7Message = class {
|
|
|
4148
4208
|
return orders(this);
|
|
4149
4209
|
}
|
|
4150
4210
|
/**
|
|
4151
|
-
* Message-level NTE notes
|
|
4211
|
+
* Message-level NTE notes: every NTE segment with no recognized
|
|
4152
4212
|
* preceding parent (not immediately following a `PID`, `ORC`, `OBR`, or
|
|
4153
4213
|
* `OBX`), surfaced verbatim in document order so nothing is dropped. Notes
|
|
4154
4214
|
* that DO attach to a specific patient / order / result are exposed on those
|
|
@@ -4165,7 +4225,7 @@ var Hl7Message = class {
|
|
|
4165
4225
|
}
|
|
4166
4226
|
/**
|
|
4167
4227
|
* Every recognized ADT patient-identity event (merge / move / link /
|
|
4168
|
-
* unlink / person add/update
|
|
4228
|
+
* unlink / person add/update), with the MRG-sourced
|
|
4169
4229
|
* `prior` and PID/PV1-sourced `surviving` parties labelled by role and the
|
|
4170
4230
|
* spec-constant `direction: "MRG_TO_PID"` on merge/move events. Returns
|
|
4171
4231
|
* `[]` when the trigger event is not in the identity family. D-06: not
|
|
@@ -4186,13 +4246,13 @@ var Hl7Message = class {
|
|
|
4186
4246
|
}
|
|
4187
4247
|
/**
|
|
4188
4248
|
* Every RXO/RXE/RXD/RXA as a typed `Medication`, with RXR (route) and RXC
|
|
4189
|
-
* (component) segments grouped positionally under their parent
|
|
4190
|
-
*
|
|
4191
|
-
*
|
|
4192
|
-
*
|
|
4249
|
+
* (component) segments grouped positionally under their parent. D-05:
|
|
4250
|
+
* returns `[]` when no RX* parent present. D-06: not memoized. The give
|
|
4251
|
+
* *amount* and give *strength* are surfaced separately and never
|
|
4252
|
+
* reconciled.
|
|
4193
4253
|
*
|
|
4194
4254
|
* Each medication also carries its TQ1 / legacy embedded-TQ (RXE-1) `timings`
|
|
4195
|
-
* (
|
|
4255
|
+
* (repeat pattern verbatim, never resolved to a schedule).
|
|
4196
4256
|
*
|
|
4197
4257
|
* @example
|
|
4198
4258
|
* ```ts
|
|
@@ -4209,7 +4269,7 @@ var Hl7Message = class {
|
|
|
4209
4269
|
/**
|
|
4210
4270
|
* Every RXA of a VXU^V04 as a typed `Immunization`, with RXR (route/site)
|
|
4211
4271
|
* and OBX children grouped positionally under the RXA and `orderControl`
|
|
4212
|
-
* from the preceding ORC of the VXU order group
|
|
4272
|
+
* from the preceding ORC of the VXU order group. D-05:
|
|
4213
4273
|
* returns `[]` when no RXA present. D-06: not memoized. The vaccine code
|
|
4214
4274
|
* carries its own provenance; the action code (RXA-21) is surfaced verbatim
|
|
4215
4275
|
* and `recordOrigin` (administered vs historical) is derived only from the
|
|
@@ -4277,7 +4337,7 @@ var Hl7Message = class {
|
|
|
4277
4337
|
return insurance(this);
|
|
4278
4338
|
}
|
|
4279
4339
|
/**
|
|
4280
|
-
* Every SCH of an SIU message as a typed `Appointment
|
|
4340
|
+
* Every SCH of an SIU message as a typed `Appointment`, with
|
|
4281
4341
|
* the AIS/AIG/AIL/AIP resource segments that follow it grouped positionally
|
|
4282
4342
|
* under that SCH. Surfaces the placer/filler appointment ids, SCH-25 filler
|
|
4283
4343
|
* status (Table 0278), SCH-11 start/end timing, and the resource groups
|
|
@@ -4297,7 +4357,7 @@ var Hl7Message = class {
|
|
|
4297
4357
|
return appointments(this);
|
|
4298
4358
|
}
|
|
4299
4359
|
/**
|
|
4300
|
-
* Every TXA of an MDM message as a typed `ClinicalDocument
|
|
4360
|
+
* Every TXA of an MDM message as a typed `ClinicalDocument`,
|
|
4301
4361
|
* with the OBX narrative body grouped positionally under that TXA. The
|
|
4302
4362
|
* completion status (TXA-17) and availability status (TXA-19) are surfaced as
|
|
4303
4363
|
* **distinct** fields and never conflated: a document can be available before
|
|
@@ -4317,7 +4377,7 @@ var Hl7Message = class {
|
|
|
4317
4377
|
return documents(this);
|
|
4318
4378
|
}
|
|
4319
4379
|
/**
|
|
4320
|
-
* Every FT1 of a DFT message as a typed `Charge
|
|
4380
|
+
* Every FT1 of a DFT message as a typed `Charge`, one per
|
|
4321
4381
|
* FT1 in document order. Surfaces billing-critical fields (FT1-6 transaction
|
|
4322
4382
|
* type, FT1-7 code, FT1-11/12 extended/unit amount, FT1-19 diagnosis linkage)
|
|
4323
4383
|
* with **no billing logic and no money-as-float**: amounts are the verbatim
|
|
@@ -4411,7 +4471,7 @@ var Hl7Message = class {
|
|
|
4411
4471
|
* `TypeError` with an actionable message otherwise).
|
|
4412
4472
|
*
|
|
4413
4473
|
* The value is accepted verbatim: unescaped delimiter characters are NOT
|
|
4414
|
-
* rejected on input (D-18). Re-escaping
|
|
4474
|
+
* rejected on input (D-18). Re-escaping is the serializer's concern.
|
|
4415
4475
|
*
|
|
4416
4476
|
* MSH-1 / MSH-2 follow the user-facing HL7 convention: `setField("MSH.3", ...)`
|
|
4417
4477
|
* targets MSH-3 (sending application), matching `msg.get("MSH.3")`.
|
|
@@ -4497,11 +4557,11 @@ var Hl7Message = class {
|
|
|
4497
4557
|
return this;
|
|
4498
4558
|
}
|
|
4499
4559
|
/**
|
|
4500
|
-
* Set a **typed composite** at a field (or field-repetition) dot-path
|
|
4501
|
-
*
|
|
4560
|
+
* Set a **typed composite** at a field (or field-repetition) dot-path:
|
|
4561
|
+
* the conservative-emit mirror of the typed read accessors
|
|
4502
4562
|
* (`asXpn`/`asCx`/…). The caller passes a structured value (an XPN name, a CX
|
|
4503
4563
|
* identifier, a TS timestamp, …) by its {@link CompositeKind}, and the setter
|
|
4504
|
-
* encodes it into a spec-clean field using the
|
|
4564
|
+
* encodes it into a spec-clean field using the encode-safe path: any
|
|
4505
4565
|
* delimiter embedded in a component value is **escaped, never injected**, so
|
|
4506
4566
|
* a `familyName` of `"Smith^Jr"` re-parses to exactly that string rather than
|
|
4507
4567
|
* forging a component boundary. No hand-assembly of `^`/`&`/`~`.
|
|
@@ -4692,8 +4752,8 @@ var Hl7Message = class {
|
|
|
4692
4752
|
return this;
|
|
4693
4753
|
}
|
|
4694
4754
|
/**
|
|
4695
|
-
* Drop every wrapper AND helper cache wholesale (
|
|
4696
|
-
*
|
|
4755
|
+
* Drop every wrapper AND helper cache wholesale (D-17 + D-02). Called by
|
|
4756
|
+
* every mutation method so subsequent `segments(type)` /
|
|
4697
4757
|
* `allSegments()` / `meta` / `patient` / `visit` reads rebuild from the
|
|
4698
4758
|
* mutated `rawSegments` tree.
|
|
4699
4759
|
* @internal
|
|
@@ -4792,7 +4852,12 @@ function resolveBufferCharset(raw, options, emit) {
|
|
|
4792
4852
|
emit(
|
|
4793
4853
|
encodingMismatch(
|
|
4794
4854
|
{ segmentIndex: 0 },
|
|
4795
|
-
`
|
|
4855
|
+
// `declared` is MSH-18 read off the wire. On a message with no
|
|
4856
|
+
// segment terminators it is not MSH-18 at all but the 18th
|
|
4857
|
+
// `|`-token of the flattened message, commonly a data field, so it
|
|
4858
|
+
// is shape-checked before it reaches a log surface. `override` is
|
|
4859
|
+
// the caller's own `options.charset`, not input, and is left alone.
|
|
4860
|
+
`options.charset="${override}" disagrees with MSH-18="${safeCharsetLabel(declared)}"`
|
|
4796
4861
|
)
|
|
4797
4862
|
);
|
|
4798
4863
|
}
|
|
@@ -6807,7 +6872,7 @@ async function* parseStream(source, optionsOrProfile) {
|
|
|
6807
6872
|
}
|
|
6808
6873
|
|
|
6809
6874
|
// src/index.ts
|
|
6810
|
-
var VERSION = "0.0.
|
|
6875
|
+
var VERSION = "0.0.4";
|
|
6811
6876
|
|
|
6812
6877
|
export { ACK_CODES, ACK_CONDITIONS, BUILTIN_DATE_FALLBACKS, DEFAULT_ENCODING_CHARACTERS, ERR_CONDITION_CODES, ERR_CONDITION_CODE_SYSTEM, ERR_SEVERITIES, FATAL_CODES, FINDING_CODES, Field, namespace_exports as HL7, Hl7Message, Hl7ParseError, KNOWN_CODING_SYSTEMS, KNOWN_SEGMENTS, MESSAGE_STRUCTURE_DEFINITIONS, ProfileDefinitionError, SUPPORTED_DATE_TOKENS, Segment, USAGE_CODES, VERSION, WARNING_CODES, ackNoCorrelationId, alternateCodingSystemOf, analyzeMessageStructure, batchCountMismatch, batchMissingTrailer, buildAck, buildAdt, buildMessage, buildOru, canonicalCharset, codingSystem, codingSystemOf, conformance_exports as conformance, decodeText, defineConformanceProfile, defineProfile, detectAckMode, downgradePositiveAck, dtmToDate, duplicateRequiredSegment, encodeCe, encodeComposite, encodeCompositeReps, encodeCwe, encodeCx, encodeHd, encodeNm, encodePl, encodeText, encodeTs, encodeXad, encodeXcn, encodeXpn, encodeXtn, encodingMismatch, extraFields, fieldWhitespaceTrimmed, formatDtm, getDefaultProfile, interpretAck, isPositiveAck, mergeMissingPriorOrSurvivor, missingExpectedGroup, missingRequiredField, mllpFramingStripped, outOfOrderSegment, parseCe, parseCwe, parseCx, parseDtm, parseHL7, parseHd, parseNm, parsePath, parsePl, parseSn, parseStream, parseTs, parseXad, parseXcn, parseXpn, parseXtn, pickMrn, profiles, reescape, renderText, resolveCharset, resolvePath, segmentCase, setDefaultProfile, splitBatch, text_exports as text, timestampFallbackFormat, unescape, unknownCharset, unknownEscapeSequence, unknownSegment, unsupportedCharset, unterminatedEscapeSequence, unterminatedStreamMessage, validateAgainstProfile, versionMismatch };
|
|
6813
6878
|
//# sourceMappingURL=index.mjs.map
|