@rethinkhealth/hl7v2-parser 0.2.0 → 0.2.1

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 ADDED
@@ -0,0 +1,66 @@
1
+ # HL7v2 Parser
2
+
3
+ This package is a utility that takes a raw HL7v2 message as input and turns it into an HL7v2 syntax tree following the [@rethinkhealth/hl7v2-ast](../hl7v2-ast/README.md) definition.
4
+
5
+ This utility is a low level project. It’s used in [@rethinkhealth/hl7v2](../hl7v2/), which focusses on making it easier to transform content by abstracting these internals away.
6
+
7
+ ---
8
+
9
+ ## When should I use this?
10
+
11
+ If you want to handle syntax trees manually, use this. For an easier time processing content, use the [@rethinkhealth/hl7v2](../hl7v2/) ecosystem instead.
12
+
13
+ ## Install
14
+
15
+ This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). In Node.js (version 16+), install with npm:
16
+
17
+ ```bash
18
+ npm install @rethinkhealth/hl7v2-parser
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Use
24
+
25
+ ### Basic Usage
26
+
27
+ ```typescript
28
+ import { hl7v2Parser } from '@rethinkhealth/hl7v2-parser';
29
+
30
+ // Sample HL7v2 message
31
+ const message = `MSH|^~\\&|SENDING_APP|SENDING_FAC|RECEIVING_APP|RECEIVING_FAC|20110613061611||ADT^A04|12345|P|2.3
32
+ PID|1||123456||SMITH^JOHN^J||19800101|M|||123 MAIN ST^^ANYTOWN^ST^12345
33
+ PV1|1|I|ICU^101^1|||DOCTOR123^SMITH^JOHN^MD`;
34
+
35
+ // Parse using the unified processor
36
+ const processor = hl7v2Parser();
37
+ const result = processor.parse(message);
38
+
39
+ console.log(`Parsed ${result.children?.length} segments`);
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Contributing
45
+
46
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for more details.
47
+
48
+ 1. Fork the repository
49
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
50
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
51
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
52
+ 5. Open a Pull Request
53
+
54
+ ---
55
+
56
+ ## Code of Conduct
57
+
58
+ To ensure a welcoming and positive environment, we have a [Code of Conduct](CODE_OF_CONDUCT.md) that all contributors and participants are expected to adhere to.
59
+
60
+ ---
61
+
62
+ ## License
63
+
64
+ Copyright 2025 Rethink Health, SUARL. All rights reserved.
65
+
66
+ This program is licensed to you under the terms of the [MIT License](https://opensource.org/licenses/MIT). This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the [LICENSE](LICENSE) file for details.
package/dist/index.js CHANGED
@@ -5,11 +5,11 @@ var DEFAULT_DELIMITERS = {
5
5
  subcomponent: "&",
6
6
  repetition: "~",
7
7
  escape: "\\",
8
- segment: "\r"
9
- // default to \r
8
+ segment: "\n"
9
+ // default to \n (more common in modern systems)
10
10
  };
11
11
  var EMPTY_MESSAGE = {
12
- type: "message",
12
+ type: "root",
13
13
  delimiter: DEFAULT_DELIMITERS.segment,
14
14
  children: [],
15
15
  position: {
@@ -18,9 +18,13 @@ var EMPTY_MESSAGE = {
18
18
  }
19
19
  };
20
20
 
21
- // src/utils.ts
21
+ // src/pipeline/utils/index.ts
22
22
  function detectDelimitersFromMSH(raw, segmentDelimiter) {
23
- const firstLineEnd = raw.indexOf(segmentDelimiter);
23
+ const detectedSegmentDelimiter = detectSegmentDelimiter(
24
+ raw,
25
+ segmentDelimiter
26
+ );
27
+ const firstLineEnd = raw.indexOf(detectedSegmentDelimiter);
24
28
  const mshSegment = firstLineEnd >= 0 ? raw.slice(0, firstLineEnd) : raw;
25
29
  if (!mshSegment.startsWith("MSH")) {
26
30
  return {};
@@ -39,7 +43,7 @@ function detectDelimitersFromMSH(raw, segmentDelimiter) {
39
43
  repetition: encodingChars[1],
40
44
  escape: encodingChars[2],
41
45
  subcomponent: encodingChars[3],
42
- segment: segmentDelimiter
46
+ segment: detectedSegmentDelimiter
43
47
  };
44
48
  }
45
49
  function splitByString(text, delimiter) {
@@ -62,210 +66,512 @@ function splitByString(text, delimiter) {
62
66
  });
63
67
  return result;
64
68
  }
69
+ function detectSegmentDelimiter(message, fallback = "\n") {
70
+ const possibleDelimiters = ["\r\n", "\n", "\r"];
71
+ for (const delimiter of possibleDelimiters) {
72
+ if (message.includes(delimiter)) {
73
+ return delimiter;
74
+ }
75
+ }
76
+ return fallback;
77
+ }
65
78
 
66
- // src/parser.ts
67
- function fromHL7v2(rawMessage, options = {}) {
68
- if (!rawMessage.trim()) {
69
- return EMPTY_MESSAGE;
79
+ // src/pipeline/core/parsers/subcomponent.ts
80
+ var SubcomponentParser = class {
81
+ canParse(input) {
82
+ return input.type === "subcomponent";
70
83
  }
71
- const baseDelimiters = {
72
- ...DEFAULT_DELIMITERS,
73
- ...options.delimiters
74
- };
75
- let activeDelimiters = baseDelimiters;
76
- if (options.autoDetectDelimiters !== false) {
77
- const detected = detectDelimitersFromMSH(
78
- rawMessage,
79
- baseDelimiters.segment
84
+ parse(input) {
85
+ if (!this.canParse(input)) {
86
+ return null;
87
+ }
88
+ return {
89
+ type: "subcomponent",
90
+ index: input.subcomponentIndex,
91
+ value: input.text,
92
+ position: {
93
+ start: { line: input.line, column: input.column, offset: input.start },
94
+ end: {
95
+ line: input.line,
96
+ column: input.column + input.text.length,
97
+ offset: input.end
98
+ }
99
+ }
100
+ };
101
+ }
102
+ };
103
+
104
+ // src/pipeline/core/parsers/component.ts
105
+ var ComponentParser = class {
106
+ subcomponentParser = new SubcomponentParser();
107
+ canParse(input) {
108
+ return input.type === "component";
109
+ }
110
+ parse(input) {
111
+ if (!this.canParse(input)) {
112
+ return null;
113
+ }
114
+ const baseNode = {
115
+ type: "component",
116
+ index: input.componentIndex,
117
+ position: {
118
+ start: { line: input.line, column: input.column, offset: input.start },
119
+ end: {
120
+ line: input.line,
121
+ column: input.column + input.text.length,
122
+ offset: input.end
123
+ }
124
+ }
125
+ };
126
+ if (input.text.includes(input.context.delimiters.subcomponent)) {
127
+ return {
128
+ ...baseNode,
129
+ delimiter: input.context.delimiters.subcomponent,
130
+ children: this.parseSubcomponents(input)
131
+ };
132
+ }
133
+ return { ...baseNode, value: input.text };
134
+ }
135
+ parseSubcomponents(input) {
136
+ const subcomponents = this.splitByDelimiter(
137
+ input.text,
138
+ input.context.delimiters.subcomponent
80
139
  );
81
- activeDelimiters = { ...baseDelimiters, ...detected };
140
+ const nodes = [];
141
+ for (let i = 0; i < subcomponents.length; i++) {
142
+ const sub = subcomponents[i];
143
+ if (!sub) {
144
+ continue;
145
+ }
146
+ const subNode = this.subcomponentParser.parse({
147
+ type: "subcomponent",
148
+ text: sub.value,
149
+ start: input.start + sub.start,
150
+ end: input.start + sub.end,
151
+ index: i,
152
+ subcomponentIndex: i,
153
+ line: input.line,
154
+ column: input.column + sub.start,
155
+ context: input.context
156
+ });
157
+ if (subNode) {
158
+ nodes.push(subNode);
159
+ }
160
+ }
161
+ return nodes;
82
162
  }
83
- const segments = splitByString(rawMessage, activeDelimiters.segment);
84
- const messageNode = {
85
- type: "message",
86
- delimiter: activeDelimiters.segment,
87
- children: [],
88
- position: {
89
- start: { line: 1, column: 1, offset: 0 },
90
- end: {
91
- line: segments.length,
92
- column: (segments.at(-1)?.value.length ?? 0) + 1,
93
- offset: rawMessage.length
163
+ splitByDelimiter(text, delimiter) {
164
+ const result = [];
165
+ let lastIndex = 0;
166
+ let index = text.indexOf(delimiter);
167
+ while (index !== -1) {
168
+ result.push({
169
+ value: text.slice(lastIndex, index),
170
+ start: lastIndex,
171
+ end: index
172
+ });
173
+ lastIndex = index + delimiter.length;
174
+ index = text.indexOf(delimiter, lastIndex);
175
+ }
176
+ result.push({
177
+ value: text.slice(lastIndex),
178
+ start: lastIndex,
179
+ end: text.length
180
+ });
181
+ return result;
182
+ }
183
+ };
184
+
185
+ // src/pipeline/core/parsers/field.ts
186
+ var FieldParser = class {
187
+ componentParser = new ComponentParser();
188
+ canParse(input) {
189
+ return input.type === "field";
190
+ }
191
+ parse(input) {
192
+ if (!this.canParse(input)) {
193
+ return null;
194
+ }
195
+ const baseNode = {
196
+ type: input.fieldIndex === 0 ? "header" : "field",
197
+ index: input.fieldIndex,
198
+ position: {
199
+ start: { line: input.line, column: input.column, offset: input.start },
200
+ end: {
201
+ line: input.line,
202
+ column: input.column + input.text.length,
203
+ offset: input.end
204
+ }
94
205
  }
206
+ };
207
+ if (input.isEncodingField) {
208
+ return { ...baseNode, value: input.text };
95
209
  }
96
- };
97
- let currentLine = 1;
98
- for (let i = 0; i < segments.length; i++) {
99
- const seg = segments[i];
100
- if (!seg) {
101
- throw new Error("Invalid message");
210
+ if (input.fieldIndex === 0) {
211
+ return { ...baseNode, value: input.text };
102
212
  }
103
- if (!seg.value.trim()) {
104
- currentLine++;
105
- continue;
213
+ if (input.text.includes(input.context.delimiters.component)) {
214
+ return {
215
+ ...baseNode,
216
+ delimiter: input.context.delimiters.component,
217
+ children: this.parseComponents(input)
218
+ };
106
219
  }
107
- const segmentNode = parseSegment(
108
- seg.value,
109
- seg.start,
110
- seg.end,
111
- currentLine,
112
- i,
113
- activeDelimiters
220
+ return { ...baseNode, value: input.text };
221
+ }
222
+ parseComponents(input) {
223
+ const components = this.splitByDelimiter(
224
+ input.text,
225
+ input.context.delimiters.component
114
226
  );
115
- if (segmentNode) {
116
- if (!messageNode.children) {
117
- messageNode.children = [];
227
+ const nodes = [];
228
+ for (let i = 0; i < components.length; i++) {
229
+ const comp = components[i];
230
+ if (!comp) {
231
+ continue;
232
+ }
233
+ const componentNode = this.componentParser.parse({
234
+ type: "component",
235
+ text: comp.value,
236
+ start: input.start + comp.start,
237
+ end: input.start + comp.end,
238
+ index: i,
239
+ componentIndex: i,
240
+ line: input.line,
241
+ column: input.column + comp.start,
242
+ context: input.context
243
+ });
244
+ if (componentNode) {
245
+ nodes.push(componentNode);
118
246
  }
119
- messageNode.children.push(segmentNode);
120
247
  }
121
- currentLine++;
248
+ return nodes;
122
249
  }
123
- return messageNode;
124
- }
125
- function parseSegment(segmentText, segmentStart, segmentEnd, line, segmentIndex, delimiters) {
126
- const fields = splitByString(segmentText, delimiters.field);
127
- if (!fields[0] || fields.length === 0) {
128
- return null;
129
- }
130
- const segmentNode = {
131
- type: "segment",
132
- name: fields[0].value,
133
- index: segmentIndex,
134
- delimiter: delimiters.field,
135
- children: [],
136
- position: {
137
- start: { line, column: 1, offset: segmentStart },
138
- end: { line, column: segmentText.length + 1, offset: segmentEnd }
139
- }
140
- };
141
- for (let i = 0; i < fields.length; i++) {
142
- const f = fields[i];
143
- if (!f) {
144
- throw new Error("Invalid message");
250
+ splitByDelimiter(text, delimiter) {
251
+ const result = [];
252
+ let lastIndex = 0;
253
+ let index = text.indexOf(delimiter);
254
+ while (index !== -1) {
255
+ result.push({
256
+ value: text.slice(lastIndex, index),
257
+ start: lastIndex,
258
+ end: index
259
+ });
260
+ lastIndex = index + delimiter.length;
261
+ index = text.indexOf(delimiter, lastIndex);
145
262
  }
146
- const node = i === 0 ? createHeaderNode(
147
- f.value,
148
- i,
149
- segmentStart + f.start,
150
- segmentStart + f.end,
151
- line,
152
- f.start + 1
153
- ) : createFieldNode(
154
- f.value,
155
- i,
156
- segmentStart + f.start,
157
- segmentStart + f.end,
158
- line,
159
- f.start + 1,
160
- delimiters
161
- );
162
- segmentNode.children.push(node);
263
+ result.push({
264
+ value: text.slice(lastIndex),
265
+ start: lastIndex,
266
+ end: text.length
267
+ });
268
+ return result;
163
269
  }
164
- return segmentNode;
165
- }
166
- function createHeaderNode(headerText, headerIndex, headerStart, headerEnd, line, column) {
167
- return {
168
- type: "header",
169
- index: headerIndex,
170
- position: {
171
- start: { line, column, offset: headerStart },
172
- end: { line, column: column + headerText.length, offset: headerEnd }
173
- },
174
- value: headerText
175
- };
176
- }
177
- function createFieldNode(fieldText, fieldIndex, fieldStart, fieldEnd, line, column, delimiters) {
178
- const node = {
179
- type: "field",
180
- index: fieldIndex,
181
- position: {
182
- start: { line, column, offset: fieldStart },
183
- end: { line, column: column + fieldText.length, offset: fieldEnd }
270
+ };
271
+
272
+ // src/pipeline/core/parsers/segment.ts
273
+ var SegmentParser = class {
274
+ segmentType = "DEFAULT";
275
+ fieldParser = new FieldParser();
276
+ canParse(input) {
277
+ return input.type === "segment" && input.text.trim().length > 0;
278
+ }
279
+ parse(input) {
280
+ if (!this.canParse(input)) {
281
+ return null;
184
282
  }
185
- };
186
- if (fieldText.includes(delimiters.component)) {
187
- return {
188
- ...node,
189
- delimiter: delimiters.component,
190
- children: parseComponents(
191
- fieldText,
192
- fieldStart,
193
- line,
194
- column,
195
- delimiters
196
- )
283
+ const fields = splitByString(input.text, input.context.delimiters.field);
284
+ if (!fields[0] || fields.length === 0) {
285
+ return null;
286
+ }
287
+ const segmentNode = {
288
+ type: "segment",
289
+ name: fields[0].value,
290
+ index: input.index,
291
+ delimiter: input.context.delimiters.field,
292
+ children: [],
293
+ position: {
294
+ start: { line: input.line, column: 1, offset: input.start },
295
+ end: {
296
+ line: input.line,
297
+ column: input.text.length + 1,
298
+ offset: input.end
299
+ }
300
+ }
197
301
  };
302
+ segmentNode.children = this.parseFields(fields, input);
303
+ return segmentNode;
198
304
  }
199
- return { ...node, value: fieldText };
200
- }
201
- function parseComponents(fieldText, fieldStart, line, column, delimiters) {
202
- const comps = splitByString(fieldText, delimiters.component);
203
- const nodes = [];
204
- for (let i = 0; i < comps.length; i++) {
205
- const c = comps[i];
206
- if (!c) {
207
- throw new Error("Invalid message");
305
+ parseFields(fields, input) {
306
+ const children = [];
307
+ for (let i = 0; i < fields.length; i++) {
308
+ const field = fields[i];
309
+ if (!field) {
310
+ continue;
311
+ }
312
+ const fieldNode = this.fieldParser.parse({
313
+ type: "field",
314
+ text: field.value,
315
+ start: input.start + field.start,
316
+ end: input.start + field.end,
317
+ index: i,
318
+ fieldIndex: i,
319
+ line: input.line,
320
+ column: field.start + 1,
321
+ context: input.context
322
+ });
323
+ if (fieldNode) {
324
+ children.push(fieldNode);
325
+ }
208
326
  }
209
- const startColumn = column + c.start;
210
- const base = {
211
- type: "component",
212
- index: i,
327
+ return children;
328
+ }
329
+ };
330
+
331
+ // src/pipeline/core/parsers/segment-msh.ts
332
+ var MSHSegmentParser = class {
333
+ segmentType = "MSH";
334
+ fieldParser = new FieldParser();
335
+ canParse(input) {
336
+ return input.type === "segment" && input.segmentType === "MSH";
337
+ }
338
+ parse(input) {
339
+ if (!this.canParse(input)) {
340
+ return null;
341
+ }
342
+ const fields = this.extractMSHFields(
343
+ input.text,
344
+ input.context.delimiters.field
345
+ );
346
+ const segmentNode = {
347
+ type: "segment",
348
+ name: "MSH",
349
+ index: input.index,
350
+ delimiter: input.context.delimiters.field,
351
+ children: [],
213
352
  position: {
214
- start: { line, column: startColumn, offset: fieldStart + c.start },
353
+ start: { line: input.line, column: 1, offset: input.start },
215
354
  end: {
216
- line,
217
- column: startColumn + c.value.length,
218
- offset: fieldStart + c.end
355
+ line: input.line,
356
+ column: input.text.length + 1,
357
+ offset: input.end
219
358
  }
220
359
  }
221
360
  };
222
- if (c.value.includes(delimiters.subcomponent)) {
223
- nodes.push({
224
- ...base,
225
- delimiter: delimiters.subcomponent,
226
- children: parseSubcomponents(
227
- c.value,
228
- fieldStart + c.start,
229
- line,
230
- startColumn,
231
- delimiters
232
- )
361
+ segmentNode.children = this.parseFields(fields, input);
362
+ return segmentNode;
363
+ }
364
+ extractMSHFields(segmentText, fieldDelimiter) {
365
+ const msh1 = segmentText[3] ?? "";
366
+ const msh2 = segmentText.slice(4, 8) ?? "";
367
+ const rest = segmentText.slice(9);
368
+ const restFields = splitByString(rest, fieldDelimiter);
369
+ return [
370
+ { value: "MSH", start: 0, end: 3 },
371
+ { value: msh1, start: 3, end: 4 },
372
+ { value: msh2, start: 4, end: 8, isEncodingField: true },
373
+ ...restFields.map((f) => ({
374
+ value: f.value ?? "",
375
+ start: 9 + (f.start ?? 0),
376
+ end: 9 + (f.end ?? 0)
377
+ }))
378
+ ];
379
+ }
380
+ parseFields(fields, input) {
381
+ const children = [];
382
+ for (let i = 0; i < fields.length; i++) {
383
+ const field = fields[i];
384
+ if (!field) {
385
+ continue;
386
+ }
387
+ const fieldNode = this.fieldParser.parse({
388
+ type: "field",
389
+ text: field.value,
390
+ start: input.start + field.start,
391
+ end: input.start + field.end,
392
+ index: i,
393
+ fieldIndex: i,
394
+ line: input.line,
395
+ column: field.start + 1,
396
+ isEncodingField: field.isEncodingField,
397
+ context: input.context
233
398
  });
234
- } else {
235
- nodes.push({ ...base, value: c.value });
399
+ if (fieldNode) {
400
+ children.push(fieldNode);
401
+ }
236
402
  }
403
+ return children;
237
404
  }
238
- return nodes;
239
- }
240
- function parseSubcomponents(componentText, componentStart, line, column, delimiters) {
241
- const subs = splitByString(componentText, delimiters.subcomponent);
242
- if (!subs[0]) {
243
- throw new Error("Invalid message");
244
- }
245
- return subs.map((s, i) => ({
246
- type: "subcomponent",
247
- index: i,
248
- value: s.value,
249
- position: {
250
- start: {
251
- line,
252
- column: column + s.start,
253
- offset: componentStart + s.start
254
- },
255
- end: {
256
- line,
257
- column: column + s.start + s.value.length,
258
- offset: componentStart + s.end
405
+ };
406
+
407
+ // src/pipeline/core/registry.ts
408
+ var SegmentParserRegistry = class {
409
+ parsers = /* @__PURE__ */ new Map();
410
+ defaultParser;
411
+ constructor(customParsers) {
412
+ this.defaultParser = new SegmentParser();
413
+ this.register(new MSHSegmentParser());
414
+ if (customParsers) {
415
+ for (const [, parser] of customParsers) {
416
+ this.register(parser);
259
417
  }
260
418
  }
261
- }));
419
+ }
420
+ /**
421
+ * Register a segment parser for a specific segment type
422
+ */
423
+ register(parser) {
424
+ this.parsers.set(parser.segmentType, parser);
425
+ }
426
+ /**
427
+ * Get the appropriate parser for a segment type
428
+ */
429
+ getParser(segmentType) {
430
+ return this.parsers.get(segmentType) || this.defaultParser;
431
+ }
432
+ /**
433
+ * Check if a parser is registered for a segment type
434
+ */
435
+ hasParser(segmentType) {
436
+ return this.parsers.has(segmentType);
437
+ }
438
+ /**
439
+ * Unregister a parser for a segment type
440
+ */
441
+ unregister(segmentType) {
442
+ return this.parsers.delete(segmentType);
443
+ }
444
+ /**
445
+ * Get all registered segment types
446
+ */
447
+ getRegisteredTypes() {
448
+ return Array.from(this.parsers.keys());
449
+ }
450
+ };
451
+
452
+ // src/pipeline/core/message.ts
453
+ var HL7MessageParser = class {
454
+ segmentRegistry;
455
+ options;
456
+ constructor(options = {}) {
457
+ this.options = options;
458
+ this.segmentRegistry = new SegmentParserRegistry(options.customParsers);
459
+ }
460
+ canParse(input) {
461
+ return input.type === "message" && input.text.trim().length > 0;
462
+ }
463
+ parse(input) {
464
+ if (!this.canParse(input)) {
465
+ return EMPTY_MESSAGE;
466
+ }
467
+ const context = this.createParseContext(input.text);
468
+ const segments = splitByString(input.text, context.delimiters.segment);
469
+ const messageNode = {
470
+ type: "root",
471
+ delimiter: context.delimiters.segment,
472
+ children: [],
473
+ position: {
474
+ start: { line: 1, column: 1, offset: 0 },
475
+ end: {
476
+ line: segments.length,
477
+ column: (segments.at(-1)?.value.length ?? 0) + 1,
478
+ offset: input.text.length
479
+ }
480
+ }
481
+ };
482
+ let currentLine = 1;
483
+ for (let i = 0; i < segments.length; i++) {
484
+ const seg = segments[i];
485
+ const hasContent = seg?.value.trim();
486
+ if (!seg) {
487
+ currentLine++;
488
+ continue;
489
+ }
490
+ if (!hasContent) {
491
+ currentLine++;
492
+ continue;
493
+ }
494
+ const segmentNode = this.parseSegment(seg, currentLine, i, context);
495
+ if (segmentNode) {
496
+ messageNode.children = messageNode.children || [];
497
+ messageNode.children.push(segmentNode);
498
+ }
499
+ currentLine++;
500
+ }
501
+ return this.applyValidationHooks(messageNode, context);
502
+ }
503
+ createParseContext(rawMessage) {
504
+ const baseDelimiters = {
505
+ ...DEFAULT_DELIMITERS,
506
+ ...this.options.delimiters
507
+ };
508
+ let activeDelimiters = baseDelimiters;
509
+ if (this.options.autoDetectDelimiters !== false) {
510
+ const detected = detectDelimitersFromMSH(
511
+ rawMessage,
512
+ baseDelimiters.segment
513
+ );
514
+ activeDelimiters = { ...baseDelimiters, ...detected };
515
+ }
516
+ return {
517
+ delimiters: activeDelimiters,
518
+ options: this.options,
519
+ currentLine: 1,
520
+ totalOffset: 0
521
+ };
522
+ }
523
+ parseSegment(segment, line, index, context) {
524
+ const segmentType = segment.value.slice(0, 3);
525
+ const parser = this.segmentRegistry.getParser(segmentType);
526
+ return parser.parse({
527
+ type: "segment",
528
+ text: segment.value,
529
+ start: segment.start,
530
+ end: segment.end,
531
+ index,
532
+ segmentType,
533
+ line,
534
+ context
535
+ });
536
+ }
537
+ applyValidationHooks(node, context) {
538
+ if (!this.options.validationHooks) {
539
+ return node;
540
+ }
541
+ for (const hook of this.options.validationHooks) {
542
+ const result = hook.validate(node, context);
543
+ if (!result.isValid) {
544
+ throw new Error(result.errors?.[0] ?? "Validation error");
545
+ }
546
+ }
547
+ return node;
548
+ }
549
+ };
550
+
551
+ // src/parser.ts
552
+ function fromHL7v2Pipeline(rawMessage, options = {}) {
553
+ const parser = new HL7MessageParser(options);
554
+ const result = parser.parse({
555
+ type: "message",
556
+ text: rawMessage,
557
+ start: 0,
558
+ end: rawMessage.length,
559
+ index: 0,
560
+ context: {
561
+ delimiters: options.delimiters || {},
562
+ options,
563
+ currentLine: 1,
564
+ totalOffset: 0
565
+ }
566
+ });
567
+ return result || EMPTY_MESSAGE;
262
568
  }
263
569
 
264
570
  // src/processor.ts
265
571
  var hl7v2Parser = function(options = {}) {
266
572
  const self = this;
267
573
  function parser(value) {
268
- return fromHL7v2(value, options);
574
+ return fromHL7v2Pipeline(value, options);
269
575
  }
270
576
  self.parser = parser;
271
577
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/utils.ts","../src/parser.ts","../src/processor.ts"],"sourcesContent":["import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport type { HL7v2Delimiters } from './types';\n\n/**\n * Default HL7v2 delimiters\n */\nexport const DEFAULT_DELIMITERS: HL7v2Delimiters = {\n field: '|',\n component: '^',\n subcomponent: '&',\n repetition: '~',\n escape: '\\\\',\n segment: '\\r', // default to \\r\n};\n\n/**\n * Empty message node\n */\nexport const EMPTY_MESSAGE: HL7v2Node = {\n type: 'message',\n delimiter: DEFAULT_DELIMITERS.segment,\n children: [],\n position: {\n start: { line: 1, column: 1, offset: 0 },\n end: { line: 1, column: 1, offset: 0 },\n },\n};\n","import type { HL7v2Delimiters } from './types';\n\n/**\n * Auto-detect custom delimiters from MSH-1 and MSH-2\n */\nexport function detectDelimitersFromMSH(\n raw: string,\n segmentDelimiter: string\n): Partial<HL7v2Delimiters> {\n const firstLineEnd = raw.indexOf(segmentDelimiter);\n const mshSegment = firstLineEnd >= 0 ? raw.slice(0, firstLineEnd) : raw;\n\n if (!mshSegment.startsWith('MSH')) {\n return {};\n }\n\n const fieldDelimiter = mshSegment[3];\n\n if (!fieldDelimiter) {\n return {};\n }\n\n const encodingChars = mshSegment.slice(4, 8);\n\n if (encodingChars.length !== 4) {\n return {};\n }\n\n return {\n field: fieldDelimiter,\n component: encodingChars[0],\n repetition: encodingChars[1],\n escape: encodingChars[2],\n subcomponent: encodingChars[3],\n segment: segmentDelimiter,\n };\n}\n\n/**\n * Split text by string delimiter, preserving positions\n */\nexport function splitByString(\n text: string,\n delimiter: string\n): Array<{ value: string; start: number; end: number }> {\n const result: { value: string; start: number; end: number }[] = [];\n let lastIndex = 0;\n let index = text.indexOf(delimiter);\n\n while (index !== -1) {\n result.push({\n value: text.slice(lastIndex, index),\n start: lastIndex,\n end: index,\n });\n lastIndex = index + delimiter.length;\n index = text.indexOf(delimiter, lastIndex);\n }\n\n result.push({\n value: text.slice(lastIndex),\n start: lastIndex,\n end: text.length,\n });\n return result;\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport { DEFAULT_DELIMITERS, EMPTY_MESSAGE } from './constants';\nimport type { HL7v2Delimiters, ParseOptions } from './types';\nimport { detectDelimitersFromMSH, splitByString } from './utils';\n\n/**\n * Parse an HL7v2 message into a Unist-compatible DOM tree.\n * Tracks lines/columns and preserves delimiters for round-tripping.\n */\nexport function fromHL7v2(\n rawMessage: string,\n options: ParseOptions = {}\n): HL7v2Node {\n if (!rawMessage.trim()) {\n return EMPTY_MESSAGE;\n }\n\n // Merge user-defined delimiters with defaults\n const baseDelimiters: HL7v2Delimiters = {\n ...DEFAULT_DELIMITERS,\n ...options.delimiters,\n };\n\n // Auto-detect from MSH-2 if enabled\n let activeDelimiters = baseDelimiters;\n if (options.autoDetectDelimiters !== false) {\n const detected = detectDelimitersFromMSH(\n rawMessage,\n baseDelimiters.segment\n );\n activeDelimiters = { ...baseDelimiters, ...detected };\n }\n\n // Split into segments\n const segments = splitByString(rawMessage, activeDelimiters.segment);\n\n const messageNode: HL7v2Node = {\n type: 'message',\n delimiter: activeDelimiters.segment,\n children: [],\n position: {\n start: { line: 1, column: 1, offset: 0 },\n end: {\n line: segments.length,\n column: (segments.at(-1)?.value.length ?? 0) + 1,\n offset: rawMessage.length,\n },\n },\n };\n\n let currentLine = 1;\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n\n if (!seg) {\n // TODO: Handle this case with a better error message\n throw new Error('Invalid message');\n }\n\n if (!seg.value.trim()) {\n currentLine++;\n continue;\n }\n\n const segmentNode = parseSegment(\n seg.value,\n seg.start,\n seg.end,\n currentLine,\n i,\n activeDelimiters\n );\n if (segmentNode) {\n if (!messageNode.children) {\n messageNode.children = [];\n }\n\n messageNode.children.push(segmentNode);\n }\n currentLine++;\n }\n\n return messageNode;\n}\n\n/**\n * Parse a single segment into fields and components\n */\nfunction parseSegment(\n segmentText: string,\n segmentStart: number,\n segmentEnd: number,\n line: number,\n segmentIndex: number,\n delimiters: HL7v2Delimiters\n): HL7v2Node | null {\n // 1. Split into fields\n const fields = splitByString(segmentText, delimiters.field);\n\n // 2. If no fields, return null\n if (!fields[0] || fields.length === 0) {\n return null;\n }\n\n const segmentNode: HL7v2Node = {\n type: 'segment',\n name: fields[0].value,\n index: segmentIndex,\n delimiter: delimiters.field,\n children: [],\n position: {\n start: { line, column: 1, offset: segmentStart },\n end: { line, column: segmentText.length + 1, offset: segmentEnd },\n },\n };\n\n for (let i = 0; i < fields.length; i++) {\n const f = fields[i];\n\n if (!f) {\n // TODO: Handle this case with a better error message\n throw new Error('Invalid message');\n }\n\n // Create header node for first field (segment identifier), field node for others\n const node =\n i === 0\n ? createHeaderNode(\n f.value,\n i,\n segmentStart + f.start,\n segmentStart + f.end,\n line,\n f.start + 1\n )\n : createFieldNode(\n f.value,\n i,\n segmentStart + f.start,\n segmentStart + f.end,\n line,\n f.start + 1,\n delimiters\n );\n\n // biome-ignore lint/style/noNonNullAssertion: This is defined always\n segmentNode.children!.push(node);\n }\n\n return segmentNode;\n}\n\n/**\n * Create a header node for segment identifiers\n */\nfunction createHeaderNode(\n headerText: string,\n headerIndex: number,\n headerStart: number,\n headerEnd: number,\n line: number,\n column: number\n): HL7v2Node {\n return {\n type: 'header',\n index: headerIndex,\n position: {\n start: { line, column, offset: headerStart },\n end: { line, column: column + headerText.length, offset: headerEnd },\n },\n value: headerText,\n };\n}\n\n/**\n * Create a field node, parsing components if needed\n */\nfunction createFieldNode(\n fieldText: string,\n fieldIndex: number,\n fieldStart: number,\n fieldEnd: number,\n line: number,\n column: number,\n delimiters: HL7v2Delimiters\n): HL7v2Node {\n const node: HL7v2Node = {\n type: 'field',\n index: fieldIndex,\n position: {\n start: { line, column, offset: fieldStart },\n end: { line, column: column + fieldText.length, offset: fieldEnd },\n },\n };\n\n if (fieldText.includes(delimiters.component)) {\n return {\n ...node,\n delimiter: delimiters.component,\n children: parseComponents(\n fieldText,\n fieldStart,\n line,\n column,\n delimiters\n ),\n };\n }\n\n return { ...node, value: fieldText };\n}\n\n/**\n * Parse components within a field\n */\nfunction parseComponents(\n fieldText: string,\n fieldStart: number,\n line: number,\n column: number,\n delimiters: HL7v2Delimiters\n): HL7v2Node[] {\n const comps = splitByString(fieldText, delimiters.component);\n const nodes: HL7v2Node[] = [];\n\n for (let i = 0; i < comps.length; i++) {\n const c = comps[i];\n\n if (!c) {\n // TODO: Handle this case with a better error message\n throw new Error('Invalid message');\n }\n\n const startColumn = column + c.start;\n const base: HL7v2Node = {\n type: 'component',\n index: i,\n position: {\n start: { line, column: startColumn, offset: fieldStart + c.start },\n end: {\n line,\n column: startColumn + c.value.length,\n offset: fieldStart + c.end,\n },\n },\n };\n\n if (c.value.includes(delimiters.subcomponent)) {\n nodes.push({\n ...base,\n delimiter: delimiters.subcomponent,\n children: parseSubcomponents(\n c.value,\n fieldStart + c.start,\n line,\n startColumn,\n delimiters\n ),\n });\n } else {\n nodes.push({ ...base, value: c.value });\n }\n }\n\n return nodes;\n}\n\n/**\n * Parse subcomponents within a component\n */\nfunction parseSubcomponents(\n componentText: string,\n componentStart: number,\n line: number,\n column: number,\n delimiters: HL7v2Delimiters\n): HL7v2Node[] {\n const subs = splitByString(componentText, delimiters.subcomponent);\n\n if (!subs[0]) {\n // TODO: Handle this case with a better error message\n throw new Error('Invalid message');\n }\n\n return subs.map((s, i) => ({\n type: 'subcomponent',\n index: i,\n value: s.value,\n position: {\n start: {\n line,\n column: column + s.start,\n offset: componentStart + s.start,\n },\n end: {\n line,\n column: column + s.start + s.value.length,\n offset: componentStart + s.end,\n },\n },\n }));\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport type { Plugin } from 'unified';\nimport { fromHL7v2 } from './parser';\nimport type { ParseOptions } from './types';\n\nconst hl7v2Parser: Plugin<[ParseOptions?], undefined, HL7v2Node> = function (\n options: ParseOptions = {}\n): void {\n // biome-ignore lint/complexity/noUselessThisAlias: this is a plugin\n const self = this;\n\n function parser(this: unknown, value: string): HL7v2Node {\n return fromHL7v2(value, options);\n }\n\n self.parser = parser;\n};\n\nexport default hl7v2Parser;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/pipeline/utils/index.ts","../src/pipeline/core/parsers/subcomponent.ts","../src/pipeline/core/parsers/component.ts","../src/pipeline/core/parsers/field.ts","../src/pipeline/core/parsers/segment.ts","../src/pipeline/core/parsers/segment-msh.ts","../src/pipeline/core/registry.ts","../src/pipeline/core/message.ts","../src/parser.ts","../src/processor.ts"],"sourcesContent":["import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport type { HL7v2Delimiters } from './types';\n\n/**\n * Default HL7v2 delimiters\n */\nexport const DEFAULT_DELIMITERS: HL7v2Delimiters = {\n field: '|',\n component: '^',\n subcomponent: '&',\n repetition: '~',\n escape: '\\\\',\n segment: '\\n', // default to \\n (more common in modern systems)\n};\n\n/**\n * Empty message node\n */\nexport const EMPTY_MESSAGE: HL7v2Node = {\n type: 'root',\n delimiter: DEFAULT_DELIMITERS.segment,\n children: [],\n position: {\n start: { line: 1, column: 1, offset: 0 },\n end: { line: 1, column: 1, offset: 0 },\n },\n};\n","import type { HL7v2Delimiters } from '../../types';\n\n/**\n * Auto-detect custom delimiters from MSH-1 and MSH-2\n */\nexport function detectDelimitersFromMSH(\n raw: string,\n segmentDelimiter: string\n): Partial<HL7v2Delimiters> {\n const detectedSegmentDelimiter = detectSegmentDelimiter(\n raw,\n segmentDelimiter\n );\n\n const firstLineEnd = raw.indexOf(detectedSegmentDelimiter);\n\n // If there are multiple segments, use the first one. Otherwise, use the entire message.\n const mshSegment = firstLineEnd >= 0 ? raw.slice(0, firstLineEnd) : raw;\n\n if (!mshSegment.startsWith('MSH')) {\n return {};\n }\n\n const fieldDelimiter = mshSegment[3];\n\n if (!fieldDelimiter) {\n return {};\n }\n\n const encodingChars = mshSegment.slice(4, 8);\n\n if (encodingChars.length !== 4) {\n return {};\n }\n\n return {\n field: fieldDelimiter,\n component: encodingChars[0],\n repetition: encodingChars[1],\n escape: encodingChars[2],\n subcomponent: encodingChars[3],\n segment: detectedSegmentDelimiter,\n };\n}\n\n/**\n * Split text by string delimiter, preserving positions\n */\nexport function splitByString(\n text: string,\n delimiter: string\n): Array<{ value: string; start: number; end: number }> {\n const result: { value: string; start: number; end: number }[] = [];\n let lastIndex = 0;\n let index = text.indexOf(delimiter);\n\n while (index !== -1) {\n result.push({\n value: text.slice(lastIndex, index),\n start: lastIndex,\n end: index,\n });\n lastIndex = index + delimiter.length;\n index = text.indexOf(delimiter, lastIndex);\n }\n\n result.push({\n value: text.slice(lastIndex),\n start: lastIndex,\n end: text.length,\n });\n return result;\n}\n\n/**\n * Detect the segment delimiter used in the message\n */\nexport function detectSegmentDelimiter(\n message: string,\n fallback = '\\n'\n): string {\n // Look for common segment delimiters in order of preference\n const possibleDelimiters = ['\\r\\n', '\\n', '\\r'];\n\n for (const delimiter of possibleDelimiters) {\n if (message.includes(delimiter)) {\n return delimiter;\n }\n }\n\n // Use the provided fallback if no delimiter found\n return fallback;\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport type {\n ISubcomponentParser,\n SubcomponentParseInput,\n} from '../../interfaces';\n\n/**\n * Default subcomponent parser - leaf level parser\n */\nexport class SubcomponentParser implements ISubcomponentParser {\n canParse(input: SubcomponentParseInput): boolean {\n return input.type === 'subcomponent';\n }\n\n parse(input: SubcomponentParseInput): HL7v2Node | null {\n if (!this.canParse(input)) {\n return null;\n }\n\n return {\n type: 'subcomponent',\n index: input.subcomponentIndex,\n value: input.text,\n position: {\n start: { line: input.line, column: input.column, offset: input.start },\n end: {\n line: input.line,\n column: input.column + input.text.length,\n offset: input.end,\n },\n },\n };\n }\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport type { ComponentParseInput, IComponentParser } from '../../interfaces';\nimport { SubcomponentParser } from './subcomponent';\n\n/**\n * Default component parser that handles subcomponents\n */\nexport class ComponentParser implements IComponentParser {\n private subcomponentParser = new SubcomponentParser();\n\n canParse(input: ComponentParseInput): boolean {\n return input.type === 'component';\n }\n\n parse(input: ComponentParseInput): HL7v2Node | null {\n if (!this.canParse(input)) {\n return null;\n }\n\n const baseNode: HL7v2Node = {\n type: 'component',\n index: input.componentIndex,\n position: {\n start: { line: input.line, column: input.column, offset: input.start },\n end: {\n line: input.line,\n column: input.column + input.text.length,\n offset: input.end,\n },\n },\n };\n\n // Check if component contains subcomponents\n if (input.text.includes(input.context.delimiters.subcomponent)) {\n return {\n ...baseNode,\n delimiter: input.context.delimiters.subcomponent,\n children: this.parseSubcomponents(input),\n };\n }\n\n return { ...baseNode, value: input.text };\n }\n\n private parseSubcomponents(input: ComponentParseInput): HL7v2Node[] {\n const subcomponents = this.splitByDelimiter(\n input.text,\n input.context.delimiters.subcomponent\n );\n const nodes: HL7v2Node[] = [];\n\n for (let i = 0; i < subcomponents.length; i++) {\n const sub = subcomponents[i];\n if (!sub) {\n continue;\n }\n\n const subNode = this.subcomponentParser.parse({\n type: 'subcomponent',\n text: sub.value,\n start: input.start + sub.start,\n end: input.start + sub.end,\n index: i,\n subcomponentIndex: i,\n line: input.line,\n column: input.column + sub.start,\n context: input.context,\n });\n\n if (subNode) {\n nodes.push(subNode);\n }\n }\n\n return nodes;\n }\n\n private splitByDelimiter(\n text: string,\n delimiter: string\n ): Array<{ value: string; start: number; end: number }> {\n const result: { value: string; start: number; end: number }[] = [];\n let lastIndex = 0;\n let index = text.indexOf(delimiter);\n\n while (index !== -1) {\n result.push({\n value: text.slice(lastIndex, index),\n start: lastIndex,\n end: index,\n });\n lastIndex = index + delimiter.length;\n index = text.indexOf(delimiter, lastIndex);\n }\n\n result.push({\n value: text.slice(lastIndex),\n start: lastIndex,\n end: text.length,\n });\n\n return result;\n }\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport type { FieldParseInput, IFieldParser } from '../../interfaces';\nimport { ComponentParser } from './component';\n\n/**\n * Default field parser that handles components\n */\nexport class FieldParser implements IFieldParser {\n private componentParser = new ComponentParser();\n\n canParse(input: FieldParseInput): boolean {\n return input.type === 'field';\n }\n\n parse(input: FieldParseInput): HL7v2Node | null {\n if (!this.canParse(input)) {\n return null;\n }\n\n const baseNode: HL7v2Node = {\n type: input.fieldIndex === 0 ? 'header' : 'field',\n index: input.fieldIndex,\n position: {\n start: { line: input.line, column: input.column, offset: input.start },\n end: {\n line: input.line,\n column: input.column + input.text.length,\n offset: input.end,\n },\n },\n };\n\n // Handle encoding field (MSH-2) - no component parsing\n if (input.isEncodingField) {\n return { ...baseNode, value: input.text };\n }\n\n // Handle header (first field of segment)\n if (input.fieldIndex === 0) {\n return { ...baseNode, value: input.text };\n }\n\n // Check if field contains components\n if (input.text.includes(input.context.delimiters.component)) {\n return {\n ...baseNode,\n delimiter: input.context.delimiters.component,\n children: this.parseComponents(input),\n };\n }\n\n return { ...baseNode, value: input.text };\n }\n\n private parseComponents(input: FieldParseInput): HL7v2Node[] {\n const components = this.splitByDelimiter(\n input.text,\n input.context.delimiters.component\n );\n const nodes: HL7v2Node[] = [];\n\n for (let i = 0; i < components.length; i++) {\n const comp = components[i];\n if (!comp) {\n continue;\n }\n\n const componentNode = this.componentParser.parse({\n type: 'component',\n text: comp.value,\n start: input.start + comp.start,\n end: input.start + comp.end,\n index: i,\n componentIndex: i,\n line: input.line,\n column: input.column + comp.start,\n context: input.context,\n });\n\n if (componentNode) {\n nodes.push(componentNode);\n }\n }\n\n return nodes;\n }\n\n private splitByDelimiter(\n text: string,\n delimiter: string\n ): Array<{ value: string; start: number; end: number }> {\n const result: { value: string; start: number; end: number }[] = [];\n let lastIndex = 0;\n let index = text.indexOf(delimiter);\n\n while (index !== -1) {\n result.push({\n value: text.slice(lastIndex, index),\n start: lastIndex,\n end: index,\n });\n lastIndex = index + delimiter.length;\n index = text.indexOf(delimiter, lastIndex);\n }\n\n result.push({\n value: text.slice(lastIndex),\n start: lastIndex,\n end: text.length,\n });\n\n return result;\n }\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport type { ISegmentParser, SegmentParseInput } from '../../interfaces';\nimport { splitByString } from '../../utils';\nimport { FieldParser } from './field';\n\n/**\n * Default segment parser for standard HL7v2 segments\n */\nexport class SegmentParser implements ISegmentParser {\n segmentType = 'DEFAULT';\n private fieldParser = new FieldParser();\n\n canParse(input: SegmentParseInput): boolean {\n return input.type === 'segment' && input.text.trim().length > 0;\n }\n\n parse(input: SegmentParseInput): HL7v2Node | null {\n if (!this.canParse(input)) {\n return null;\n }\n\n const fields = splitByString(input.text, input.context.delimiters.field);\n if (!fields[0] || fields.length === 0) {\n return null;\n }\n\n const segmentNode: HL7v2Node = {\n type: 'segment',\n name: fields[0].value,\n index: input.index,\n delimiter: input.context.delimiters.field,\n children: [],\n position: {\n start: { line: input.line, column: 1, offset: input.start },\n end: {\n line: input.line,\n column: input.text.length + 1,\n offset: input.end,\n },\n },\n };\n\n segmentNode.children = this.parseFields(fields, input);\n return segmentNode;\n }\n\n private parseFields(\n fields: Array<{ value: string; start: number; end: number }>,\n input: SegmentParseInput\n ): HL7v2Node[] {\n const children: HL7v2Node[] = [];\n\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i];\n if (!field) {\n continue;\n }\n\n const fieldNode = this.fieldParser.parse({\n type: 'field',\n text: field.value,\n start: input.start + field.start,\n end: input.start + field.end,\n index: i,\n fieldIndex: i,\n line: input.line,\n column: field.start + 1,\n context: input.context,\n });\n\n if (fieldNode) {\n children.push(fieldNode);\n }\n }\n\n return children;\n }\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport type { ISegmentParser, SegmentParseInput } from '../../interfaces';\nimport { splitByString } from '../../utils';\nimport { FieldParser } from './field';\n\n/**\n * Specialized parser for MSH segments with special field handling\n */\nexport class MSHSegmentParser implements ISegmentParser {\n segmentType = 'MSH';\n private fieldParser = new FieldParser();\n\n canParse(input: SegmentParseInput): boolean {\n return input.type === 'segment' && input.segmentType === 'MSH';\n }\n\n parse(input: SegmentParseInput): HL7v2Node | null {\n if (!this.canParse(input)) {\n return null;\n }\n\n const fields = this.extractMSHFields(\n input.text,\n input.context.delimiters.field\n );\n\n const segmentNode: HL7v2Node = {\n type: 'segment',\n name: 'MSH',\n index: input.index,\n delimiter: input.context.delimiters.field,\n children: [],\n position: {\n start: { line: input.line, column: 1, offset: input.start },\n end: {\n line: input.line,\n column: input.text.length + 1,\n offset: input.end,\n },\n },\n };\n\n segmentNode.children = this.parseFields(fields, input);\n return segmentNode;\n }\n\n private extractMSHFields(\n segmentText: string,\n fieldDelimiter: string\n ): Array<{\n value: string;\n start: number;\n end: number;\n isEncodingField?: boolean;\n }> {\n const msh1 = segmentText[3] ?? '';\n const msh2 = segmentText.slice(4, 8) ?? '';\n const rest = segmentText.slice(9); // Skip the field delimiter at position 8\n const restFields = splitByString(rest, fieldDelimiter);\n\n return [\n { value: 'MSH', start: 0, end: 3 },\n { value: msh1, start: 3, end: 4 },\n { value: msh2, start: 4, end: 8, isEncodingField: true },\n ...restFields.map((f) => ({\n value: f.value ?? '',\n start: 9 + (f.start ?? 0),\n end: 9 + (f.end ?? 0),\n })),\n ];\n }\n\n private parseFields(\n fields: Array<{\n value: string;\n start: number;\n end: number;\n isEncodingField?: boolean;\n }>,\n input: SegmentParseInput\n ): HL7v2Node[] {\n const children: HL7v2Node[] = [];\n\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i];\n if (!field) {\n continue;\n }\n\n const fieldNode = this.fieldParser.parse({\n type: 'field',\n text: field.value,\n start: input.start + field.start,\n end: input.start + field.end,\n index: i,\n fieldIndex: i,\n line: input.line,\n column: field.start + 1,\n isEncodingField: field.isEncodingField,\n context: input.context,\n });\n\n if (fieldNode) {\n children.push(fieldNode);\n }\n }\n\n return children;\n }\n}\n","import type { ISegmentParser } from '../interfaces';\nimport { SegmentParser } from './parsers/segment';\nimport { MSHSegmentParser } from './parsers/segment-msh';\n\n/**\n * Registry for segment parsers with fallback strategy\n */\nexport class SegmentParserRegistry {\n private parsers = new Map<string, ISegmentParser>();\n private defaultParser: ISegmentParser;\n\n constructor(customParsers?: Map<string, ISegmentParser>) {\n this.defaultParser = new SegmentParser();\n\n // Register built-in parsers\n this.register(new MSHSegmentParser());\n\n // Register custom parsers if provided\n if (customParsers) {\n for (const [, parser] of customParsers) {\n this.register(parser);\n }\n }\n }\n\n /**\n * Register a segment parser for a specific segment type\n */\n register(parser: ISegmentParser): void {\n this.parsers.set(parser.segmentType, parser);\n }\n\n /**\n * Get the appropriate parser for a segment type\n */\n getParser(segmentType: string): ISegmentParser {\n return this.parsers.get(segmentType) || this.defaultParser;\n }\n\n /**\n * Check if a parser is registered for a segment type\n */\n hasParser(segmentType: string): boolean {\n return this.parsers.has(segmentType);\n }\n\n /**\n * Unregister a parser for a segment type\n */\n unregister(segmentType: string): boolean {\n return this.parsers.delete(segmentType);\n }\n\n /**\n * Get all registered segment types\n */\n getRegisteredTypes(): string[] {\n return Array.from(this.parsers.keys());\n }\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport { DEFAULT_DELIMITERS, EMPTY_MESSAGE } from '../../constants';\nimport type { HL7v2Delimiters } from '../../types';\nimport type {\n IMessageParser,\n MessageParseInput,\n ParseContext,\n ParseOptions,\n} from '../interfaces';\nimport { detectDelimitersFromMSH, splitByString } from '../utils';\nimport { SegmentParserRegistry } from './registry';\n\n/**\n * Main message parser that orchestrates the parsing pipeline\n */\nexport class HL7MessageParser implements IMessageParser {\n private segmentRegistry: SegmentParserRegistry;\n\n private options: ParseOptions;\n\n constructor(options: ParseOptions = {}) {\n this.options = options;\n this.segmentRegistry = new SegmentParserRegistry(options.customParsers);\n }\n\n canParse(input: MessageParseInput): boolean {\n return input.type === 'message' && input.text.trim().length > 0;\n }\n\n parse(input: MessageParseInput): HL7v2Node | null {\n if (!this.canParse(input)) {\n return EMPTY_MESSAGE;\n }\n\n const context = this.createParseContext(input.text);\n const segments = splitByString(input.text, context.delimiters.segment);\n\n const messageNode: HL7v2Node = {\n type: 'root',\n delimiter: context.delimiters.segment,\n children: [],\n position: {\n start: { line: 1, column: 1, offset: 0 },\n end: {\n line: segments.length,\n column: (segments.at(-1)?.value.length ?? 0) + 1,\n offset: input.text.length,\n },\n },\n };\n\n let currentLine = 1;\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n const hasContent = seg?.value.trim();\n if (!seg) {\n currentLine++;\n continue;\n }\n if (!hasContent) {\n currentLine++;\n continue;\n }\n\n const segmentNode = this.parseSegment(seg, currentLine, i, context);\n if (segmentNode) {\n messageNode.children = messageNode.children || [];\n messageNode.children.push(segmentNode);\n }\n currentLine++;\n }\n\n return this.applyValidationHooks(messageNode, context);\n }\n\n private createParseContext(rawMessage: string): ParseContext {\n // Merge user-defined delimiters with defaults\n const baseDelimiters: HL7v2Delimiters = {\n ...DEFAULT_DELIMITERS,\n ...this.options.delimiters,\n };\n\n // Auto-detect from MSH-2 if enabled\n let activeDelimiters = baseDelimiters;\n if (this.options.autoDetectDelimiters !== false) {\n const detected = detectDelimitersFromMSH(\n rawMessage,\n baseDelimiters.segment\n );\n activeDelimiters = { ...baseDelimiters, ...detected };\n }\n\n return {\n delimiters: activeDelimiters,\n options: this.options,\n currentLine: 1,\n totalOffset: 0,\n };\n }\n\n private parseSegment(\n segment: { value: string; start: number; end: number },\n line: number,\n index: number,\n context: ParseContext\n ): HL7v2Node | null {\n const segmentType = segment.value.slice(0, 3);\n const parser = this.segmentRegistry.getParser(segmentType);\n\n return parser.parse({\n type: 'segment',\n text: segment.value,\n start: segment.start,\n end: segment.end,\n index,\n segmentType,\n line,\n context,\n });\n }\n\n private applyValidationHooks(\n node: HL7v2Node,\n context: ParseContext\n ): HL7v2Node {\n if (!this.options.validationHooks) {\n return node;\n }\n\n for (const hook of this.options.validationHooks) {\n const result = hook.validate(node, context);\n if (!result.isValid) {\n // TODO: Handle validation errors\n throw new Error(result.errors?.[0] ?? 'Validation error');\n }\n }\n\n return node;\n }\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport { EMPTY_MESSAGE } from './constants';\nimport { HL7MessageParser } from './pipeline/core/message';\nimport type { ParseContext, ParseOptions } from './pipeline/interfaces';\n\n/**\n * Pipeline-based HL7v2 parser.\n *\n * This parser is a wrapper around the HL7MessageParser class.\n * It is used to parse HL7v2 messages into an AST.\n *\n * @param rawMessage - The HL7v2 message to parse.\n * @param options - The options for the parser.\n * @returns The parsed HL7v2 message.\n */\nexport function fromHL7v2Pipeline(\n rawMessage: string,\n options: ParseOptions = {}\n): HL7v2Node {\n const parser = new HL7MessageParser(options);\n\n const result = parser.parse({\n type: 'message',\n text: rawMessage,\n start: 0,\n end: rawMessage.length,\n index: 0,\n context: {\n delimiters: options.delimiters || {},\n options,\n currentLine: 1,\n totalOffset: 0,\n } as ParseContext,\n });\n\n return result || EMPTY_MESSAGE;\n}\n","import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';\nimport type { Plugin } from 'unified';\nimport { fromHL7v2Pipeline } from './parser';\nimport type { ParseOptions } from './types';\n\nconst hl7v2Parser: Plugin<[ParseOptions?], undefined, HL7v2Node> = function (\n options: ParseOptions = {}\n): void {\n // biome-ignore lint/complexity/noUselessThisAlias: this is a plugin\n const self = this;\n\n function parser(this: unknown, value: string): HL7v2Node {\n return fromHL7v2Pipeline(value, options);\n }\n\n self.parser = parser;\n};\n\nexport default hl7v2Parser;\n"],"mappings":"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","names":[]}
package/dist/parser.d.ts CHANGED
@@ -1,8 +1,14 @@
1
1
  import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
- import type { ParseOptions } from './types';
2
+ import type { ParseOptions } from './pipeline/interfaces';
3
3
  /**
4
- * Parse an HL7v2 message into a Unist-compatible DOM tree.
5
- * Tracks lines/columns and preserves delimiters for round-tripping.
4
+ * Pipeline-based HL7v2 parser.
5
+ *
6
+ * This parser is a wrapper around the HL7MessageParser class.
7
+ * It is used to parse HL7v2 messages into an AST.
8
+ *
9
+ * @param rawMessage - The HL7v2 message to parse.
10
+ * @param options - The options for the parser.
11
+ * @returns The parsed HL7v2 message.
6
12
  */
7
- export declare function fromHL7v2(rawMessage: string, options?: ParseOptions): HL7v2Node;
13
+ export declare function fromHL7v2Pipeline(rawMessage: string, options?: ParseOptions): HL7v2Node;
8
14
  //# sourceMappingURL=parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,SAAS,CAAC;AAG7D;;;GAGG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,YAAiB,GACzB,SAAS,CAuEX"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAG1D,OAAO,KAAK,EAAgB,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAExE;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,YAAiB,GACzB,SAAS,CAkBX"}
@@ -0,0 +1,16 @@
1
+ import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
+ import type { IMessageParser, MessageParseInput, ParseOptions } from '../interfaces';
3
+ /**
4
+ * Main message parser that orchestrates the parsing pipeline
5
+ */
6
+ export declare class HL7MessageParser implements IMessageParser {
7
+ private segmentRegistry;
8
+ private options;
9
+ constructor(options?: ParseOptions);
10
+ canParse(input: MessageParseInput): boolean;
11
+ parse(input: MessageParseInput): HL7v2Node | null;
12
+ private createParseContext;
13
+ private parseSegment;
14
+ private applyValidationHooks;
15
+ }
16
+ //# sourceMappingURL=message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/pipeline/core/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAG1D,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EAEjB,YAAY,EACb,MAAM,eAAe,CAAC;AAIvB;;GAEG;AACH,qBAAa,gBAAiB,YAAW,cAAc;IACrD,OAAO,CAAC,eAAe,CAAwB;IAE/C,OAAO,CAAC,OAAO,CAAe;gBAElB,OAAO,GAAE,YAAiB;IAKtC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO;IAI3C,KAAK,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI;IA8CjD,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,oBAAoB;CAkB7B"}
@@ -0,0 +1,13 @@
1
+ import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
+ import type { ComponentParseInput, IComponentParser } from '../../interfaces';
3
+ /**
4
+ * Default component parser that handles subcomponents
5
+ */
6
+ export declare class ComponentParser implements IComponentParser {
7
+ private subcomponentParser;
8
+ canParse(input: ComponentParseInput): boolean;
9
+ parse(input: ComponentParseInput): HL7v2Node | null;
10
+ private parseSubcomponents;
11
+ private splitByDelimiter;
12
+ }
13
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../../src/pipeline/core/parsers/component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAG9E;;GAEG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IACtD,OAAO,CAAC,kBAAkB,CAA4B;IAEtD,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO;IAI7C,KAAK,CAAC,KAAK,EAAE,mBAAmB,GAAG,SAAS,GAAG,IAAI;IA8BnD,OAAO,CAAC,kBAAkB;IAiC1B,OAAO,CAAC,gBAAgB;CA0BzB"}
@@ -0,0 +1,13 @@
1
+ import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
+ import type { FieldParseInput, IFieldParser } from '../../interfaces';
3
+ /**
4
+ * Default field parser that handles components
5
+ */
6
+ export declare class FieldParser implements IFieldParser {
7
+ private componentParser;
8
+ canParse(input: FieldParseInput): boolean;
9
+ parse(input: FieldParseInput): HL7v2Node | null;
10
+ private parseComponents;
11
+ private splitByDelimiter;
12
+ }
13
+ //# sourceMappingURL=field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../../../src/pipeline/core/parsers/field.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGtE;;GAEG;AACH,qBAAa,WAAY,YAAW,YAAY;IAC9C,OAAO,CAAC,eAAe,CAAyB;IAEhD,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO;IAIzC,KAAK,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI;IAwC/C,OAAO,CAAC,eAAe;IAiCvB,OAAO,CAAC,gBAAgB;CA0BzB"}
@@ -0,0 +1,14 @@
1
+ import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
+ import type { ISegmentParser, SegmentParseInput } from '../../interfaces';
3
+ /**
4
+ * Specialized parser for MSH segments with special field handling
5
+ */
6
+ export declare class MSHSegmentParser implements ISegmentParser {
7
+ segmentType: string;
8
+ private fieldParser;
9
+ canParse(input: SegmentParseInput): boolean;
10
+ parse(input: SegmentParseInput): HL7v2Node | null;
11
+ private extractMSHFields;
12
+ private parseFields;
13
+ }
14
+ //# sourceMappingURL=segment-msh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment-msh.d.ts","sourceRoot":"","sources":["../../../../src/pipeline/core/parsers/segment-msh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAI1E;;GAEG;AACH,qBAAa,gBAAiB,YAAW,cAAc;IACrD,WAAW,SAAS;IACpB,OAAO,CAAC,WAAW,CAAqB;IAExC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO;IAI3C,KAAK,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI;IA8BjD,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,WAAW;CAqCpB"}
@@ -0,0 +1,13 @@
1
+ import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
+ import type { ISegmentParser, SegmentParseInput } from '../../interfaces';
3
+ /**
4
+ * Default segment parser for standard HL7v2 segments
5
+ */
6
+ export declare class SegmentParser implements ISegmentParser {
7
+ segmentType: string;
8
+ private fieldParser;
9
+ canParse(input: SegmentParseInput): boolean;
10
+ parse(input: SegmentParseInput): HL7v2Node | null;
11
+ private parseFields;
12
+ }
13
+ //# sourceMappingURL=segment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment.d.ts","sourceRoot":"","sources":["../../../../src/pipeline/core/parsers/segment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAI1E;;GAEG;AACH,qBAAa,aAAc,YAAW,cAAc;IAClD,WAAW,SAAa;IACxB,OAAO,CAAC,WAAW,CAAqB;IAExC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO;IAI3C,KAAK,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI;IA8BjD,OAAO,CAAC,WAAW;CA+BpB"}
@@ -0,0 +1,10 @@
1
+ import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
+ import type { ISubcomponentParser, SubcomponentParseInput } from '../../interfaces';
3
+ /**
4
+ * Default subcomponent parser - leaf level parser
5
+ */
6
+ export declare class SubcomponentParser implements ISubcomponentParser {
7
+ canParse(input: SubcomponentParseInput): boolean;
8
+ parse(input: SubcomponentParseInput): HL7v2Node | null;
9
+ }
10
+ //# sourceMappingURL=subcomponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subcomponent.d.ts","sourceRoot":"","sources":["../../../../src/pipeline/core/parsers/subcomponent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EACV,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,kBAAkB,CAAC;AAE1B;;GAEG;AACH,qBAAa,kBAAmB,YAAW,mBAAmB;IAC5D,QAAQ,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO;IAIhD,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,SAAS,GAAG,IAAI;CAmBvD"}
@@ -0,0 +1,30 @@
1
+ import type { ISegmentParser } from '../interfaces';
2
+ /**
3
+ * Registry for segment parsers with fallback strategy
4
+ */
5
+ export declare class SegmentParserRegistry {
6
+ private parsers;
7
+ private defaultParser;
8
+ constructor(customParsers?: Map<string, ISegmentParser>);
9
+ /**
10
+ * Register a segment parser for a specific segment type
11
+ */
12
+ register(parser: ISegmentParser): void;
13
+ /**
14
+ * Get the appropriate parser for a segment type
15
+ */
16
+ getParser(segmentType: string): ISegmentParser;
17
+ /**
18
+ * Check if a parser is registered for a segment type
19
+ */
20
+ hasParser(segmentType: string): boolean;
21
+ /**
22
+ * Unregister a parser for a segment type
23
+ */
24
+ unregister(segmentType: string): boolean;
25
+ /**
26
+ * Get all registered segment types
27
+ */
28
+ getRegisteredTypes(): string[];
29
+ }
30
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/pipeline/core/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,aAAa,CAAiB;gBAE1B,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC;IAcvD;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAItC;;OAEG;IACH,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc;IAI9C;;OAEG;IACH,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIvC;;OAEG;IACH,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIxC;;OAEG;IACH,kBAAkB,IAAI,MAAM,EAAE;CAG/B"}
@@ -0,0 +1,10 @@
1
+ export { HL7MessageParser } from './core/message';
2
+ export { ComponentParser } from './core/parsers/component';
3
+ export { FieldParser } from './core/parsers/field';
4
+ export { SegmentParser } from './core/parsers/segment';
5
+ export { MSHSegmentParser } from './core/parsers/segment-msh';
6
+ export { SubcomponentParser } from './core/parsers/subcomponent';
7
+ export { SegmentParserRegistry } from './core/registry';
8
+ export type { ComponentParseInput, FieldParseInput, IComponentParser, IFieldParser, IMessageParser, ISegmentParser, ISubcomponentParser, MessageParseInput, ParseContext, ParseInput, ParseOptions, Parser, PipelineStage, SegmentParseInput, SubcomponentParseInput, ValidationHook, ValidationResult, } from './interfaces';
9
+ export { BasicValidationHook, SegmentRequirementValidationHook, } from './validation/basic-validation';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pipeline/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExD,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,EACd,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,mBAAmB,EACnB,gCAAgC,GACjC,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,109 @@
1
+ import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
+ import type { HL7v2Delimiters } from '../types';
3
+ /**
4
+ * Context passed between pipeline stages
5
+ */
6
+ export interface ParseContext {
7
+ delimiters: HL7v2Delimiters;
8
+ options: ParseOptions;
9
+ currentLine: number;
10
+ totalOffset: number;
11
+ }
12
+ /**
13
+ * Parse options for the pipeline
14
+ */
15
+ export interface ParseOptions {
16
+ delimiters?: Partial<HL7v2Delimiters>;
17
+ autoDetectDelimiters?: boolean;
18
+ customParsers?: Map<string, ISegmentParser>;
19
+ validationHooks?: ValidationHook[];
20
+ }
21
+ /**
22
+ * Input for any parser stage
23
+ */
24
+ export interface ParseInput {
25
+ text: string;
26
+ start: number;
27
+ end: number;
28
+ index: number;
29
+ context: ParseContext;
30
+ }
31
+ /**
32
+ * Base interface for all parsers
33
+ */
34
+ export interface Parser<TInput extends ParseInput, TOutput extends HL7v2Node> {
35
+ parse(input: TInput): TOutput | null;
36
+ canParse(input: TInput): boolean;
37
+ }
38
+ /**
39
+ * Message-level parser interface
40
+ */
41
+ export interface IMessageParser extends Parser<MessageParseInput, HL7v2Node> {
42
+ }
43
+ export interface MessageParseInput extends ParseInput {
44
+ type: 'message';
45
+ }
46
+ /**
47
+ * Segment-level parser interface
48
+ */
49
+ export interface ISegmentParser extends Parser<SegmentParseInput, HL7v2Node> {
50
+ segmentType: string;
51
+ }
52
+ export interface SegmentParseInput extends ParseInput {
53
+ type: 'segment';
54
+ segmentType: string;
55
+ line: number;
56
+ }
57
+ /**
58
+ * Field-level parser interface
59
+ */
60
+ export interface IFieldParser extends Parser<FieldParseInput, HL7v2Node> {
61
+ }
62
+ export interface FieldParseInput extends ParseInput {
63
+ type: 'field';
64
+ fieldIndex: number;
65
+ line: number;
66
+ column: number;
67
+ isEncodingField?: boolean;
68
+ }
69
+ /**
70
+ * Component-level parser interface
71
+ */
72
+ export interface IComponentParser extends Parser<ComponentParseInput, HL7v2Node> {
73
+ }
74
+ export interface ComponentParseInput extends ParseInput {
75
+ type: 'component';
76
+ componentIndex: number;
77
+ line: number;
78
+ column: number;
79
+ }
80
+ /**
81
+ * Subcomponent-level parser interface
82
+ */
83
+ export interface ISubcomponentParser extends Parser<SubcomponentParseInput, HL7v2Node> {
84
+ }
85
+ export interface SubcomponentParseInput extends ParseInput {
86
+ type: 'subcomponent';
87
+ subcomponentIndex: number;
88
+ line: number;
89
+ column: number;
90
+ }
91
+ /**
92
+ * Validation hook interface
93
+ */
94
+ export interface ValidationHook {
95
+ validate(node: HL7v2Node, context: ParseContext): ValidationResult;
96
+ }
97
+ export interface ValidationResult {
98
+ isValid: boolean;
99
+ warnings?: string[];
100
+ errors?: string[];
101
+ }
102
+ /**
103
+ * Pipeline stage interface
104
+ */
105
+ export interface PipelineStage<TInput extends ParseInput, TOutput extends HL7v2Node> {
106
+ process(input: TInput): TOutput | null;
107
+ name: string;
108
+ }
109
+ //# sourceMappingURL=interfaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/pipeline/interfaces.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { HL7v2Delimiters } from './types';
1
+ import type { HL7v2Delimiters } from '../../types';
2
2
  /**
3
3
  * Auto-detect custom delimiters from MSH-1 and MSH-2
4
4
  */
@@ -11,4 +11,8 @@ export declare function splitByString(text: string, delimiter: string): Array<{
11
11
  start: number;
12
12
  end: number;
13
13
  }>;
14
- //# sourceMappingURL=utils.d.ts.map
14
+ /**
15
+ * Detect the segment delimiter used in the message
16
+ */
17
+ export declare function detectSegmentDelimiter(message: string, fallback?: string): string;
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/pipeline/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,eAAe,CAAC,CAmC1B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAqBtD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,SAAO,GACd,MAAM,CAYR"}
@@ -0,0 +1,17 @@
1
+ import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
+ import type { ParseContext, ValidationHook, ValidationResult } from '../interfaces';
3
+ /**
4
+ * Basic validation hook that checks for common HL7v2 message structure issues
5
+ */
6
+ export declare class BasicValidationHook implements ValidationHook {
7
+ validate(node: HL7v2Node, _context: ParseContext): ValidationResult;
8
+ }
9
+ /**
10
+ * Custom validation hook for specific segment requirements
11
+ */
12
+ export declare class SegmentRequirementValidationHook implements ValidationHook {
13
+ private requirements;
14
+ constructor(requirements: Map<string, number>);
15
+ validate(node: HL7v2Node, _context: ParseContext): ValidationResult;
16
+ }
17
+ //# sourceMappingURL=basic-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basic-validation.d.ts","sourceRoot":"","sources":["../../../src/pipeline/validation/basic-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,gBAAgB,EACjB,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,qBAAa,mBAAoB,YAAW,cAAc;IACxD,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,GAAG,gBAAgB;CAmCpE;AAED;;GAEG;AACH,qBAAa,gCAAiC,YAAW,cAAc;IACrE,OAAO,CAAC,YAAY,CAAsB;gBAE9B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAI7C,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,GAAG,gBAAgB;CAuBpE"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rethinkhealth/hl7v2-parser",
3
3
  "description": "hl7v2 plugin to parse hl7v2 messages",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "license": "MIT",
6
6
  "author": {
7
7
  "name": "Melek Somai",
@@ -26,9 +26,9 @@
26
26
  "tsup": "8.5.0",
27
27
  "typescript": "^5.8.3",
28
28
  "vitest": "^3.2.4",
29
+ "@rethinkhealth/hl7v2-ast": "0.2.1",
29
30
  "@rethinkhealth/testing": "0.0.0",
30
- "@rethinkhealth/tsconfig": "0.0.0",
31
- "@rethinkhealth/hl7v2-ast": "0.1.0"
31
+ "@rethinkhealth/tsconfig": "0.0.0"
32
32
  },
33
33
  "repository": "rethinkhealth/hl7v2.git",
34
34
  "homepage": "https://www.rethinkhealth.io/hl7v2/docs",
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,eAAe,CAAC,CA4B1B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAqBtD"}