@rethinkhealth/hl7v2-parser 0.4.1 → 0.5.0

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/README.md CHANGED
@@ -29,14 +29,12 @@ npm install @rethinkhealth/hl7v2-parser
29
29
  ### Basic Usage
30
30
 
31
31
  ```typescript
32
- import { unified } from 'unified';
33
- import { hl7v2Parser } from '@rethinkhealth/hl7v2-parser';
32
+ import { unified } from "unified";
33
+ import { hl7v2Parser } from "@rethinkhealth/hl7v2-parser";
34
34
 
35
35
  const message = `MSH|^~\\&|SENDING_APP|SENDING_FAC|...`;
36
36
 
37
- const tree = unified()
38
- .use(hl7v2Parser)
39
- .parse(message);
37
+ const tree = unified().use(hl7v2Parser).parse(message);
40
38
 
41
39
  console.log(tree);
42
40
  ```
@@ -46,15 +44,15 @@ console.log(tree);
46
44
  You can specify custom delimiters for parsing non-standard HL7v2 messages. The `delimiters` option accepts a partial object, so you only need to specify the delimiters you want to override:
47
45
 
48
46
  ```typescript
49
- import { unified } from 'unified';
50
- import { hl7v2Parser } from '@rethinkhealth/hl7v2-parser';
47
+ import { unified } from "unified";
48
+ import { hl7v2Parser } from "@rethinkhealth/hl7v2-parser";
51
49
 
52
50
  // Override only the segment delimiter
53
51
  const tree = unified()
54
52
  .use(hl7v2Parser, {
55
53
  delimiters: {
56
- segment: '\n', // Use newline instead of carriage return
57
- }
54
+ segment: "\n", // Use newline instead of carriage return
55
+ },
58
56
  })
59
57
  .parse(message);
60
58
 
@@ -62,10 +60,10 @@ const tree = unified()
62
60
  const customTree = unified()
63
61
  .use(hl7v2Parser, {
64
62
  delimiters: {
65
- field: '$',
66
- component: '%',
67
- segment: '\n',
68
- }
63
+ field: "$",
64
+ component: "%",
65
+ segment: "\n",
66
+ },
69
67
  })
70
68
  .parse(customMessage);
71
69
  ```
@@ -88,17 +86,17 @@ The parser supports experimental features through the `experimental` option. The
88
86
  By default, the parser represents empty fields with full scaffolding (Field → FieldRepetition → Component → Subcomponent with `value: ""`). The `emptyMode: 'empty'` option changes this behavior to use empty children arrays instead, making the AST more compact and easier to work with.
89
87
 
90
88
  ```typescript
91
- import { unified } from 'unified';
92
- import { hl7v2Parser } from '@rethinkhealth/hl7v2-parser';
89
+ import { unified } from "unified";
90
+ import { hl7v2Parser } from "@rethinkhealth/hl7v2-parser";
93
91
 
94
92
  // With empty-array mode (new behavior)
95
93
  const tree = unified()
96
94
  .use(hl7v2Parser, {
97
95
  experimental: {
98
- emptyMode: 'empty-array',
99
- }
96
+ emptyMode: "empty-array",
97
+ },
100
98
  })
101
- .parse('PID|1||');
99
+ .parse("PID|1||");
102
100
 
103
101
  // PID.2 (empty field) will have: { type: 'field', children: [] }
104
102
  // Instead of: Field → Rep → Comp → Sub with value: ""
@@ -114,12 +112,12 @@ const tree = unified()
114
112
 
115
113
  **Examples:**
116
114
 
117
- | Wire Format | Legacy Mode | Empty-Array Mode |
118
- |--------------|------------------------------------------------|-----------------------------------------|
119
- | `PID\|1\|\|` | Field → Rep → Comp → Sub("") | Field(children: []) |
120
- | `PID\|1\|^\|` | Field → Rep → [Comp → Sub(""), Comp → Sub("")] | Field → Rep → [Comp[], Comp[]] |
121
- | `PID\|1\|~\|` | Field → [Rep → Comp → Sub(""), Rep → ...] | Field → [Rep[], Rep[]] |
122
- | `PID\|1\|ABC\|`| Field → Rep → Comp → Sub("ABC") | Field → Rep → Comp → Sub("ABC") (same) |
115
+ | Wire Format | Legacy Mode | Empty-Array Mode |
116
+ | --------------- | ---------------------------------------------- | -------------------------------------- |
117
+ | `PID\|1\|\|` | Field → Rep → Comp → Sub("") | Field(children: []) |
118
+ | `PID\|1\|^\|` | Field → Rep → [Comp → Sub(""), Comp → Sub("")] | Field → Rep → [Comp[], Comp[]] |
119
+ | `PID\|1\|~\|` | Field → [Rep → Comp → Sub(""), Rep → ...] | Field → [Rep[], Rep[]] |
120
+ | `PID\|1\|ABC\|` | Field → Rep → Comp → Sub("ABC") | Field → Rep → Comp → Sub("ABC") (same) |
123
121
 
124
122
  **Benefits:**
125
123
 
package/dist/index.d.ts CHANGED
@@ -3,3 +3,4 @@ export * from "./preprocessor";
3
3
  export { parseHL7v2FromIterator } from "./processor";
4
4
  export * from "./tokenizer";
5
5
  export * from "./types";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC9D,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -4,13 +4,13 @@ import { DEFAULT_DELIMITERS as DEFAULT_DELIMITERS2 } from "@rethinkhealth/hl7v2-
4
4
  // src/preprocessor.ts
5
5
  import { DEFAULT_DELIMITERS } from "@rethinkhealth/hl7v2-utils";
6
6
  var stripBOM = (ctx) => {
7
- if (ctx.input.charCodeAt(0) === 65279) {
7
+ if (ctx.input.codePointAt(0) === 65279) {
8
8
  ctx.input = ctx.input.slice(1);
9
9
  }
10
10
  return ctx;
11
11
  };
12
12
  var normalizeNewlines = (ctx) => {
13
- ctx.input = ctx.input.replace(/\r?\n/g, ctx.delimiters.segment);
13
+ ctx.input = ctx.input.replaceAll(/\r?\n/g, ctx.delimiters.segment);
14
14
  return ctx;
15
15
  };
16
16
  var detectDelimiters = (ctx) => {
@@ -21,14 +21,14 @@ var detectDelimiters = (ctx) => {
21
21
  const repetition = enc.charAt(1) || DEFAULT_DELIMITERS.repetition;
22
22
  const _escape = enc.charAt(2) || DEFAULT_DELIMITERS.escape;
23
23
  const subcomponent = enc.charAt(3) || DEFAULT_DELIMITERS.subcomponent;
24
- const segment = DEFAULT_DELIMITERS.segment;
24
+ const { segment } = DEFAULT_DELIMITERS;
25
25
  ctx.delimiters = {
26
- field,
27
26
  component,
28
- repetition,
29
27
  escape: _escape,
30
- subcomponent,
31
- segment
28
+ field,
29
+ repetition,
30
+ segment,
31
+ subcomponent
32
32
  };
33
33
  }
34
34
  return ctx;
@@ -49,40 +49,40 @@ function runPreprocessors(ctx, steps) {
49
49
  import { isEmptyNode } from "@rethinkhealth/hl7v2-utils";
50
50
  function createSubcomponent(start) {
51
51
  return {
52
+ position: { end: start, start },
52
53
  type: "subcomponent",
53
- value: "",
54
- position: { start, end: start }
54
+ value: ""
55
55
  };
56
56
  }
57
57
  function createComponent(start, mode) {
58
58
  return {
59
- type: "component",
60
- children: mode !== "empty" ? [createSubcomponent(start)] : [],
61
- position: { start, end: start }
59
+ children: mode === "empty" ? [] : [createSubcomponent(start)],
60
+ position: { end: start, start },
61
+ type: "component"
62
62
  };
63
63
  }
64
64
  function createFieldRepetition(start, mode) {
65
65
  return {
66
- type: "field-repetition",
67
- children: mode !== "empty" ? [createComponent(start, mode)] : [],
68
- position: { start, end: start }
66
+ children: mode === "empty" ? [] : [createComponent(start, mode)],
67
+ position: { end: start, start },
68
+ type: "field-repetition"
69
69
  };
70
70
  }
71
71
  function createField(start, mode) {
72
72
  return {
73
- type: "field",
74
- children: mode !== "empty" ? [createFieldRepetition(start, mode)] : [],
75
- position: { start, end: start }
73
+ children: mode === "empty" ? [] : [createFieldRepetition(start, mode)],
74
+ position: { end: start, start },
75
+ type: "field"
76
76
  };
77
77
  }
78
78
  function createParserCore(ctx) {
79
79
  const mode = ctx.emptyMode;
80
80
  const root = {
81
- type: "root",
82
81
  children: [],
83
82
  data: {
84
83
  delimiters: ctx.delimiters
85
- }
84
+ },
85
+ type: "root"
86
86
  };
87
87
  let seg = null;
88
88
  let field = null;
@@ -106,15 +106,11 @@ function createParserCore(ctx) {
106
106
  expectingSegmentName = true;
107
107
  };
108
108
  const openSegment = (name, position) => {
109
- const header = {
110
- type: "segment-header",
111
- value: name,
112
- position: { ...position }
113
- };
114
109
  seg = {
115
- type: "segment",
116
- children: [header],
117
- position: { start: position.start, end: position.end }
110
+ children: [],
111
+ name,
112
+ position: { end: position.end, start: position.start },
113
+ type: "segment"
118
114
  };
119
115
  root.children.push(seg);
120
116
  field = null;
@@ -133,14 +129,14 @@ function createParserCore(ctx) {
133
129
  }
134
130
  field = createField(start, mode);
135
131
  seg.children.push(field);
136
- if (mode !== "empty") {
137
- rep = field.children[0] ?? null;
138
- comp = rep?.children[0] ?? null;
139
- currentSub = comp?.children[0] ?? null;
140
- } else {
132
+ if (mode === "empty") {
141
133
  rep = null;
142
134
  comp = null;
143
135
  currentSub = null;
136
+ } else {
137
+ rep = field.children[0] ?? null;
138
+ comp = rep?.children[0] ?? null;
139
+ currentSub = comp?.children[0] ?? null;
144
140
  }
145
141
  segmentHasContent = true;
146
142
  };
@@ -158,12 +154,12 @@ function createParserCore(ctx) {
158
154
  }
159
155
  rep = createFieldRepetition(start, mode);
160
156
  field.children.push(rep);
161
- if (mode !== "empty") {
162
- comp = rep.children[0] ?? null;
163
- currentSub = comp?.children[0] ?? null;
164
- } else {
157
+ if (mode === "empty") {
165
158
  comp = null;
166
159
  currentSub = null;
160
+ } else {
161
+ comp = rep.children[0] ?? null;
162
+ currentSub = comp?.children[0] ?? null;
167
163
  }
168
164
  segmentHasContent = true;
169
165
  };
@@ -204,11 +200,7 @@ function createParserCore(ctx) {
204
200
  }
205
201
  comp = createComponent(start, mode);
206
202
  rep.children.push(comp);
207
- if (mode !== "empty") {
208
- currentSub = comp.children[0] ?? null;
209
- } else {
210
- currentSub = null;
211
- }
203
+ currentSub = mode === "empty" ? null : comp.children[0] ?? null;
212
204
  segmentHasContent = true;
213
205
  };
214
206
  const ensureForText = (start) => {
@@ -311,8 +303,8 @@ function createParserCore(ctx) {
311
303
  const val = tok.value ?? "";
312
304
  if (!rootStartSet) {
313
305
  root.position = {
314
- start: tok.position.start,
315
- end: tok.position.start
306
+ end: tok.position.start,
307
+ start: tok.position.start
316
308
  };
317
309
  rootStartSet = true;
318
310
  }
@@ -349,14 +341,14 @@ function createParserCore(ctx) {
349
341
  root.position.end = documentEnd;
350
342
  } else if (!root.position) {
351
343
  root.position = {
352
- start: { line: 1, column: 1, offset: 0 },
353
- end: { line: 1, column: 1, offset: 0 }
344
+ end: { column: 1, line: 1, offset: 0 },
345
+ start: { column: 1, line: 1, offset: 0 }
354
346
  };
355
347
  }
356
348
  return root;
357
349
  };
358
350
  function dropTrailingEmptyFieldIfPresent() {
359
- if (!seg || seg.children.length <= 1) {
351
+ if (!seg || seg.children.length === 0) {
360
352
  return;
361
353
  }
362
354
  const lastChild = seg.children.at(-1);
@@ -368,7 +360,7 @@ function createParserCore(ctx) {
368
360
  seg.children.pop();
369
361
  }
370
362
  }
371
- return { processToken, finalize, root };
363
+ return { finalize, processToken, root };
372
364
  }
373
365
  function parseHL7v2FromIterator(tokens, ctx) {
374
366
  const core = createParserCore(ctx);
@@ -414,22 +406,22 @@ var HL7v2Tokenizer = class {
414
406
  MSH_FIELD_DELIMITER_END
415
407
  );
416
408
  this.pendingBootstrap = [
417
- { kind: "TEXT", value: msh, advance: msh.length },
418
- { kind: "FIELD_DELIM", advance: 0 },
419
- { kind: "TEXT", value: msh1, advance: msh1.length },
420
- { kind: "FIELD_DELIM", advance: 0 },
421
- { kind: "TEXT", value: msh2, advance: msh2.length }
409
+ { advance: msh.length, kind: "TEXT", value: msh },
410
+ { advance: 0, kind: "FIELD_DELIM" },
411
+ { advance: msh1.length, kind: "TEXT", value: msh1 },
412
+ { advance: 0, kind: "FIELD_DELIM" },
413
+ { advance: msh2.length, kind: "TEXT", value: msh2 }
422
414
  ];
423
415
  }
424
416
  }
425
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: The cognitive complexity of this method is justified because it must handle the HL7v2 MSH segment bootstrap logic and multiple tokenization cases in a single method for performance and maintainability.
417
+ // oxlint-disable-next-line complexity
426
418
  next() {
427
419
  const s = this.input;
428
420
  const n = s.length;
429
421
  if (this.i >= n && !this.pendingBootstrap?.length) {
430
422
  return null;
431
423
  }
432
- const start = { offset: this.i, line: this.line, column: this.col };
424
+ const start = { column: this.col, line: this.line, offset: this.i };
433
425
  if (!this.didMshBootstrap && this.pendingBootstrap) {
434
426
  const step = this.pendingBootstrap.shift();
435
427
  if (step) {
@@ -476,13 +468,13 @@ var HL7v2Tokenizer = class {
476
468
  return this._tok("SUBCOMP_DELIM", void 0, start);
477
469
  }
478
470
  let j = this.i;
479
- const seg = this.delims.segment, fld = this.delims.field, rep = this.delims.repetition, cmp = this.delims.component, sub = this.delims.subcomponent;
471
+ const cmp = this.delims.component, fld = this.delims.field, rep = this.delims.repetition, seg = this.delims.segment, sub = this.delims.subcomponent;
480
472
  while (j < s.length) {
481
473
  const c = s.charAt(j);
482
474
  if (c === seg || c === fld || c === rep || c === cmp || c === sub) {
483
475
  break;
484
476
  }
485
- j++;
477
+ j += 1;
486
478
  }
487
479
  const val = s.slice(this.i, j);
488
480
  this._fastAdvance(val);
@@ -512,15 +504,15 @@ var HL7v2Tokenizer = class {
512
504
  this.i += chunk.length;
513
505
  }
514
506
  _tok(type, value, start) {
515
- const end = { offset: this.i, line: this.line, column: this.col };
516
- return { type, value, position: { start, end } };
507
+ const end = { column: this.col, line: this.line, offset: this.i };
508
+ return { position: { end, start }, type, value };
517
509
  }
518
510
  // Iterable protocol (sync)
519
511
  [Symbol.iterator]() {
520
512
  return {
521
513
  next: () => {
522
514
  const t = this.next();
523
- if (t == null) {
515
+ if (!t) {
524
516
  return { done: true, value: void 0 };
525
517
  }
526
518
  return { done: false, value: t };
@@ -537,19 +529,19 @@ function* iterateTokenizerSync(t) {
537
529
  }
538
530
  function parseHL7v2(input, opts = {}, settings) {
539
531
  let ctx = {
540
- input,
541
532
  delimiters: {
542
533
  ...DEFAULT_DELIMITERS2,
543
534
  ...settings?.delimiters ?? {}
544
535
  },
545
- emptyMode: settings?.experimental?.emptyMode
536
+ emptyMode: settings?.experimental?.emptyMode,
537
+ input
546
538
  };
547
539
  ctx = runPreprocessors(ctx, opts.preprocess || defaultPreprocessors);
548
540
  const tokenizer = new HL7v2Tokenizer();
549
541
  tokenizer.reset(ctx);
550
542
  return parseHL7v2FromIterator(iterateTokenizerSync(tokenizer), ctx);
551
543
  }
552
- var hl7v2Parser = function(options = {}) {
544
+ var hl7v2Parser = function hl7v2Parser2(options = {}) {
553
545
  this.parser = (document) => {
554
546
  const settings = this.data("settings");
555
547
  return parseHL7v2(document, options, settings);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parser.ts","../src/preprocessor.ts","../src/processor.ts","../src/tokenizer.ts"],"sourcesContent":["import type { Root } from \"@rethinkhealth/hl7v2-ast\";\nimport type { HL7v2Settings } from \"@rethinkhealth/hl7v2-config\";\nimport { DEFAULT_DELIMITERS } from \"@rethinkhealth/hl7v2-utils\";\nimport type { Plugin, Processor } from \"unified\";\nimport { defaultPreprocessors, runPreprocessors } from \"./preprocessor\";\nimport { parseHL7v2FromIterator } from \"./processor\";\nimport { HL7v2Tokenizer } from \"./tokenizer\";\nimport type { ParseOptions, ParserContext, Token, Tokenizer } from \"./types\";\n\nfunction* iterateTokenizerSync(t: Tokenizer): Iterable<Token> {\n for (let tok = t.next(); tok; tok = t.next()) {\n yield tok;\n }\n}\n\nexport function parseHL7v2(\n input: string,\n opts: ParseOptions = {},\n settings?: HL7v2Settings\n): Root {\n // Merge settings: defaults < provided settings\n // Note: MSH auto-detection (via detectDelimiters preprocessor) runs after this\n // and will override delimiters if the message starts with MSH\n\n let ctx: ParserContext = {\n input,\n delimiters: {\n ...DEFAULT_DELIMITERS,\n ...(settings?.delimiters ?? {}),\n },\n emptyMode: settings?.experimental?.emptyMode,\n };\n // Run preprocessing\n ctx = runPreprocessors(ctx, opts.preprocess || defaultPreprocessors);\n // Run tokenizer\n const tokenizer = new HL7v2Tokenizer();\n // Reset tokenizer.\n tokenizer.reset(ctx);\n // Parse\n return parseHL7v2FromIterator(iterateTokenizerSync(tokenizer), ctx);\n}\n\nconst hl7v2Parser: Plugin<[ParseOptions?], string, Root> = function (\n this: Processor,\n options = {}\n) {\n this.parser = (document: string) => {\n // Get settings from processor (populated by unified-args from config)\n const settings = this.data(\"settings\");\n\n return parseHL7v2(document, options, settings);\n };\n};\n\nexport default hl7v2Parser;\n","import { DEFAULT_DELIMITERS } from \"@rethinkhealth/hl7v2-utils\";\nimport type { ParserContext, PreprocessorStep } from \"./types\";\n\n// PreprocessorStep is declared in `types.ts` to avoid circular imports\n\n/**\n * Step: strip UTF-8 BOM.\n */\nexport const stripBOM: PreprocessorStep = (ctx) => {\n if (ctx.input.charCodeAt(0) === 0xfe_ff) {\n ctx.input = ctx.input.slice(1);\n }\n return ctx;\n};\n\n/**\n * Step: normalize newlines to the default delimiters.\n */\nexport const normalizeNewlines: PreprocessorStep = (ctx) => {\n ctx.input = ctx.input.replace(/\\r?\\n/g, ctx.delimiters.segment);\n return ctx;\n};\n\n/**\n * Step: auto-detect delimiters from MSH.\n */\nexport const detectDelimiters: PreprocessorStep = (ctx) => {\n if (ctx.input.startsWith(\"MSH\")) {\n const field = ctx.input.charAt(3) || DEFAULT_DELIMITERS.field;\n const enc = ctx.input.slice(4, 8);\n const component = enc.charAt(0) || DEFAULT_DELIMITERS.component;\n const repetition = enc.charAt(1) || DEFAULT_DELIMITERS.repetition;\n const _escape = enc.charAt(2) || DEFAULT_DELIMITERS.escape;\n const subcomponent = enc.charAt(3) || DEFAULT_DELIMITERS.subcomponent;\n const segment = DEFAULT_DELIMITERS.segment;\n\n ctx.delimiters = {\n field,\n component,\n repetition,\n escape: _escape,\n subcomponent,\n segment,\n };\n }\n return ctx;\n};\n\n/**\n * Default preprocessing pipeline.\n */\nexport const defaultPreprocessors: PreprocessorStep[] = [\n stripBOM,\n normalizeNewlines,\n detectDelimiters,\n];\n\n/**\n * Run the pipeline to initialize ParserContext.\n */\nexport function runPreprocessors(\n ctx: ParserContext,\n steps: PreprocessorStep[]\n): ParserContext {\n for (const step of steps) {\n // biome-ignore lint/style/noParameterAssign: this is necessary to keep no-copy\n ctx = step(ctx);\n }\n\n return ctx;\n}\n","// src/parser.ts\n/** biome-ignore-all lint/complexity/noExcessiveCognitiveComplexity: there are complex logic */\n/** biome-ignore-all lint/style/noNonNullAssertion: the processor uses non-null assertions */\n\nimport type {\n Component,\n Field,\n FieldRepetition,\n Root,\n Segment,\n SegmentHeader,\n Subcomponent,\n} from \"@rethinkhealth/hl7v2-ast\";\nimport { isEmptyNode } from \"@rethinkhealth/hl7v2-utils\";\nimport type { Position } from \"unist\";\nimport type { ParserContext, Token } from \"./types\";\n\n// Helper to create an empty subcomponent at a given position\nfunction createSubcomponent(start: Position[\"start\"]): Subcomponent {\n return {\n type: \"subcomponent\",\n value: \"\",\n position: { start, end: start },\n };\n}\n\n// Helper to create a component (with or without children based on mode)\nfunction createComponent(\n start: Position[\"start\"],\n mode: \"legacy\" | \"empty\" | undefined\n): Component {\n return {\n type: \"component\",\n children: mode !== \"empty\" ? [createSubcomponent(start)] : [],\n position: { start, end: start },\n };\n}\n\n// Helper to create a field repetition (with or without children based on mode)\nfunction createFieldRepetition(\n start: Position[\"start\"],\n mode: \"legacy\" | \"empty\" | undefined\n): FieldRepetition {\n return {\n type: \"field-repetition\",\n children: mode !== \"empty\" ? [createComponent(start, mode)] : [],\n position: { start, end: start },\n };\n}\n\n// Helper to create a field (with or without children based on mode)\nfunction createField(\n start: Position[\"start\"],\n mode: \"legacy\" | \"empty\" | undefined\n): Field {\n return {\n type: \"field\",\n children: mode !== \"empty\" ? [createFieldRepetition(start, mode)] : [],\n position: { start, end: start },\n };\n}\n\n// Shared core: process a single token into mutable parse state\nfunction createParserCore(ctx: ParserContext) {\n const mode = ctx.emptyMode;\n const root: Root = {\n type: \"root\",\n children: [],\n data: {\n delimiters: ctx.delimiters,\n },\n };\n\n let seg: Segment | null = null;\n let field: Field | null = null;\n let rep: FieldRepetition | null = null;\n let comp: Component | null = null;\n let currentSub: Subcomponent | null = null;\n let segmentHasContent = false;\n let lastContentEnd: Position[\"end\"] | null = null;\n let documentEnd: Position[\"end\"] | null = null; // Track document-level end position\n let expectingSegmentName = true; // Start expecting a segment name\n let justSetSegmentName = false; // Track if we just set the segment name\n let rootStartSet = false; // Track if we've set the root start position\n\n const resetState = () => {\n seg = null;\n field = null;\n rep = null;\n comp = null;\n currentSub = null;\n segmentHasContent = false;\n lastContentEnd = null;\n expectingSegmentName = true;\n };\n\n const openSegment = (name: string, position: Position) => {\n const header: SegmentHeader = {\n type: \"segment-header\",\n value: name,\n position: { ...position },\n };\n seg = {\n type: \"segment\",\n children: [header],\n position: { start: position.start, end: position.end },\n };\n root.children.push(seg);\n // Reset field-level state\n field = null;\n rep = null;\n comp = null;\n currentSub = null;\n segmentHasContent = false;\n justSetSegmentName = true;\n expectingSegmentName = false;\n };\n\n const openField = (start: Position[\"start\"]) => {\n if (!seg) {\n throw new Error(\n \"Cannot open field without an active segment. TEXT token with segment name must precede field content.\"\n );\n }\n field = createField(start, mode);\n seg.children.push(field);\n if (mode !== \"empty\") {\n rep = field.children[0] ?? null;\n comp = rep?.children[0] ?? null;\n currentSub = comp?.children[0] ?? null;\n } else {\n rep = null;\n comp = null;\n currentSub = null;\n }\n segmentHasContent = true;\n };\n\n const openRepetition = (start: Position[\"start\"]) => {\n if (!field) {\n openField(start);\n // In empty-array mode, openField creates empty field\n // We need to add an empty first repetition before the delimiter\n if (mode === \"empty\") {\n const emptyRep = createFieldRepetition(start, mode);\n field!.children.push(emptyRep);\n }\n // Fall through to create the repetition after the delimiter\n }\n // In empty-array mode, if field has no children yet, add empty first rep\n if (mode === \"empty\" && field!.children.length === 0) {\n const emptyRep = createFieldRepetition(start, mode);\n field!.children.push(emptyRep);\n }\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n if (mode !== \"empty\") {\n comp = rep.children[0] ?? null;\n currentSub = comp?.children[0] ?? null;\n } else {\n comp = null;\n currentSub = null;\n }\n segmentHasContent = true;\n };\n\n // Ensure there's a component to add subcomponents to (for SUBCOMP_DELIM)\n // Does NOT add empty sibling components\n const ensureComponent = (start: Position[\"start\"]) => {\n if (!field) {\n openField(start);\n }\n if (!rep) {\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n }\n if (!comp) {\n comp = createComponent(start, mode);\n rep.children.push(comp);\n }\n segmentHasContent = true;\n };\n\n // Handle COMPONENT_DELIM - adds empty component before delimiter if needed\n const openComponent = (start: Position[\"start\"]) => {\n if (!field) {\n openField(start);\n // In empty-array mode, openField creates empty field\n // We need to create rep and add empty first component\n if (mode === \"empty\") {\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n const emptyComp = createComponent(start, mode);\n rep.children.push(emptyComp);\n }\n // Fall through to create the component after the delimiter\n }\n if (!rep) {\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n // In empty-array mode, need to add empty first component before the delimiter\n if (mode === \"empty\") {\n const emptyComp = createComponent(start, mode);\n rep.children.push(emptyComp);\n }\n } else if (mode === \"empty\" && rep.children.length === 0) {\n // If rep exists but has no children, add empty first component\n const emptyComp = createComponent(start, mode);\n rep.children.push(emptyComp);\n }\n comp = createComponent(start, mode);\n rep.children.push(comp);\n if (mode !== \"empty\") {\n currentSub = comp.children[0] ?? null;\n } else {\n currentSub = null;\n }\n segmentHasContent = true;\n };\n\n const ensureForText = (start: Position[\"start\"]) => {\n if (!field) {\n openField(start);\n if (mode !== \"empty\") {\n return; // Everything is already set up by openField in legacy mode\n }\n // In empty-array mode, openField created empty field, need to build structure\n }\n if (!rep) {\n if (mode !== \"empty\") {\n openRepetition(start);\n return; // Everything is already set up by openRepetition in legacy mode\n }\n // In empty-array mode, need to create repetition\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n }\n if (!comp) {\n if (mode !== \"empty\") {\n openComponent(start);\n return; // Everything is already set up by openComponent in legacy mode\n }\n // In empty-array mode, need to create component\n comp = createComponent(start, mode);\n rep!.children.push(comp);\n }\n if (!currentSub) {\n currentSub = createSubcomponent(start);\n comp!.children.push(currentSub);\n segmentHasContent = true;\n }\n };\n\n const updatePositionsToEnd = (endPos: Position[\"end\"]) => {\n if (currentSub?.position) {\n currentSub.position.end = endPos;\n }\n if (comp?.position) {\n comp.position.end = endPos;\n }\n if (rep?.position) {\n rep.position.end = endPos;\n }\n if (field?.position) {\n field.position.end = endPos;\n }\n if (seg?.position) {\n seg.position.end = endPos;\n }\n };\n\n const processToken = (tok: Token) => {\n switch (tok.type) {\n case \"SEGMENT_END\": {\n // Use the last content position instead of the segment delimiter position\n const endPos = lastContentEnd || tok.position.start;\n updatePositionsToEnd(endPos);\n dropTrailingEmptyFieldIfPresent();\n resetState();\n return;\n }\n case \"FIELD_DELIM\": {\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n // Skip the first field delimiter after setting segment name (it separates segment name from fields)\n if (justSetSegmentName) {\n justSetSegmentName = false;\n return;\n }\n // Leading field delimiter implies an empty first field\n if (!field) {\n // Open an empty first field (already has empty subcomponent from openField)\n openField(tok.position.start);\n }\n openField(tok.position.end);\n return;\n }\n case \"REPETITION_DELIM\": {\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n if (!field) {\n openField(tok.position.start);\n }\n openRepetition(tok.position.end);\n return;\n }\n case \"COMPONENT_DELIM\": {\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n openComponent(tok.position.end);\n return;\n }\n case \"SUBCOMP_DELIM\": {\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n // Ensure there's a component to add subcomponents to\n ensureComponent(tok.position.start);\n // In empty-array mode, if comp has no children yet, add empty first subcomponent\n if (mode === \"empty\" && comp!.children.length === 0) {\n const emptySub = createSubcomponent(tok.position.start);\n comp!.children.push(emptySub);\n }\n currentSub = createSubcomponent(tok.position.end);\n comp?.children.push(currentSub);\n segmentHasContent = true;\n return;\n }\n case \"TEXT\": {\n const val = tok.value ?? \"\";\n\n // Set root start position on first token\n if (!rootStartSet) {\n root.position = {\n start: tok.position.start,\n end: tok.position.start,\n };\n rootStartSet = true;\n }\n\n // If we're expecting a segment name, this TEXT is the segment name\n if (expectingSegmentName) {\n // `tok.position` is always available for TEXT tokens\n openSegment(val, tok.position);\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n return;\n }\n\n // Otherwise, it's regular field content\n ensureForText(tok.position.start);\n if (currentSub) {\n currentSub.value += val;\n }\n updatePositionsToEnd(tok.position.end);\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n segmentHasContent = true;\n return;\n }\n default: {\n throw new Error(`Unexpected token type: ${tok.type}`);\n }\n }\n };\n\n // Do not pre-open a segment; lazily open upon first non-SEGMENT_END token.\n\n const finalize = () => {\n // Handle input that ends without an explicit segment delimiter as above.\n if (lastContentEnd && seg) {\n updatePositionsToEnd(lastContentEnd);\n }\n dropTrailingEmptyFieldIfPresent();\n if (seg && !segmentHasContent) {\n // Drop trailing empty segment if no content was added\n root.children.pop();\n }\n\n // Set root end position once at finalization using document-level end\n if (root.position && documentEnd) {\n root.position.end = documentEnd;\n } else if (!root.position) {\n // Empty document - set default position\n root.position = {\n start: { line: 1, column: 1, offset: 0 },\n end: { line: 1, column: 1, offset: 0 },\n };\n }\n\n return root;\n };\n\n function dropTrailingEmptyFieldIfPresent() {\n if (!seg || seg.children.length <= 1) {\n return;\n }\n // Drop only the final trailing empty field (created by the last delimiter),\n // preserving any intentional empty fields immediately before it.\n const lastChild = seg.children.at(-1);\n if (lastChild?.type !== \"field\") {\n return;\n }\n const lastField = lastChild as Field;\n if (isEmptyNode(lastField)) {\n seg.children.pop();\n }\n }\n\n return { processToken, finalize, root };\n}\n\n// Sync convenience wrapper over a sync Iterable token source\nexport function parseHL7v2FromIterator(\n tokens: Iterable<Token>,\n ctx: ParserContext\n): Root {\n const core = createParserCore(ctx);\n for (const tok of tokens) {\n core.processToken(tok);\n }\n return core.finalize();\n}\n","// src/tokenizer.ts\nimport type { Delimiters } from \"@rethinkhealth/hl7v2-ast\";\nimport type { Position } from \"unist\";\nimport type { ParserContext, Token, Tokenizer, TokenType } from \"./types\";\n\nconst MSH_SEGMENT_START = 0;\nconst MSH_SEGMENT_END = 3;\nconst MSH_FIELD_SEPERATOR_START = 3;\nconst MSH_FIELD_SEPERATOR_END = 4;\nconst MSH_FIELD_DELIMITER_START = 4;\nconst MSH_FIELD_DELIMITER_END = 8;\n\nexport class HL7v2Tokenizer implements Tokenizer, Iterable<Token> {\n private input = \"\";\n private i = 0;\n private line = 1;\n private col = 1;\n private delims!: Delimiters;\n\n // Only-run-once MSH bootstrap at the start of the file\n private didMshBootstrap = false;\n private pendingBootstrap: null | Array<\n | { kind: \"TEXT\"; value: string; advance: number }\n | { kind: \"FIELD_DELIM\"; advance: number }\n > = null; // queue to emit TEXT('MSH'), FIELD_DELIM, TEXT('^~\\\\&')\n\n reset(ctx: ParserContext) {\n this.input = ctx.input;\n this.delims = ctx.delimiters;\n this.i = 0;\n this.line = 1;\n this.col = 1;\n this.didMshBootstrap = false;\n this.pendingBootstrap = null;\n\n // Prepare a one-time bootstrap if file starts with MSH\n if (this.input.startsWith(\"MSH\")) {\n // Precompute MSH and MSH.2; MSH.1 is the field delimiter char at index 3\n const msh = this._slice(MSH_SEGMENT_START, MSH_SEGMENT_END);\n const msh1 = this._slice(\n MSH_FIELD_SEPERATOR_START,\n MSH_FIELD_SEPERATOR_END\n ); // the field delimiter char at index 3\n const msh2 = this._slice(\n MSH_FIELD_DELIMITER_START,\n MSH_FIELD_DELIMITER_END\n ); // may be shorter than 4 if truncated\n this.pendingBootstrap = [\n { kind: \"TEXT\", value: msh, advance: msh.length },\n { kind: \"FIELD_DELIM\", advance: 0 },\n { kind: \"TEXT\", value: msh1, advance: msh1.length },\n { kind: \"FIELD_DELIM\", advance: 0 },\n { kind: \"TEXT\", value: msh2, advance: msh2.length },\n ];\n // NOTE: we have not advanced indices yet; we will as we emit tokens\n }\n }\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: The cognitive complexity of this method is justified because it must handle the HL7v2 MSH segment bootstrap logic and multiple tokenization cases in a single method for performance and maintainability.\n next(): Token | null {\n const s = this.input;\n const n = s.length;\n if (this.i >= n && !this.pendingBootstrap?.length) {\n return null;\n }\n\n const start = { offset: this.i, line: this.line, column: this.col };\n\n // ---- One-time MSH bootstrap at file start ----\n if (!this.didMshBootstrap && this.pendingBootstrap) {\n const step = this.pendingBootstrap.shift();\n if (step) {\n if (step.kind === \"TEXT\") {\n const take = Math.min(step.advance, n - this.i);\n const out = step.value.slice(0, take);\n this._fastAdvance(out);\n if (this.pendingBootstrap.length === 0) {\n this.pendingBootstrap = null;\n this.didMshBootstrap = true;\n }\n return this._tok(\"TEXT\", out, start);\n }\n // FIELD_DELIM: advance exactly one char (the delimiter) and emit a FIELD_DELIM token\n this._advance(Math.min(step.advance, n - this.i));\n if (this.pendingBootstrap.length === 0) {\n this.pendingBootstrap = null;\n this.didMshBootstrap = true;\n }\n return this._tok(\"FIELD_DELIM\", undefined, start);\n }\n }\n\n // ---- Normal tokenization (delimiters + text) ----\n if (this.i >= n) {\n return null;\n }\n const ch = s.charAt(this.i);\n\n if (ch === this.delims.segment) {\n this._advance(1, true);\n return this._tok(\"SEGMENT_END\", undefined, start);\n }\n if (ch === this.delims.field) {\n this._advance(1);\n return this._tok(\"FIELD_DELIM\", undefined, start);\n }\n if (ch === this.delims.repetition) {\n this._advance(1);\n return this._tok(\"REPETITION_DELIM\", undefined, start);\n }\n if (ch === this.delims.component) {\n this._advance(1);\n return this._tok(\"COMPONENT_DELIM\", undefined, start);\n }\n if (ch === this.delims.subcomponent) {\n this._advance(1);\n return this._tok(\"SUBCOMP_DELIM\", undefined, start);\n }\n\n // TEXT until next delimiter or end\n let j = this.i;\n const seg = this.delims.segment,\n fld = this.delims.field,\n rep = this.delims.repetition,\n cmp = this.delims.component,\n sub = this.delims.subcomponent;\n\n while (j < s.length) {\n const c = s.charAt(j);\n if (c === seg || c === fld || c === rep || c === cmp || c === sub) {\n break;\n }\n j++;\n }\n\n const val = s.slice(this.i, j);\n this._fastAdvance(val);\n return this._tok(\"TEXT\", val, start);\n }\n\n // ---- helpers ----\n private _slice(start: number, end: number): string {\n return this.input.slice(start, Math.min(end, this.input.length));\n }\n\n private _advance(n: number, isNewline = false) {\n this.i += n;\n if (isNewline) {\n this.line += 1;\n this.col = 1;\n } else {\n this.col += n;\n }\n }\n\n private _fastAdvance(chunk: string) {\n const parts = chunk.split(this.delims.segment);\n if (parts.length > 1) {\n this.line += parts.length - 1;\n this.col = (parts.at(-1)?.length ?? 0) + 1;\n } else {\n this.col += chunk.length;\n }\n this.i += chunk.length;\n }\n\n private _tok(\n type: TokenType,\n value: string | undefined,\n start: Position[\"start\"]\n ): Token {\n const end = { offset: this.i, line: this.line, column: this.col };\n return { type, value, position: { start, end } };\n }\n\n // Iterable protocol (sync)\n [Symbol.iterator](): Iterator<Token> {\n return {\n next: () => {\n const t = this.next();\n if (t == null) {\n return { done: true, value: undefined as unknown as Token };\n }\n return { done: false, value: t };\n },\n };\n }\n}\n"],"mappings":"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","names":["DEFAULT_DELIMITERS","DEFAULT_DELIMITERS"]}
1
+ {"version":3,"sources":["../src/parser.ts","../src/preprocessor.ts","../src/processor.ts","../src/tokenizer.ts"],"sourcesContent":["import type { Root } from \"@rethinkhealth/hl7v2-ast\";\nimport type { HL7v2Settings } from \"@rethinkhealth/hl7v2-config\";\nimport { DEFAULT_DELIMITERS } from \"@rethinkhealth/hl7v2-utils\";\nimport type { Plugin, Processor } from \"unified\";\n\nimport { defaultPreprocessors, runPreprocessors } from \"./preprocessor\";\nimport { parseHL7v2FromIterator } from \"./processor\";\nimport { HL7v2Tokenizer } from \"./tokenizer\";\nimport type { ParseOptions, ParserContext, Token, Tokenizer } from \"./types\";\n\nfunction* iterateTokenizerSync(t: Tokenizer): Iterable<Token> {\n for (let tok = t.next(); tok; tok = t.next()) {\n yield tok;\n }\n}\n\nexport function parseHL7v2(\n input: string,\n opts: ParseOptions = {},\n settings?: HL7v2Settings\n): Root {\n // Merge settings: defaults < provided settings\n // Note: MSH auto-detection (via detectDelimiters preprocessor) runs after this\n // and will override delimiters if the message starts with MSH\n\n let ctx: ParserContext = {\n delimiters: {\n ...DEFAULT_DELIMITERS,\n ...(settings?.delimiters ?? {}),\n },\n emptyMode: settings?.experimental?.emptyMode,\n input,\n };\n // Run preprocessing\n ctx = runPreprocessors(ctx, opts.preprocess || defaultPreprocessors);\n // Run tokenizer\n const tokenizer = new HL7v2Tokenizer();\n // Reset tokenizer.\n tokenizer.reset(ctx);\n // Parse\n return parseHL7v2FromIterator(iterateTokenizerSync(tokenizer), ctx);\n}\n\nconst hl7v2Parser: Plugin<[ParseOptions?], string, Root> = function hl7v2Parser(\n this: Processor,\n options = {}\n) {\n this.parser = (document: string) => {\n // Get settings from processor (populated by unified-args from config)\n const settings = this.data(\"settings\");\n\n return parseHL7v2(document, options, settings);\n };\n};\n\nexport default hl7v2Parser;\n","import { DEFAULT_DELIMITERS } from \"@rethinkhealth/hl7v2-utils\";\n\nimport type { ParserContext, PreprocessorStep } from \"./types\";\n\n// PreprocessorStep is declared in `types.ts` to avoid circular imports\n\n/**\n * Step: strip UTF-8 BOM.\n */\nexport const stripBOM: PreprocessorStep = (ctx) => {\n if (ctx.input.codePointAt(0) === 0xfe_ff) {\n ctx.input = ctx.input.slice(1);\n }\n return ctx;\n};\n\n/**\n * Step: normalize newlines to the default delimiters.\n */\nexport const normalizeNewlines: PreprocessorStep = (ctx) => {\n ctx.input = ctx.input.replaceAll(/\\r?\\n/g, ctx.delimiters.segment);\n return ctx;\n};\n\n/**\n * Step: auto-detect delimiters from MSH.\n */\nexport const detectDelimiters: PreprocessorStep = (ctx) => {\n if (ctx.input.startsWith(\"MSH\")) {\n const field = ctx.input.charAt(3) || DEFAULT_DELIMITERS.field;\n const enc = ctx.input.slice(4, 8);\n const component = enc.charAt(0) || DEFAULT_DELIMITERS.component;\n const repetition = enc.charAt(1) || DEFAULT_DELIMITERS.repetition;\n const _escape = enc.charAt(2) || DEFAULT_DELIMITERS.escape;\n const subcomponent = enc.charAt(3) || DEFAULT_DELIMITERS.subcomponent;\n const { segment } = DEFAULT_DELIMITERS;\n\n ctx.delimiters = {\n component,\n escape: _escape,\n field,\n repetition,\n segment,\n subcomponent,\n };\n }\n return ctx;\n};\n\n/**\n * Default preprocessing pipeline.\n */\nexport const defaultPreprocessors: PreprocessorStep[] = [\n stripBOM,\n normalizeNewlines,\n detectDelimiters,\n];\n\n/**\n * Run the pipeline to initialize ParserContext.\n */\nexport function runPreprocessors(\n ctx: ParserContext,\n steps: PreprocessorStep[]\n): ParserContext {\n for (const step of steps) {\n // oxlint-disable-next-line no-param-reassign\n ctx = step(ctx);\n }\n\n return ctx;\n}\n","// oxlint-disable typescript/no-non-null-assertion\n// src/parser.ts\n/** biome-ignore-all lint/complexity/noExcessiveCognitiveComplexity: there are complex logic */\n/** biome-ignore-all lint/style/noNonNullAssertion: the processor uses non-null assertions */\n\nimport type {\n Component,\n Field,\n FieldRepetition,\n Root,\n Segment,\n Subcomponent,\n} from \"@rethinkhealth/hl7v2-ast\";\nimport { isEmptyNode } from \"@rethinkhealth/hl7v2-utils\";\nimport type { Position } from \"unist\";\n\nimport type { ParserContext, Token } from \"./types\";\n\n// Helper to create an empty subcomponent at a given position\nfunction createSubcomponent(start: Position[\"start\"]): Subcomponent {\n return {\n position: { end: start, start },\n type: \"subcomponent\",\n value: \"\",\n };\n}\n\n// Helper to create a component (with or without children based on mode)\nfunction createComponent(\n start: Position[\"start\"],\n mode: \"legacy\" | \"empty\" | undefined\n): Component {\n return {\n children: mode === \"empty\" ? [] : [createSubcomponent(start)],\n position: { end: start, start },\n type: \"component\",\n };\n}\n\n// Helper to create a field repetition (with or without children based on mode)\nfunction createFieldRepetition(\n start: Position[\"start\"],\n mode: \"legacy\" | \"empty\" | undefined\n): FieldRepetition {\n return {\n children: mode === \"empty\" ? [] : [createComponent(start, mode)],\n position: { end: start, start },\n type: \"field-repetition\",\n };\n}\n\n// Helper to create a field (with or without children based on mode)\nfunction createField(\n start: Position[\"start\"],\n mode: \"legacy\" | \"empty\" | undefined\n): Field {\n return {\n children: mode === \"empty\" ? [] : [createFieldRepetition(start, mode)],\n position: { end: start, start },\n type: \"field\",\n };\n}\n\n// Shared core: process a single token into mutable parse state\nfunction createParserCore(ctx: ParserContext) {\n const mode = ctx.emptyMode;\n const root: Root = {\n children: [],\n data: {\n delimiters: ctx.delimiters,\n },\n type: \"root\",\n };\n\n let seg: Segment | null = null;\n let field: Field | null = null;\n let rep: FieldRepetition | null = null;\n let comp: Component | null = null;\n let currentSub: Subcomponent | null = null;\n let segmentHasContent = false;\n let lastContentEnd: Position[\"end\"] | null = null;\n let documentEnd: Position[\"end\"] | null = null; // Track document-level end position\n let expectingSegmentName = true; // Start expecting a segment name\n let justSetSegmentName = false; // Track if we just set the segment name\n let rootStartSet = false; // Track if we've set the root start position\n\n const resetState = () => {\n seg = null;\n field = null;\n rep = null;\n comp = null;\n currentSub = null;\n segmentHasContent = false;\n lastContentEnd = null;\n expectingSegmentName = true;\n };\n\n const openSegment = (name: string, position: Position) => {\n seg = {\n children: [],\n name,\n position: { end: position.end, start: position.start },\n type: \"segment\",\n };\n root.children.push(seg);\n // Reset field-level state\n field = null;\n rep = null;\n comp = null;\n currentSub = null;\n segmentHasContent = false;\n justSetSegmentName = true;\n expectingSegmentName = false;\n };\n\n const openField = (start: Position[\"start\"]) => {\n if (!seg) {\n throw new Error(\n \"Cannot open field without an active segment. TEXT token with segment name must precede field content.\"\n );\n }\n field = createField(start, mode);\n seg.children.push(field);\n if (mode === \"empty\") {\n rep = null;\n comp = null;\n currentSub = null;\n } else {\n rep = field.children[0] ?? null;\n comp = rep?.children[0] ?? null;\n currentSub = comp?.children[0] ?? null;\n }\n segmentHasContent = true;\n };\n\n const openRepetition = (start: Position[\"start\"]) => {\n if (!field) {\n openField(start);\n // In empty-array mode, openField creates empty field\n // We need to add an empty first repetition before the delimiter\n if (mode === \"empty\") {\n const emptyRep = createFieldRepetition(start, mode);\n field!.children.push(emptyRep);\n }\n // Fall through to create the repetition after the delimiter\n }\n // In empty-array mode, if field has no children yet, add empty first rep\n if (mode === \"empty\" && field!.children.length === 0) {\n const emptyRep = createFieldRepetition(start, mode);\n field!.children.push(emptyRep);\n }\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n if (mode === \"empty\") {\n comp = null;\n currentSub = null;\n } else {\n comp = rep.children[0] ?? null;\n currentSub = comp?.children[0] ?? null;\n }\n segmentHasContent = true;\n };\n\n // Ensure there's a component to add subcomponents to (for SUBCOMP_DELIM)\n // Does NOT add empty sibling components\n const ensureComponent = (start: Position[\"start\"]) => {\n if (!field) {\n openField(start);\n }\n if (!rep) {\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n }\n if (!comp) {\n comp = createComponent(start, mode);\n rep.children.push(comp);\n }\n segmentHasContent = true;\n };\n\n // Handle COMPONENT_DELIM - adds empty component before delimiter if needed\n const openComponent = (start: Position[\"start\"]) => {\n if (!field) {\n openField(start);\n // In empty-array mode, openField creates empty field\n // We need to create rep and add empty first component\n if (mode === \"empty\") {\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n const emptyComp = createComponent(start, mode);\n rep.children.push(emptyComp);\n }\n // Fall through to create the component after the delimiter\n }\n if (!rep) {\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n // In empty-array mode, need to add empty first component before the delimiter\n if (mode === \"empty\") {\n const emptyComp = createComponent(start, mode);\n rep.children.push(emptyComp);\n }\n } else if (mode === \"empty\" && rep.children.length === 0) {\n // If rep exists but has no children, add empty first component\n const emptyComp = createComponent(start, mode);\n rep.children.push(emptyComp);\n }\n comp = createComponent(start, mode);\n rep.children.push(comp);\n currentSub = mode === \"empty\" ? null : (comp.children[0] ?? null);\n segmentHasContent = true;\n };\n\n const ensureForText = (start: Position[\"start\"]) => {\n if (!field) {\n openField(start);\n if (mode !== \"empty\") {\n return; // Everything is already set up by openField in legacy mode\n }\n // In empty-array mode, openField created empty field, need to build structure\n }\n if (!rep) {\n if (mode !== \"empty\") {\n openRepetition(start);\n return; // Everything is already set up by openRepetition in legacy mode\n }\n // In empty-array mode, need to create repetition\n rep = createFieldRepetition(start, mode);\n field!.children.push(rep);\n }\n if (!comp) {\n if (mode !== \"empty\") {\n openComponent(start);\n return; // Everything is already set up by openComponent in legacy mode\n }\n // In empty-array mode, need to create component\n comp = createComponent(start, mode);\n rep!.children.push(comp);\n }\n if (!currentSub) {\n currentSub = createSubcomponent(start);\n comp!.children.push(currentSub);\n segmentHasContent = true;\n }\n };\n\n const updatePositionsToEnd = (endPos: Position[\"end\"]) => {\n if (currentSub?.position) {\n currentSub.position.end = endPos;\n }\n if (comp?.position) {\n comp.position.end = endPos;\n }\n if (rep?.position) {\n rep.position.end = endPos;\n }\n if (field?.position) {\n field.position.end = endPos;\n }\n if (seg?.position) {\n seg.position.end = endPos;\n }\n };\n\n const processToken = (tok: Token) => {\n switch (tok.type) {\n case \"SEGMENT_END\": {\n // Use the last content position instead of the segment delimiter position\n const endPos = lastContentEnd || tok.position.start;\n updatePositionsToEnd(endPos);\n dropTrailingEmptyFieldIfPresent();\n resetState();\n return;\n }\n case \"FIELD_DELIM\": {\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n // Skip the first field delimiter after setting segment name (it separates segment name from fields)\n if (justSetSegmentName) {\n justSetSegmentName = false;\n return;\n }\n // Leading field delimiter implies an empty first field\n if (!field) {\n // Open an empty first field (already has empty subcomponent from openField)\n openField(tok.position.start);\n }\n openField(tok.position.end);\n return;\n }\n case \"REPETITION_DELIM\": {\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n if (!field) {\n openField(tok.position.start);\n }\n openRepetition(tok.position.end);\n return;\n }\n case \"COMPONENT_DELIM\": {\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n openComponent(tok.position.end);\n return;\n }\n case \"SUBCOMP_DELIM\": {\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n // Ensure there's a component to add subcomponents to\n ensureComponent(tok.position.start);\n // In empty-array mode, if comp has no children yet, add empty first subcomponent\n if (mode === \"empty\" && comp!.children.length === 0) {\n const emptySub = createSubcomponent(tok.position.start);\n comp!.children.push(emptySub);\n }\n currentSub = createSubcomponent(tok.position.end);\n comp?.children.push(currentSub);\n segmentHasContent = true;\n return;\n }\n case \"TEXT\": {\n const val = tok.value ?? \"\";\n\n // Set root start position on first token\n if (!rootStartSet) {\n root.position = {\n end: tok.position.start,\n start: tok.position.start,\n };\n rootStartSet = true;\n }\n\n // If we're expecting a segment name, this TEXT is the segment name\n if (expectingSegmentName) {\n // `tok.position` is always available for TEXT tokens\n openSegment(val, tok.position);\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n return;\n }\n\n // Otherwise, it's regular field content\n ensureForText(tok.position.start);\n if (currentSub) {\n currentSub.value += val;\n }\n updatePositionsToEnd(tok.position.end);\n lastContentEnd = tok.position.end;\n documentEnd = tok.position.end;\n segmentHasContent = true;\n return;\n }\n default: {\n throw new Error(`Unexpected token type: ${tok.type}`);\n }\n }\n };\n\n // Do not pre-open a segment; lazily open upon first non-SEGMENT_END token.\n\n const finalize = () => {\n // Handle input that ends without an explicit segment delimiter as above.\n if (lastContentEnd && seg) {\n updatePositionsToEnd(lastContentEnd);\n }\n dropTrailingEmptyFieldIfPresent();\n if (seg && !segmentHasContent) {\n // Drop trailing empty segment if no content was added\n root.children.pop();\n }\n\n // Set root end position once at finalization using document-level end\n if (root.position && documentEnd) {\n root.position.end = documentEnd;\n } else if (!root.position) {\n // Empty document - set default position\n root.position = {\n end: { column: 1, line: 1, offset: 0 },\n start: { column: 1, line: 1, offset: 0 },\n };\n }\n\n return root;\n };\n\n function dropTrailingEmptyFieldIfPresent() {\n if (!seg || seg.children.length === 0) {\n return;\n }\n // Drop only the final trailing empty field (created by the last delimiter),\n // preserving any intentional empty fields immediately before it.\n const lastChild = seg.children.at(-1);\n if (lastChild?.type !== \"field\") {\n return;\n }\n const lastField = lastChild as Field;\n if (isEmptyNode(lastField)) {\n seg.children.pop();\n }\n }\n\n return { finalize, processToken, root };\n}\n\n// Sync convenience wrapper over a sync Iterable token source\nexport function parseHL7v2FromIterator(\n tokens: Iterable<Token>,\n ctx: ParserContext\n): Root {\n const core = createParserCore(ctx);\n for (const tok of tokens) {\n core.processToken(tok);\n }\n return core.finalize();\n}\n","// src/tokenizer.ts\nimport type { Delimiters } from \"@rethinkhealth/hl7v2-ast\";\nimport type { Position } from \"unist\";\n\nimport type { ParserContext, Token, Tokenizer, TokenType } from \"./types\";\n\nconst MSH_SEGMENT_START = 0;\nconst MSH_SEGMENT_END = 3;\nconst MSH_FIELD_SEPERATOR_START = 3;\nconst MSH_FIELD_SEPERATOR_END = 4;\nconst MSH_FIELD_DELIMITER_START = 4;\nconst MSH_FIELD_DELIMITER_END = 8;\n\nexport class HL7v2Tokenizer implements Tokenizer, Iterable<Token> {\n private input = \"\";\n private i = 0;\n private line = 1;\n private col = 1;\n private delims!: Delimiters;\n\n // Only-run-once MSH bootstrap at the start of the file\n private didMshBootstrap = false;\n private pendingBootstrap: null | Array<\n | { kind: \"TEXT\"; value: string; advance: number }\n | { kind: \"FIELD_DELIM\"; advance: number }\n > = null; // queue to emit TEXT('MSH'), FIELD_DELIM, TEXT('^~\\\\&')\n\n reset(ctx: ParserContext) {\n this.input = ctx.input;\n this.delims = ctx.delimiters;\n this.i = 0;\n this.line = 1;\n this.col = 1;\n this.didMshBootstrap = false;\n this.pendingBootstrap = null;\n\n // Prepare a one-time bootstrap if file starts with MSH\n if (this.input.startsWith(\"MSH\")) {\n // Precompute MSH and MSH.2; MSH.1 is the field delimiter char at index 3\n const msh = this._slice(MSH_SEGMENT_START, MSH_SEGMENT_END);\n const msh1 = this._slice(\n MSH_FIELD_SEPERATOR_START,\n MSH_FIELD_SEPERATOR_END\n ); // the field delimiter char at index 3\n const msh2 = this._slice(\n MSH_FIELD_DELIMITER_START,\n MSH_FIELD_DELIMITER_END\n ); // may be shorter than 4 if truncated\n this.pendingBootstrap = [\n { advance: msh.length, kind: \"TEXT\", value: msh },\n { advance: 0, kind: \"FIELD_DELIM\" },\n { advance: msh1.length, kind: \"TEXT\", value: msh1 },\n { advance: 0, kind: \"FIELD_DELIM\" },\n { advance: msh2.length, kind: \"TEXT\", value: msh2 },\n ];\n // NOTE: we have not advanced indices yet; we will as we emit tokens\n }\n }\n\n // oxlint-disable-next-line complexity\n next(): Token | null {\n const s = this.input;\n const n = s.length;\n if (this.i >= n && !this.pendingBootstrap?.length) {\n return null;\n }\n\n const start = { column: this.col, line: this.line, offset: this.i };\n\n // ---- One-time MSH bootstrap at file start ----\n if (!this.didMshBootstrap && this.pendingBootstrap) {\n const step = this.pendingBootstrap.shift();\n if (step) {\n if (step.kind === \"TEXT\") {\n const take = Math.min(step.advance, n - this.i);\n const out = step.value.slice(0, take);\n this._fastAdvance(out);\n if (this.pendingBootstrap.length === 0) {\n this.pendingBootstrap = null;\n this.didMshBootstrap = true;\n }\n return this._tok(\"TEXT\", out, start);\n }\n // FIELD_DELIM: advance exactly one char (the delimiter) and emit a FIELD_DELIM token\n this._advance(Math.min(step.advance, n - this.i));\n if (this.pendingBootstrap.length === 0) {\n this.pendingBootstrap = null;\n this.didMshBootstrap = true;\n }\n return this._tok(\"FIELD_DELIM\", undefined, start);\n }\n }\n\n // ---- Normal tokenization (delimiters + text) ----\n if (this.i >= n) {\n return null;\n }\n const ch = s.charAt(this.i);\n\n if (ch === this.delims.segment) {\n this._advance(1, true);\n return this._tok(\"SEGMENT_END\", undefined, start);\n }\n if (ch === this.delims.field) {\n this._advance(1);\n return this._tok(\"FIELD_DELIM\", undefined, start);\n }\n if (ch === this.delims.repetition) {\n this._advance(1);\n return this._tok(\"REPETITION_DELIM\", undefined, start);\n }\n if (ch === this.delims.component) {\n this._advance(1);\n return this._tok(\"COMPONENT_DELIM\", undefined, start);\n }\n if (ch === this.delims.subcomponent) {\n this._advance(1);\n return this._tok(\"SUBCOMP_DELIM\", undefined, start);\n }\n\n // TEXT until next delimiter or end\n let j = this.i;\n const cmp = this.delims.component,\n fld = this.delims.field,\n rep = this.delims.repetition,\n seg = this.delims.segment,\n sub = this.delims.subcomponent;\n\n while (j < s.length) {\n const c = s.charAt(j);\n if (c === seg || c === fld || c === rep || c === cmp || c === sub) {\n break;\n }\n j += 1;\n }\n\n const val = s.slice(this.i, j);\n this._fastAdvance(val);\n return this._tok(\"TEXT\", val, start);\n }\n\n // ---- helpers ----\n private _slice(start: number, end: number): string {\n return this.input.slice(start, Math.min(end, this.input.length));\n }\n\n private _advance(n: number, isNewline = false) {\n this.i += n;\n if (isNewline) {\n this.line += 1;\n this.col = 1;\n } else {\n this.col += n;\n }\n }\n\n private _fastAdvance(chunk: string) {\n const parts = chunk.split(this.delims.segment);\n if (parts.length > 1) {\n this.line += parts.length - 1;\n this.col = (parts.at(-1)?.length ?? 0) + 1;\n } else {\n this.col += chunk.length;\n }\n this.i += chunk.length;\n }\n\n private _tok(\n type: TokenType,\n value: string | undefined,\n start: Position[\"start\"]\n ): Token {\n const end = { column: this.col, line: this.line, offset: this.i };\n return { position: { end, start }, type, value };\n }\n\n // Iterable protocol (sync)\n [Symbol.iterator](): Iterator<Token> {\n return {\n next: () => {\n const t = this.next();\n if (!t) {\n return { done: true, value: undefined as unknown as Token };\n }\n return { done: false, value: t };\n },\n };\n }\n}\n"],"mappings":";AAEA,SAAS,sBAAAA,2BAA0B;;;ACFnC,SAAS,0BAA0B;AAS5B,IAAM,WAA6B,CAAC,QAAQ;AACjD,MAAI,IAAI,MAAM,YAAY,CAAC,MAAM,OAAS;AACxC,QAAI,QAAQ,IAAI,MAAM,MAAM,CAAC;AAAA,EAC/B;AACA,SAAO;AACT;AAKO,IAAM,oBAAsC,CAAC,QAAQ;AAC1D,MAAI,QAAQ,IAAI,MAAM,WAAW,UAAU,IAAI,WAAW,OAAO;AACjE,SAAO;AACT;AAKO,IAAM,mBAAqC,CAAC,QAAQ;AACzD,MAAI,IAAI,MAAM,WAAW,KAAK,GAAG;AAC/B,UAAM,QAAQ,IAAI,MAAM,OAAO,CAAC,KAAK,mBAAmB;AACxD,UAAM,MAAM,IAAI,MAAM,MAAM,GAAG,CAAC;AAChC,UAAM,YAAY,IAAI,OAAO,CAAC,KAAK,mBAAmB;AACtD,UAAM,aAAa,IAAI,OAAO,CAAC,KAAK,mBAAmB;AACvD,UAAM,UAAU,IAAI,OAAO,CAAC,KAAK,mBAAmB;AACpD,UAAM,eAAe,IAAI,OAAO,CAAC,KAAK,mBAAmB;AACzD,UAAM,EAAE,QAAQ,IAAI;AAEpB,QAAI,aAAa;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKO,IAAM,uBAA2C;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AACF;AAKO,SAAS,iBACd,KACA,OACe;AACf,aAAW,QAAQ,OAAO;AAExB,UAAM,KAAK,GAAG;AAAA,EAChB;AAEA,SAAO;AACT;;;AC1DA,SAAS,mBAAmB;AAM5B,SAAS,mBAAmB,OAAwC;AAClE,SAAO;AAAA,IACL,UAAU,EAAE,KAAK,OAAO,MAAM;AAAA,IAC9B,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF;AAGA,SAAS,gBACP,OACA,MACW;AACX,SAAO;AAAA,IACL,UAAU,SAAS,UAAU,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC;AAAA,IAC5D,UAAU,EAAE,KAAK,OAAO,MAAM;AAAA,IAC9B,MAAM;AAAA,EACR;AACF;AAGA,SAAS,sBACP,OACA,MACiB;AACjB,SAAO;AAAA,IACL,UAAU,SAAS,UAAU,CAAC,IAAI,CAAC,gBAAgB,OAAO,IAAI,CAAC;AAAA,IAC/D,UAAU,EAAE,KAAK,OAAO,MAAM;AAAA,IAC9B,MAAM;AAAA,EACR;AACF;AAGA,SAAS,YACP,OACA,MACO;AACP,SAAO;AAAA,IACL,UAAU,SAAS,UAAU,CAAC,IAAI,CAAC,sBAAsB,OAAO,IAAI,CAAC;AAAA,IACrE,UAAU,EAAE,KAAK,OAAO,MAAM;AAAA,IAC9B,MAAM;AAAA,EACR;AACF;AAGA,SAAS,iBAAiB,KAAoB;AAC5C,QAAM,OAAO,IAAI;AACjB,QAAM,OAAa;AAAA,IACjB,UAAU,CAAC;AAAA,IACX,MAAM;AAAA,MACJ,YAAY,IAAI;AAAA,IAClB;AAAA,IACA,MAAM;AAAA,EACR;AAEA,MAAI,MAAsB;AAC1B,MAAI,QAAsB;AAC1B,MAAI,MAA8B;AAClC,MAAI,OAAyB;AAC7B,MAAI,aAAkC;AACtC,MAAI,oBAAoB;AACxB,MAAI,iBAAyC;AAC7C,MAAI,cAAsC;AAC1C,MAAI,uBAAuB;AAC3B,MAAI,qBAAqB;AACzB,MAAI,eAAe;AAEnB,QAAM,aAAa,MAAM;AACvB,UAAM;AACN,YAAQ;AACR,UAAM;AACN,WAAO;AACP,iBAAa;AACb,wBAAoB;AACpB,qBAAiB;AACjB,2BAAuB;AAAA,EACzB;AAEA,QAAM,cAAc,CAAC,MAAc,aAAuB;AACxD,UAAM;AAAA,MACJ,UAAU,CAAC;AAAA,MACX;AAAA,MACA,UAAU,EAAE,KAAK,SAAS,KAAK,OAAO,SAAS,MAAM;AAAA,MACrD,MAAM;AAAA,IACR;AACA,SAAK,SAAS,KAAK,GAAG;AAEtB,YAAQ;AACR,UAAM;AACN,WAAO;AACP,iBAAa;AACb,wBAAoB;AACpB,yBAAqB;AACrB,2BAAuB;AAAA,EACzB;AAEA,QAAM,YAAY,CAAC,UAA6B;AAC9C,QAAI,CAAC,KAAK;AACR,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,YAAQ,YAAY,OAAO,IAAI;AAC/B,QAAI,SAAS,KAAK,KAAK;AACvB,QAAI,SAAS,SAAS;AACpB,YAAM;AACN,aAAO;AACP,mBAAa;AAAA,IACf,OAAO;AACL,YAAM,MAAM,SAAS,CAAC,KAAK;AAC3B,aAAO,KAAK,SAAS,CAAC,KAAK;AAC3B,mBAAa,MAAM,SAAS,CAAC,KAAK;AAAA,IACpC;AACA,wBAAoB;AAAA,EACtB;AAEA,QAAM,iBAAiB,CAAC,UAA6B;AACnD,QAAI,CAAC,OAAO;AACV,gBAAU,KAAK;AAGf,UAAI,SAAS,SAAS;AACpB,cAAM,WAAW,sBAAsB,OAAO,IAAI;AAClD,cAAO,SAAS,KAAK,QAAQ;AAAA,MAC/B;AAAA,IAEF;AAEA,QAAI,SAAS,WAAW,MAAO,SAAS,WAAW,GAAG;AACpD,YAAM,WAAW,sBAAsB,OAAO,IAAI;AAClD,YAAO,SAAS,KAAK,QAAQ;AAAA,IAC/B;AACA,UAAM,sBAAsB,OAAO,IAAI;AACvC,UAAO,SAAS,KAAK,GAAG;AACxB,QAAI,SAAS,SAAS;AACpB,aAAO;AACP,mBAAa;AAAA,IACf,OAAO;AACL,aAAO,IAAI,SAAS,CAAC,KAAK;AAC1B,mBAAa,MAAM,SAAS,CAAC,KAAK;AAAA,IACpC;AACA,wBAAoB;AAAA,EACtB;AAIA,QAAM,kBAAkB,CAAC,UAA6B;AACpD,QAAI,CAAC,OAAO;AACV,gBAAU,KAAK;AAAA,IACjB;AACA,QAAI,CAAC,KAAK;AACR,YAAM,sBAAsB,OAAO,IAAI;AACvC,YAAO,SAAS,KAAK,GAAG;AAAA,IAC1B;AACA,QAAI,CAAC,MAAM;AACT,aAAO,gBAAgB,OAAO,IAAI;AAClC,UAAI,SAAS,KAAK,IAAI;AAAA,IACxB;AACA,wBAAoB;AAAA,EACtB;AAGA,QAAM,gBAAgB,CAAC,UAA6B;AAClD,QAAI,CAAC,OAAO;AACV,gBAAU,KAAK;AAGf,UAAI,SAAS,SAAS;AACpB,cAAM,sBAAsB,OAAO,IAAI;AACvC,cAAO,SAAS,KAAK,GAAG;AACxB,cAAM,YAAY,gBAAgB,OAAO,IAAI;AAC7C,YAAI,SAAS,KAAK,SAAS;AAAA,MAC7B;AAAA,IAEF;AACA,QAAI,CAAC,KAAK;AACR,YAAM,sBAAsB,OAAO,IAAI;AACvC,YAAO,SAAS,KAAK,GAAG;AAExB,UAAI,SAAS,SAAS;AACpB,cAAM,YAAY,gBAAgB,OAAO,IAAI;AAC7C,YAAI,SAAS,KAAK,SAAS;AAAA,MAC7B;AAAA,IACF,WAAW,SAAS,WAAW,IAAI,SAAS,WAAW,GAAG;AAExD,YAAM,YAAY,gBAAgB,OAAO,IAAI;AAC7C,UAAI,SAAS,KAAK,SAAS;AAAA,IAC7B;AACA,WAAO,gBAAgB,OAAO,IAAI;AAClC,QAAI,SAAS,KAAK,IAAI;AACtB,iBAAa,SAAS,UAAU,OAAQ,KAAK,SAAS,CAAC,KAAK;AAC5D,wBAAoB;AAAA,EACtB;AAEA,QAAM,gBAAgB,CAAC,UAA6B;AAClD,QAAI,CAAC,OAAO;AACV,gBAAU,KAAK;AACf,UAAI,SAAS,SAAS;AACpB;AAAA,MACF;AAAA,IAEF;AACA,QAAI,CAAC,KAAK;AACR,UAAI,SAAS,SAAS;AACpB,uBAAe,KAAK;AACpB;AAAA,MACF;AAEA,YAAM,sBAAsB,OAAO,IAAI;AACvC,YAAO,SAAS,KAAK,GAAG;AAAA,IAC1B;AACA,QAAI,CAAC,MAAM;AACT,UAAI,SAAS,SAAS;AACpB,sBAAc,KAAK;AACnB;AAAA,MACF;AAEA,aAAO,gBAAgB,OAAO,IAAI;AAClC,UAAK,SAAS,KAAK,IAAI;AAAA,IACzB;AACA,QAAI,CAAC,YAAY;AACf,mBAAa,mBAAmB,KAAK;AACrC,WAAM,SAAS,KAAK,UAAU;AAC9B,0BAAoB;AAAA,IACtB;AAAA,EACF;AAEA,QAAM,uBAAuB,CAAC,WAA4B;AACxD,QAAI,YAAY,UAAU;AACxB,iBAAW,SAAS,MAAM;AAAA,IAC5B;AACA,QAAI,MAAM,UAAU;AAClB,WAAK,SAAS,MAAM;AAAA,IACtB;AACA,QAAI,KAAK,UAAU;AACjB,UAAI,SAAS,MAAM;AAAA,IACrB;AACA,QAAI,OAAO,UAAU;AACnB,YAAM,SAAS,MAAM;AAAA,IACvB;AACA,QAAI,KAAK,UAAU;AACjB,UAAI,SAAS,MAAM;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,QAAe;AACnC,YAAQ,IAAI,MAAM;AAAA,MAChB,KAAK,eAAe;AAElB,cAAM,SAAS,kBAAkB,IAAI,SAAS;AAC9C,6BAAqB,MAAM;AAC3B,wCAAgC;AAChC,mBAAW;AACX;AAAA,MACF;AAAA,MACA,KAAK,eAAe;AAClB,yBAAiB,IAAI,SAAS;AAC9B,sBAAc,IAAI,SAAS;AAE3B,YAAI,oBAAoB;AACtB,+BAAqB;AACrB;AAAA,QACF;AAEA,YAAI,CAAC,OAAO;AAEV,oBAAU,IAAI,SAAS,KAAK;AAAA,QAC9B;AACA,kBAAU,IAAI,SAAS,GAAG;AAC1B;AAAA,MACF;AAAA,MACA,KAAK,oBAAoB;AACvB,yBAAiB,IAAI,SAAS;AAC9B,sBAAc,IAAI,SAAS;AAC3B,YAAI,CAAC,OAAO;AACV,oBAAU,IAAI,SAAS,KAAK;AAAA,QAC9B;AACA,uBAAe,IAAI,SAAS,GAAG;AAC/B;AAAA,MACF;AAAA,MACA,KAAK,mBAAmB;AACtB,yBAAiB,IAAI,SAAS;AAC9B,sBAAc,IAAI,SAAS;AAC3B,sBAAc,IAAI,SAAS,GAAG;AAC9B;AAAA,MACF;AAAA,MACA,KAAK,iBAAiB;AACpB,yBAAiB,IAAI,SAAS;AAC9B,sBAAc,IAAI,SAAS;AAE3B,wBAAgB,IAAI,SAAS,KAAK;AAElC,YAAI,SAAS,WAAW,KAAM,SAAS,WAAW,GAAG;AACnD,gBAAM,WAAW,mBAAmB,IAAI,SAAS,KAAK;AACtD,eAAM,SAAS,KAAK,QAAQ;AAAA,QAC9B;AACA,qBAAa,mBAAmB,IAAI,SAAS,GAAG;AAChD,cAAM,SAAS,KAAK,UAAU;AAC9B,4BAAoB;AACpB;AAAA,MACF;AAAA,MACA,KAAK,QAAQ;AACX,cAAM,MAAM,IAAI,SAAS;AAGzB,YAAI,CAAC,cAAc;AACjB,eAAK,WAAW;AAAA,YACd,KAAK,IAAI,SAAS;AAAA,YAClB,OAAO,IAAI,SAAS;AAAA,UACtB;AACA,yBAAe;AAAA,QACjB;AAGA,YAAI,sBAAsB;AAExB,sBAAY,KAAK,IAAI,QAAQ;AAC7B,2BAAiB,IAAI,SAAS;AAC9B,wBAAc,IAAI,SAAS;AAC3B;AAAA,QACF;AAGA,sBAAc,IAAI,SAAS,KAAK;AAChC,YAAI,YAAY;AACd,qBAAW,SAAS;AAAA,QACtB;AACA,6BAAqB,IAAI,SAAS,GAAG;AACrC,yBAAiB,IAAI,SAAS;AAC9B,sBAAc,IAAI,SAAS;AAC3B,4BAAoB;AACpB;AAAA,MACF;AAAA,MACA,SAAS;AACP,cAAM,IAAI,MAAM,0BAA0B,IAAI,IAAI,EAAE;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAIA,QAAM,WAAW,MAAM;AAErB,QAAI,kBAAkB,KAAK;AACzB,2BAAqB,cAAc;AAAA,IACrC;AACA,oCAAgC;AAChC,QAAI,OAAO,CAAC,mBAAmB;AAE7B,WAAK,SAAS,IAAI;AAAA,IACpB;AAGA,QAAI,KAAK,YAAY,aAAa;AAChC,WAAK,SAAS,MAAM;AAAA,IACtB,WAAW,CAAC,KAAK,UAAU;AAEzB,WAAK,WAAW;AAAA,QACd,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,EAAE;AAAA,QACrC,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,EAAE;AAAA,MACzC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,kCAAkC;AACzC,QAAI,CAAC,OAAO,IAAI,SAAS,WAAW,GAAG;AACrC;AAAA,IACF;AAGA,UAAM,YAAY,IAAI,SAAS,GAAG,EAAE;AACpC,QAAI,WAAW,SAAS,SAAS;AAC/B;AAAA,IACF;AACA,UAAM,YAAY;AAClB,QAAI,YAAY,SAAS,GAAG;AAC1B,UAAI,SAAS,IAAI;AAAA,IACnB;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,cAAc,KAAK;AACxC;AAGO,SAAS,uBACd,QACA,KACM;AACN,QAAM,OAAO,iBAAiB,GAAG;AACjC,aAAW,OAAO,QAAQ;AACxB,SAAK,aAAa,GAAG;AAAA,EACvB;AACA,SAAO,KAAK,SAAS;AACvB;;;ACxZA,IAAM,oBAAoB;AAC1B,IAAM,kBAAkB;AACxB,IAAM,4BAA4B;AAClC,IAAM,0BAA0B;AAChC,IAAM,4BAA4B;AAClC,IAAM,0BAA0B;AAEzB,IAAM,iBAAN,MAA2D;AAAA,EACxD,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN;AAAA;AAAA,EAGA,kBAAkB;AAAA,EAClB,mBAGJ;AAAA;AAAA,EAEJ,MAAM,KAAoB;AACxB,SAAK,QAAQ,IAAI;AACjB,SAAK,SAAS,IAAI;AAClB,SAAK,IAAI;AACT,SAAK,OAAO;AACZ,SAAK,MAAM;AACX,SAAK,kBAAkB;AACvB,SAAK,mBAAmB;AAGxB,QAAI,KAAK,MAAM,WAAW,KAAK,GAAG;AAEhC,YAAM,MAAM,KAAK,OAAO,mBAAmB,eAAe;AAC1D,YAAM,OAAO,KAAK;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AACA,YAAM,OAAO,KAAK;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AACA,WAAK,mBAAmB;AAAA,QACtB,EAAE,SAAS,IAAI,QAAQ,MAAM,QAAQ,OAAO,IAAI;AAAA,QAChD,EAAE,SAAS,GAAG,MAAM,cAAc;AAAA,QAClC,EAAE,SAAS,KAAK,QAAQ,MAAM,QAAQ,OAAO,KAAK;AAAA,QAClD,EAAE,SAAS,GAAG,MAAM,cAAc;AAAA,QAClC,EAAE,SAAS,KAAK,QAAQ,MAAM,QAAQ,OAAO,KAAK;AAAA,MACpD;AAAA,IAEF;AAAA,EACF;AAAA;AAAA,EAGA,OAAqB;AACnB,UAAM,IAAI,KAAK;AACf,UAAM,IAAI,EAAE;AACZ,QAAI,KAAK,KAAK,KAAK,CAAC,KAAK,kBAAkB,QAAQ;AACjD,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,EAAE,QAAQ,KAAK,KAAK,MAAM,KAAK,MAAM,QAAQ,KAAK,EAAE;AAGlE,QAAI,CAAC,KAAK,mBAAmB,KAAK,kBAAkB;AAClD,YAAM,OAAO,KAAK,iBAAiB,MAAM;AACzC,UAAI,MAAM;AACR,YAAI,KAAK,SAAS,QAAQ;AACxB,gBAAM,OAAO,KAAK,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC;AAC9C,gBAAM,MAAM,KAAK,MAAM,MAAM,GAAG,IAAI;AACpC,eAAK,aAAa,GAAG;AACrB,cAAI,KAAK,iBAAiB,WAAW,GAAG;AACtC,iBAAK,mBAAmB;AACxB,iBAAK,kBAAkB;AAAA,UACzB;AACA,iBAAO,KAAK,KAAK,QAAQ,KAAK,KAAK;AAAA,QACrC;AAEA,aAAK,SAAS,KAAK,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC;AAChD,YAAI,KAAK,iBAAiB,WAAW,GAAG;AACtC,eAAK,mBAAmB;AACxB,eAAK,kBAAkB;AAAA,QACzB;AACA,eAAO,KAAK,KAAK,eAAe,QAAW,KAAK;AAAA,MAClD;AAAA,IACF;AAGA,QAAI,KAAK,KAAK,GAAG;AACf,aAAO;AAAA,IACT;AACA,UAAM,KAAK,EAAE,OAAO,KAAK,CAAC;AAE1B,QAAI,OAAO,KAAK,OAAO,SAAS;AAC9B,WAAK,SAAS,GAAG,IAAI;AACrB,aAAO,KAAK,KAAK,eAAe,QAAW,KAAK;AAAA,IAClD;AACA,QAAI,OAAO,KAAK,OAAO,OAAO;AAC5B,WAAK,SAAS,CAAC;AACf,aAAO,KAAK,KAAK,eAAe,QAAW,KAAK;AAAA,IAClD;AACA,QAAI,OAAO,KAAK,OAAO,YAAY;AACjC,WAAK,SAAS,CAAC;AACf,aAAO,KAAK,KAAK,oBAAoB,QAAW,KAAK;AAAA,IACvD;AACA,QAAI,OAAO,KAAK,OAAO,WAAW;AAChC,WAAK,SAAS,CAAC;AACf,aAAO,KAAK,KAAK,mBAAmB,QAAW,KAAK;AAAA,IACtD;AACA,QAAI,OAAO,KAAK,OAAO,cAAc;AACnC,WAAK,SAAS,CAAC;AACf,aAAO,KAAK,KAAK,iBAAiB,QAAW,KAAK;AAAA,IACpD;AAGA,QAAI,IAAI,KAAK;AACb,UAAM,MAAM,KAAK,OAAO,WACtB,MAAM,KAAK,OAAO,OAClB,MAAM,KAAK,OAAO,YAClB,MAAM,KAAK,OAAO,SAClB,MAAM,KAAK,OAAO;AAEpB,WAAO,IAAI,EAAE,QAAQ;AACnB,YAAM,IAAI,EAAE,OAAO,CAAC;AACpB,UAAI,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM,KAAK;AACjE;AAAA,MACF;AACA,WAAK;AAAA,IACP;AAEA,UAAM,MAAM,EAAE,MAAM,KAAK,GAAG,CAAC;AAC7B,SAAK,aAAa,GAAG;AACrB,WAAO,KAAK,KAAK,QAAQ,KAAK,KAAK;AAAA,EACrC;AAAA;AAAA,EAGQ,OAAO,OAAe,KAAqB;AACjD,WAAO,KAAK,MAAM,MAAM,OAAO,KAAK,IAAI,KAAK,KAAK,MAAM,MAAM,CAAC;AAAA,EACjE;AAAA,EAEQ,SAAS,GAAW,YAAY,OAAO;AAC7C,SAAK,KAAK;AACV,QAAI,WAAW;AACb,WAAK,QAAQ;AACb,WAAK,MAAM;AAAA,IACb,OAAO;AACL,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA,EAEQ,aAAa,OAAe;AAClC,UAAM,QAAQ,MAAM,MAAM,KAAK,OAAO,OAAO;AAC7C,QAAI,MAAM,SAAS,GAAG;AACpB,WAAK,QAAQ,MAAM,SAAS;AAC5B,WAAK,OAAO,MAAM,GAAG,EAAE,GAAG,UAAU,KAAK;AAAA,IAC3C,OAAO;AACL,WAAK,OAAO,MAAM;AAAA,IACpB;AACA,SAAK,KAAK,MAAM;AAAA,EAClB;AAAA,EAEQ,KACN,MACA,OACA,OACO;AACP,UAAM,MAAM,EAAE,QAAQ,KAAK,KAAK,MAAM,KAAK,MAAM,QAAQ,KAAK,EAAE;AAChE,WAAO,EAAE,UAAU,EAAE,KAAK,MAAM,GAAG,MAAM,MAAM;AAAA,EACjD;AAAA;AAAA,EAGA,CAAC,OAAO,QAAQ,IAAqB;AACnC,WAAO;AAAA,MACL,MAAM,MAAM;AACV,cAAM,IAAI,KAAK,KAAK;AACpB,YAAI,CAAC,GAAG;AACN,iBAAO,EAAE,MAAM,MAAM,OAAO,OAA8B;AAAA,QAC5D;AACA,eAAO,EAAE,MAAM,OAAO,OAAO,EAAE;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;;;AHlLA,UAAU,qBAAqB,GAA+B;AAC5D,WAAS,MAAM,EAAE,KAAK,GAAG,KAAK,MAAM,EAAE,KAAK,GAAG;AAC5C,UAAM;AAAA,EACR;AACF;AAEO,SAAS,WACd,OACA,OAAqB,CAAC,GACtB,UACM;AAKN,MAAI,MAAqB;AAAA,IACvB,YAAY;AAAA,MACV,GAAGC;AAAA,MACH,GAAI,UAAU,cAAc,CAAC;AAAA,IAC/B;AAAA,IACA,WAAW,UAAU,cAAc;AAAA,IACnC;AAAA,EACF;AAEA,QAAM,iBAAiB,KAAK,KAAK,cAAc,oBAAoB;AAEnE,QAAM,YAAY,IAAI,eAAe;AAErC,YAAU,MAAM,GAAG;AAEnB,SAAO,uBAAuB,qBAAqB,SAAS,GAAG,GAAG;AACpE;AAEA,IAAM,cAAqD,SAASC,aAElE,UAAU,CAAC,GACX;AACA,OAAK,SAAS,CAAC,aAAqB;AAElC,UAAM,WAAW,KAAK,KAAK,UAAU;AAErC,WAAO,WAAW,UAAU,SAAS,QAAQ;AAAA,EAC/C;AACF;AAEA,IAAO,iBAAQ;","names":["DEFAULT_DELIMITERS","DEFAULT_DELIMITERS","hl7v2Parser"]}
package/dist/parser.d.ts CHANGED
@@ -5,3 +5,4 @@ import type { ParseOptions } from "./types";
5
5
  export declare function parseHL7v2(input: string, opts?: ParseOptions, settings?: HL7v2Settings): Root;
6
6
  declare const hl7v2Parser: Plugin<[ParseOptions?], string, Root>;
7
7
  export default hl7v2Parser;
8
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,OAAO,KAAK,EAAE,MAAM,EAAa,MAAM,SAAS,CAAC;AAKjD,OAAO,KAAK,EAAE,YAAY,EAAmC,MAAM,SAAS,CAAC;AAQ7E,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,YAAiB,EACvB,QAAQ,CAAC,EAAE,aAAa,GACvB,IAAI,CAqBN;AAED,QAAA,MAAM,WAAW,EAAE,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAUtD,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -19,3 +19,4 @@ export declare const defaultPreprocessors: PreprocessorStep[];
19
19
  * Run the pipeline to initialize ParserContext.
20
20
  */
21
21
  export declare function runPreprocessors(ctx: ParserContext, steps: PreprocessorStep[]): ParserContext;
22
+ //# sourceMappingURL=preprocessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preprocessor.d.ts","sourceRoot":"","sources":["../src/preprocessor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAI/D;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,gBAKtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,gBAG/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,gBAoB9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,gBAAgB,EAIlD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,gBAAgB,EAAE,GACxB,aAAa,CAOf"}
@@ -3,3 +3,4 @@
3
3
  import type { Root } from "@rethinkhealth/hl7v2-ast";
4
4
  import type { ParserContext, Token } from "./types";
5
5
  export declare function parseHL7v2FromIterator(tokens: Iterable<Token>, ctx: ParserContext): Root;
6
+ //# sourceMappingURL=processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processor.d.ts","sourceRoot":"","sources":["../src/processor.ts"],"names":[],"mappings":"AAEA,+FAA+F;AAC/F,6FAA6F;AAE7F,OAAO,KAAK,EAIV,IAAI,EAGL,MAAM,0BAA0B,CAAC;AAIlC,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAqYpD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,EACvB,GAAG,EAAE,aAAa,GACjB,IAAI,CAMN"}
@@ -15,3 +15,4 @@ export declare class HL7v2Tokenizer implements Tokenizer, Iterable<Token> {
15
15
  private _tok;
16
16
  [Symbol.iterator](): Iterator<Token>;
17
17
  }
18
+ //# sourceMappingURL=tokenizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../src/tokenizer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,EAAa,MAAM,SAAS,CAAC;AAS1E,qBAAa,cAAe,YAAW,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC/D,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,CAAC,CAAK;IACd,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,MAAM,CAAc;IAG5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAGf;IAET,KAAK,CAAC,GAAG,EAAE,aAAa;IAiCxB,IAAI,IAAI,KAAK,GAAG,IAAI;IAkFpB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,IAAI;IAUZ,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC;CAWrC"}
package/dist/types.d.ts CHANGED
@@ -1,25 +1,26 @@
1
1
  import type { Delimiters } from "@rethinkhealth/hl7v2-ast";
2
2
  import type { Position } from "unist";
3
3
  export type PreprocessorStep = (ctx: ParserContext) => ParserContext;
4
- export type ParseOptions = {
4
+ export interface ParseOptions {
5
5
  /**
6
6
  * Optional preprocessing steps to apply to the input before parsing.
7
7
  */
8
8
  preprocess?: PreprocessorStep[];
9
- };
10
- export type ParserContext = {
9
+ }
10
+ export interface ParserContext {
11
11
  input: string;
12
12
  delimiters: Delimiters;
13
13
  metadata?: Record<string, unknown>;
14
14
  emptyMode?: "legacy" | "empty";
15
- };
16
- export type Token = {
15
+ }
16
+ export interface Token {
17
17
  type: TokenType;
18
18
  value?: string;
19
19
  position: Position;
20
- };
20
+ }
21
21
  export type TokenType = "SEGMENT_END" | "FIELD_DELIM" | "REPETITION_DELIM" | "COMPONENT_DELIM" | "SUBCOMP_DELIM" | "TEXT";
22
- export type Tokenizer = {
22
+ export interface Tokenizer {
23
23
  reset(ctx: ParserContext): void;
24
24
  next(): Token | null;
25
- };
25
+ }
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAItC,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,aAAa,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAChC;AAGD,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAGD,MAAM,MAAM,SAAS,GACjB,aAAa,GACb,aAAa,GACb,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,GACf,MAAM,CAAC;AAEX,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC;CACtB"}
package/package.json CHANGED
@@ -1,54 +1,54 @@
1
1
  {
2
2
  "name": "@rethinkhealth/hl7v2-parser",
3
+ "version": "0.5.0",
3
4
  "description": "hl7v2 plugin to parse hl7v2 messages",
4
- "version": "0.4.1",
5
+ "keywords": [
6
+ "health",
7
+ "healthcare",
8
+ "hl7",
9
+ "hl7v2",
10
+ "nodejs",
11
+ "typescript"
12
+ ],
13
+ "homepage": "https://www.rethinkhealth.io/hl7v2/docs",
5
14
  "license": "MIT",
6
15
  "author": {
7
16
  "name": "Melek Somai",
8
17
  "email": "melek@rethinkhealth.io"
9
18
  },
10
- "type": "module",
11
- "types": "./dist/index.d.ts",
19
+ "repository": "rethinkhealth/hl7v2.git",
12
20
  "files": [
13
21
  "dist"
14
22
  ],
23
+ "type": "module",
24
+ "types": "./dist/index.d.ts",
15
25
  "exports": {
16
26
  ".": "./dist/index.js"
17
27
  },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
18
31
  "dependencies": {
19
32
  "unified": "11.0.5",
20
- "@rethinkhealth/hl7v2-utils": "0.4.1"
33
+ "@rethinkhealth/hl7v2-utils": "0.5.0"
21
34
  },
22
35
  "devDependencies": {
23
36
  "@types/node": "24.10.1",
24
37
  "@types/unist": "^3.0.3",
25
- "@vitest/coverage-v8": "4.0.14",
38
+ "@vitest/coverage-v8": "4.0.18",
26
39
  "tsup": "8.5.1",
27
40
  "typescript": "^5.9.3",
28
41
  "unist": "^0.0.1",
29
42
  "vitest": "4.0.14",
30
- "@rethinkhealth/hl7v2-config": "0.4.1",
43
+ "@rethinkhealth/hl7v2-ast": "0.5.0",
31
44
  "@rethinkhealth/testing": "0.0.2",
32
- "@rethinkhealth/hl7v2-ast": "0.4.1",
33
- "@rethinkhealth/tsconfig": "0.0.1"
45
+ "@rethinkhealth/tsconfig": "0.0.1",
46
+ "@rethinkhealth/hl7v2-config": "0.5.0"
34
47
  },
35
48
  "engines": {
36
49
  "node": ">=18"
37
50
  },
38
- "repository": "rethinkhealth/hl7v2.git",
39
- "homepage": "https://www.rethinkhealth.io/hl7v2/docs",
40
- "keywords": [
41
- "health",
42
- "healthcare",
43
- "hl7",
44
- "hl7v2",
45
- "nodejs",
46
- "typescript"
47
- ],
48
51
  "packageManager": "pnpm@10.14.0",
49
- "publishConfig": {
50
- "access": "public"
51
- },
52
52
  "scripts": {
53
53
  "bench": "vitest bench --run",
54
54
  "build": "tsup && tsc --emitDeclarationOnly",