@rethinkhealth/hl7v2-parser 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +14 -8
  2. package/dist/index.d.ts +4 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +325 -534
  5. package/dist/index.js.map +1 -1
  6. package/dist/parser.d.ts +6 -13
  7. package/dist/parser.d.ts.map +1 -1
  8. package/dist/preprocessor.d.ts +26 -0
  9. package/dist/preprocessor.d.ts.map +1 -0
  10. package/dist/processor.d.ts +3 -5
  11. package/dist/processor.d.ts.map +1 -1
  12. package/dist/tokenizer.d.ts +18 -0
  13. package/dist/tokenizer.d.ts.map +1 -0
  14. package/dist/types.d.ts +29 -13
  15. package/dist/types.d.ts.map +1 -1
  16. package/dist/utils.d.ts +3 -0
  17. package/dist/utils.d.ts.map +1 -0
  18. package/package.json +6 -5
  19. package/dist/constants.d.ts +0 -11
  20. package/dist/constants.d.ts.map +0 -1
  21. package/dist/pipeline/core/message.d.ts +0 -16
  22. package/dist/pipeline/core/message.d.ts.map +0 -1
  23. package/dist/pipeline/core/parsers/component.d.ts +0 -13
  24. package/dist/pipeline/core/parsers/component.d.ts.map +0 -1
  25. package/dist/pipeline/core/parsers/field.d.ts +0 -13
  26. package/dist/pipeline/core/parsers/field.d.ts.map +0 -1
  27. package/dist/pipeline/core/parsers/segment-msh.d.ts +0 -14
  28. package/dist/pipeline/core/parsers/segment-msh.d.ts.map +0 -1
  29. package/dist/pipeline/core/parsers/segment.d.ts +0 -13
  30. package/dist/pipeline/core/parsers/segment.d.ts.map +0 -1
  31. package/dist/pipeline/core/parsers/subcomponent.d.ts +0 -10
  32. package/dist/pipeline/core/parsers/subcomponent.d.ts.map +0 -1
  33. package/dist/pipeline/core/registry.d.ts +0 -30
  34. package/dist/pipeline/core/registry.d.ts.map +0 -1
  35. package/dist/pipeline/index.d.ts +0 -10
  36. package/dist/pipeline/index.d.ts.map +0 -1
  37. package/dist/pipeline/interfaces.d.ts +0 -109
  38. package/dist/pipeline/interfaces.d.ts.map +0 -1
  39. package/dist/pipeline/utils/index.d.ts +0 -18
  40. package/dist/pipeline/utils/index.d.ts.map +0 -1
  41. package/dist/pipeline/validation/basic-validation.d.ts +0 -17
  42. package/dist/pipeline/validation/basic-validation.d.ts.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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":[]}
1
+ {"version":3,"sources":["../src/processor.ts","../src/tokenizer.ts","../src/utils.ts","../src/parser.ts","../src/preprocessor.ts"],"sourcesContent":["// src/parser.ts\n\nimport type {\n Component,\n Field,\n FieldRepetition,\n Root,\n Segment,\n Subcomponent,\n} from '@rethinkhealth/hl7v2-ast';\nimport type { Token } from './types';\n\n// Shared core: process a single token into mutable parse state\nfunction createParserCore() {\n const root: Root = { type: 'root', children: [] };\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\n const openSegment = () => {\n seg = { type: 'segment', children: [] };\n root.children.push(seg);\n field = null;\n rep = null;\n comp = null;\n currentSub = null;\n segmentHasContent = false;\n };\n\n const ensureSegment = () => {\n if (!seg) {\n openSegment();\n }\n };\n\n const openField = () => {\n ensureSegment();\n field = { type: 'field', children: [] };\n // biome-ignore lint/style/noNonNullAssertion: seg is ensured above\n seg!.children.push(field);\n rep = { type: 'field-repetition', children: [] };\n field.children.push(rep);\n comp = { type: 'component', children: [] };\n rep.children.push(comp);\n currentSub = null;\n segmentHasContent = true;\n };\n\n const openRepetition = () => {\n if (!field) {\n openField();\n }\n rep = { type: 'field-repetition', children: [] };\n // biome-ignore lint/style/noNonNullAssertion: field is ensured above\n field!.children.push(rep);\n comp = { type: 'component', children: [] };\n rep.children.push(comp);\n currentSub = null;\n segmentHasContent = true;\n };\n\n const openComponent = () => {\n if (!field) {\n openField();\n }\n if (!rep) {\n rep = { type: 'field-repetition', children: [] };\n // biome-ignore lint/style/noNonNullAssertion: field is ensured above\n field!.children.push(rep);\n }\n comp = { type: 'component', children: [] };\n // biome-ignore lint/style/noNonNullAssertion: rep is ensured above\n rep!.children.push(comp);\n currentSub = null;\n segmentHasContent = true;\n };\n\n const ensureForText = () => {\n if (!field) {\n openField();\n }\n if (!rep) {\n openRepetition();\n }\n if (!comp) {\n openComponent();\n }\n if (!currentSub) {\n currentSub = { type: 'subcomponent', value: '' };\n // biome-ignore lint/style/noNonNullAssertion: comp is ensured above\n comp!.children.push(currentSub);\n segmentHasContent = true;\n }\n };\n\n const processToken = (tok: Token) => {\n switch (tok.type) {\n case 'SEGMENT_END': {\n dropTrailingEmptyFieldIfPresent();\n // Close current segment (if any) and reset; do not auto-open next segment\n seg = null;\n field = null;\n rep = null;\n comp = null;\n currentSub = null;\n segmentHasContent = false;\n return;\n }\n case 'FIELD_DELIM': {\n // Leading field delimiter implies an empty first field\n if (!field) {\n // Open an empty first field and record an empty subcomponent slot\n openField();\n // biome-ignore lint/style/noNonNullAssertion: comp is initialized in openField\n comp!.children.push({ type: 'subcomponent', value: '' });\n segmentHasContent = true;\n }\n openField();\n return;\n }\n case 'REPETITION_DELIM': {\n if (!field) {\n openField();\n }\n openRepetition();\n return;\n }\n case 'COMPONENT_DELIM': {\n openComponent();\n return;\n }\n case 'SUBCOMP_DELIM': {\n if (!comp) {\n openComponent();\n }\n // Start a new empty subcomponent slot\n currentSub = { type: 'subcomponent', value: '' };\n // biome-ignore lint/style/noNonNullAssertion: comp is ensured above\n comp!.children.push(currentSub);\n segmentHasContent = true;\n return;\n }\n case 'TEXT': {\n const val = tok.value ?? '';\n ensureForText();\n // biome-ignore lint/style/noNonNullAssertion: ensured above\n currentSub!.value += val;\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 dropTrailingEmptyFieldIfPresent();\n if (seg && !segmentHasContent) {\n // Drop trailing empty segment if no content was added\n root.children.pop();\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 lastField = seg.children.at(-1) as Field;\n const hasAnySubcomponents = lastField.children.some((r) =>\n r.children.some((c) => c.children.length > 0)\n );\n if (!hasAnySubcomponents) {\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(tokens: Iterable<Token>): Root {\n const core = createParserCore();\n for (const tok of tokens) {\n core.processToken(tok);\n }\n return core.finalize();\n}\n","// src/tokenizer.ts\nimport {\n DEFAULT_DELIMITERS,\n type HL7v2Delimiters,\n} from '@rethinkhealth/hl7v2-utils';\nimport type {\n ParseOptions,\n Position,\n Token,\n Tokenizer,\n TokenType,\n} from './types';\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!: HL7v2Delimiters;\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(input: string, opts: ParseOptions) {\n this.input = input;\n this.delims = opts.delimiters || DEFAULT_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(0, 3);\n const msh2 = this._slice(4, 8); // may be shorter than 4 if truncated\n this.pendingBootstrap = [\n { kind: 'TEXT', value: msh, advance: msh.length },\n { kind: 'FIELD_DELIM', advance: 1 }, // consume the single field delimiter char at index 3\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('\\r');\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 // Async iteration support removed to keep the API synchronous.\n}\n","import type { Token, Tokenizer } from './types';\n\nexport function* iterateTokenizerSync(t: Tokenizer): Iterable<Token> {\n for (let tok = t.next(); tok; tok = t.next()) {\n yield tok;\n }\n}\n\n// Removed async stream support; the parser now operates synchronously only.\n","import type { Root } from '@rethinkhealth/hl7v2-ast';\nimport type { Plugin } from 'unified';\nimport { parseHL7v2FromIterator } from './processor';\nimport { HL7v2Tokenizer } from './tokenizer';\nimport type { ParseOptions } from './types';\nimport { iterateTokenizerSync } from './utils';\n\n// Back-compat convenience API: parse from string using the built-in tokenizer (sync)\nexport function parseHL7v2(input: string, opts: ParseOptions): Root {\n const tokenizer = new HL7v2Tokenizer();\n tokenizer.reset(input, opts);\n return parseHL7v2FromIterator(iterateTokenizerSync(tokenizer));\n}\n\nconst hl7v2Parser: Plugin<[ParseOptions?], string, Root> = function (\n options = {}\n) {\n const self = this as { parser?: (value: string) => Root };\n self.parser = (value: string) => parseHL7v2(value, options);\n};\n\nexport default hl7v2Parser;\n","import type { ParseOptions, ParserContext } from './types';\n\n/**\n * A preprocessing step: takes a ParserContext, mutates or replaces it.\n */\nexport type PreprocessorStep = (ctx: ParserContext) => ParserContext;\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 CR (\\r).\n */\nexport const normalizeNewlines: PreprocessorStep = (ctx) => {\n ctx.input = ctx.input.replace(/\\r?\\n/g, '\\r');\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 fieldDelim = ctx.input.charAt(3) || '|';\n const enc = ctx.input.slice(4, 8);\n const component = enc.charAt(0) || '^';\n const repetition = enc.charAt(1) || '~';\n const _escape = enc.charAt(2) || '\\\\';\n const subcomponent = enc.charAt(3) || '&';\n\n ctx.options.delimiters = {\n field: fieldDelim,\n component,\n repetition,\n escape: _escape,\n subcomponent,\n segment: '\\r',\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 raw: string,\n opts: ParseOptions = {},\n steps: PreprocessorStep[] = defaultPreprocessors\n): ParserContext {\n let ctx: ParserContext = {\n input: raw,\n options: opts,\n metadata: {},\n };\n\n for (const step of steps) {\n ctx = step(ctx);\n }\n\n return ctx;\n}\n"],"mappings":"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","names":[]}
package/dist/parser.d.ts CHANGED
@@ -1,14 +1,7 @@
1
- import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
- import type { ParseOptions } from './pipeline/interfaces';
3
- /**
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.
12
- */
13
- export declare function fromHL7v2Pipeline(rawMessage: string, options?: ParseOptions): HL7v2Node;
1
+ import type { Root } from '@rethinkhealth/hl7v2-ast';
2
+ import type { Plugin } from 'unified';
3
+ import type { ParseOptions } from './types';
4
+ export declare function parseHL7v2(input: string, opts: ParseOptions): Root;
5
+ declare const hl7v2Parser: Plugin<[ParseOptions?], string, Root>;
6
+ export default hl7v2Parser;
14
7
  //# 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;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"}
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,MAAM,EAAE,MAAM,SAAS,CAAC;AAGtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI5C,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAIlE;AAED,QAAA,MAAM,WAAW,EAAE,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAKtD,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ParseOptions, ParserContext } from './types';
2
+ /**
3
+ * A preprocessing step: takes a ParserContext, mutates or replaces it.
4
+ */
5
+ export type PreprocessorStep = (ctx: ParserContext) => ParserContext;
6
+ /**
7
+ * Step: strip UTF-8 BOM.
8
+ */
9
+ export declare const stripBOM: PreprocessorStep;
10
+ /**
11
+ * Step: normalize newlines to CR (\r).
12
+ */
13
+ export declare const normalizeNewlines: PreprocessorStep;
14
+ /**
15
+ * Step: auto-detect delimiters from MSH.
16
+ */
17
+ export declare const detectDelimiters: PreprocessorStep;
18
+ /**
19
+ * Default preprocessing pipeline.
20
+ */
21
+ export declare const defaultPreprocessors: PreprocessorStep[];
22
+ /**
23
+ * Run the pipeline to initialize ParserContext.
24
+ */
25
+ export declare function runPreprocessors(raw: string, opts?: ParseOptions, steps?: PreprocessorStep[]): ParserContext;
26
+ //# sourceMappingURL=preprocessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preprocessor.d.ts","sourceRoot":"","sources":["../src/preprocessor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE3D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,aAAa,CAAC;AAErE;;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,gBAmB9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,gBAAgB,EAIlD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,YAAiB,EACvB,KAAK,GAAE,gBAAgB,EAAyB,GAC/C,aAAa,CAYf"}
@@ -1,6 +1,4 @@
1
- import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
- import type { Plugin } from 'unified';
3
- import type { ParseOptions } from './types';
4
- declare const hl7v2Parser: Plugin<[ParseOptions?], undefined, HL7v2Node>;
5
- export default hl7v2Parser;
1
+ import type { Root } from '@rethinkhealth/hl7v2-ast';
2
+ import type { Token } from './types';
3
+ export declare function parseHL7v2FromIterator(tokens: Iterable<Token>): Root;
6
4
  //# sourceMappingURL=processor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"processor.d.ts","sourceRoot":"","sources":["../src/processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,QAAA,MAAM,WAAW,EAAE,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,CAW9D,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"processor.d.ts","sourceRoot":"","sources":["../src/processor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAIV,IAAI,EAGL,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAqLrC,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,CAMpE"}
@@ -0,0 +1,18 @@
1
+ import type { ParseOptions, Token, Tokenizer } from './types';
2
+ export declare class HL7v2Tokenizer implements Tokenizer, Iterable<Token> {
3
+ private input;
4
+ private i;
5
+ private line;
6
+ private col;
7
+ private delims;
8
+ private didMshBootstrap;
9
+ private pendingBootstrap;
10
+ reset(input: string, opts: ParseOptions): void;
11
+ next(): Token | null;
12
+ private _slice;
13
+ private _advance;
14
+ private _fastAdvance;
15
+ private _tok;
16
+ [Symbol.iterator](): Iterator<Token>;
17
+ }
18
+ //# sourceMappingURL=tokenizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../src/tokenizer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EAEZ,KAAK,EACL,SAAS,EAEV,MAAM,SAAS,CAAC;AAEjB,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,CAAmB;IAGjC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAGf;IAET,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY;IAwBvC,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;CAarC"}
package/dist/types.d.ts CHANGED
@@ -1,16 +1,32 @@
1
- export interface ParseOptions {
2
- delimiters?: Partial<HL7v2Delimiters>;
3
- autoDetectDelimiters?: boolean;
1
+ import type { HL7v2Delimiters } from '@rethinkhealth/hl7v2-utils';
2
+ export type ParseOptions = {
3
+ delimiters?: HL7v2Delimiters;
4
+ };
5
+ export interface ParserContext {
6
+ input: string;
7
+ options: ParseOptions;
8
+ metadata?: Record<string, unknown>;
4
9
  }
5
- /**
6
- * HL7v2 Delimiters type
7
- */
8
- export interface HL7v2Delimiters {
9
- field: string;
10
- component: string;
11
- subcomponent: string;
12
- repetition: string;
13
- escape: string;
14
- segment: string;
10
+ export type Position = {
11
+ start: {
12
+ offset: number;
13
+ line: number;
14
+ column: number;
15
+ };
16
+ end: {
17
+ offset: number;
18
+ line: number;
19
+ column: number;
20
+ };
21
+ };
22
+ export type Token = {
23
+ type: TokenType;
24
+ value?: string;
25
+ position: Position;
26
+ };
27
+ export type TokenType = 'SEGMENT_START' | 'SEGMENT_END' | 'FIELD_DELIM' | 'REPETITION_DELIM' | 'COMPONENT_DELIM' | 'SUBCOMP_DELIM' | 'TEXT';
28
+ export interface Tokenizer {
29
+ reset(input: string, opts: ParseOptions): void;
30
+ next(): Token | null;
15
31
  }
16
32
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACtC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IAEtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAGD,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC;AAGF,MAAM,MAAM,SAAS,GACjB,eAAe,GACf,aAAa,GACb,aAAa,GACb,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,GACf,MAAM,CAAC;AAEX,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/C,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC;CACtB"}
@@ -0,0 +1,3 @@
1
+ import type { Token, Tokenizer } from './types';
2
+ export declare function iterateTokenizerSync(t: Tokenizer): Iterable<Token>;
3
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEhD,wBAAiB,oBAAoB,CAAC,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAInE"}
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.2",
4
+ "version": "0.2.4",
5
5
  "license": "MIT",
6
6
  "author": {
7
7
  "name": "Melek Somai",
@@ -16,7 +16,8 @@
16
16
  ".": "./dist/index.js"
17
17
  },
18
18
  "dependencies": {
19
- "unified": "11.0.1"
19
+ "unified": "11.0.1",
20
+ "@rethinkhealth/hl7v2-utils": "0.2.4"
20
21
  },
21
22
  "devDependencies": {
22
23
  "@types/node": "22.15.31",
@@ -26,9 +27,9 @@
26
27
  "tsup": "8.5.0",
27
28
  "typescript": "^5.8.3",
28
29
  "vitest": "^3.2.4",
29
- "@rethinkhealth/hl7v2-ast": "0.2.2",
30
- "@rethinkhealth/tsconfig": "0.0.0",
31
- "@rethinkhealth/testing": "0.0.0"
30
+ "@rethinkhealth/hl7v2-ast": "0.2.4",
31
+ "@rethinkhealth/testing": "0.0.0",
32
+ "@rethinkhealth/tsconfig": "0.0.0"
32
33
  },
33
34
  "repository": "rethinkhealth/hl7v2.git",
34
35
  "homepage": "https://www.rethinkhealth.io/hl7v2/docs",
@@ -1,11 +0,0 @@
1
- import type { HL7v2Node } from '@rethinkhealth/hl7v2-ast';
2
- import type { HL7v2Delimiters } from './types';
3
- /**
4
- * Default HL7v2 delimiters
5
- */
6
- export declare const DEFAULT_DELIMITERS: HL7v2Delimiters;
7
- /**
8
- * Empty message node
9
- */
10
- export declare const EMPTY_MESSAGE: HL7v2Node;
11
- //# sourceMappingURL=constants.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAOhC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,SAQ3B,CAAC"}
@@ -1,16 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,13 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,13 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,14 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,13 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,10 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,30 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,10 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,109 +0,0 @@
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