@glion/util-query 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -190,7 +190,9 @@ Canonical path grammar:
|
|
|
190
190
|
- `SEGMENT-FIELD[REP]` — field repetition (e.g., `PID-5[2]`)
|
|
191
191
|
- `SEGMENT-FIELD[REP].COMP` — component (e.g., `PID-5[1].2`)
|
|
192
192
|
- `SEGMENT-FIELD[REP].COMP.SUB` — subcomponent (e.g., `PID-5[1].2.1`)
|
|
193
|
-
- `GROUP[N]-...` — qualify with group name and optional repetition (e.g., `
|
|
193
|
+
- `GROUP[N]-...` — qualify with group name and optional repetition (e.g., `ORDER_OBSERVATION[2]-OBX-5`)
|
|
194
|
+
|
|
195
|
+
A segment or group name is an uppercase letter followed by uppercase letters, digits, and underscores, such as `PID` or `PATIENT_RESULT`.
|
|
194
196
|
|
|
195
197
|
Repetition indexes are **1-based**. If you omit `[n]`, `select`/`value`/`matches` assume `[1]`.
|
|
196
198
|
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import { DEFAULT_DELIMITERS } from "@glion/utils";
|
|
|
31
31
|
* group)
|
|
32
32
|
* - `ORDER-ORC-1` → ORDER is navigation, ORC is segment (has field access)
|
|
33
33
|
*/
|
|
34
|
-
const PATH_REGEX = /^((?:[A-Z][A-Z0-
|
|
34
|
+
const PATH_REGEX = /^((?:[A-Z][A-Z0-9_]*(?:\[\d+\])?-)*)([A-Z][A-Z0-9_]*)(?:\[(\d+)\])?(?:-(\d+)(?:(?:\[(\d+)\])?(?:\.(\d+)(?:\.(\d+))?)?)?)?$/;
|
|
35
35
|
/**
|
|
36
36
|
* Cache for parsed paths to avoid re-parsing the same path multiple times.
|
|
37
37
|
* No eviction — the realistic set of unique paths in an application is
|
|
@@ -137,7 +137,7 @@ function parseImpl(path) {
|
|
|
137
137
|
}
|
|
138
138
|
if (groupsRaw) {
|
|
139
139
|
const groups = [];
|
|
140
|
-
for (const groupMatch of groupsRaw.matchAll(/([A-Z][A-Z0-
|
|
140
|
+
for (const groupMatch of groupsRaw.matchAll(/([A-Z][A-Z0-9_]*)(?:\[(\d+)\])?-/g)) {
|
|
141
141
|
const name = groupMatch[1];
|
|
142
142
|
if (!name) continue;
|
|
143
143
|
const repStr = groupMatch[2];
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/parse.ts","../src/utils.ts","../src/select.ts","../src/value.ts","../src/delimiters.ts","../src/format.ts","../src/matches.ts","../src/set.ts"],"sourcesContent":["import type { GroupLocator, PathParts } from \"./types\";\n\n/**\n * Regular expression for canonical HL7 paths.\n *\n * Format:\n * [GROUP[N]-]...[GROUP[N]-]NAME[N][-FIELD[REPETITION][.COMPONENT[.SUBCOMPONENT]]]\n *\n * **Design Philosophy**: Groups vs Segments are distinguished by POSITION and\n * USAGE, not name length:\n *\n * - **Navigation (Groups)**: Names appearing as prefixes (before the final name)\n * are treated as group navigation: `ORDER-ORC`, `ORDER-TIMING-TQ1`\n * - **Target (Segments)**: The final name in the path is the query target.\n * Whether it's a segment or group is determined by:\n *\n * 1. Field access (-.digit): Definitively a segment → `ORC-1`, `ORDER-ORC-1`\n * 2. No field access: Query the AST to see what exists → `ORC`, `ORDER`\n *\n * This approach:\n *\n * - Makes no assumptions about name length (works with standard 3-char segments\n * AND edge cases)\n * - Lets the path structure indicate intent (field access = segment internals)\n * - Allows the AST to be the source of truth for what exists\n *\n * Examples:\n *\n * - `MSH-3` → MSH is segment (has field access)\n * - `ORDER-ORC` → ORDER is navigation, ORC is target (could be segment or nested\n * group)\n * - `ORDER-ORC-1` → ORDER is navigation, ORC is segment (has field access)\n */\nconst PATH_REGEX =\n /^((?:[A-Z][A-Z0-9]*(?:\\[\\d+\\])?-)*)([A-Z][A-Z0-9]*)(?:\\[(\\d+)\\])?(?:-(\\d+)(?:(?:\\[(\\d+)\\])?(?:\\.(\\d+)(?:\\.(\\d+))?)?)?)?$/;\n\n/**\n * Cache for parsed paths to avoid re-parsing the same path multiple times.\n * No eviction — the realistic set of unique paths in an application is\n * small (50-100 entries) and the memory cost is negligible.\n */\nconst parseCache = new Map<string, PathParts>();\n\nexport function clearParseCache(): void {\n parseCache.clear();\n}\n\nexport function getParseCacheSize(): number {\n return parseCache.size;\n}\n\n/**\n * Pre-computed PathParts for frequently accessed MSH fields.\n *\n * Multiple plugins and lint rules read MSH-9 (message type) and MSH-12\n * (version) on every message. Skipping regex parsing and cache lookups\n * for these paths eliminates ~100ns per call.\n */\nconst HOT_PATHS: Record<string, PathParts> = {\n \"MSH-10\": { field: 10, segment: { name: \"MSH\" } },\n \"MSH-12\": { field: 12, segment: { name: \"MSH\" } },\n \"MSH-3\": { field: 3, segment: { name: \"MSH\" } },\n \"MSH-4\": { field: 4, segment: { name: \"MSH\" } },\n \"MSH-5\": { field: 5, segment: { name: \"MSH\" } },\n \"MSH-6\": { field: 6, segment: { name: \"MSH\" } },\n \"MSH-9\": { field: 9, segment: { name: \"MSH\" } },\n \"MSH-9.1\": { component: 1, field: 9, segment: { name: \"MSH\" } },\n \"MSH-9.2\": { component: 2, field: 9, segment: { name: \"MSH\" } },\n \"MSH-9.3\": { component: 3, field: 9, segment: { name: \"MSH\" } },\n};\n\n/**\n * Parse an HL7 path string into structured parts.\n * Results are memoized for performance. Common MSH paths use\n * pre-computed constants to skip parsing entirely.\n *\n * @example\n * ```typescript\n * parse(\"PID-5[1].2.1\");\n * // {\n * // segment: { name: 'PID' },\n * // field: 5,\n * // repetition: 1,\n * // component: 2,\n * // subcomponent: 1\n * // }\n * ```;\n *\n * @param path - HL7 path string to parse\n * @returns Structured path components\n */\nexport function parse(path: string): PathParts {\n // Hot path: pre-computed results for common MSH field reads\n const hot = HOT_PATHS[path];\n if (hot) {\n return hot;\n }\n\n // Check cache\n const cached = parseCache.get(path);\n if (cached) {\n return cached;\n }\n\n const result = parseImpl(path);\n parseCache.set(path, result);\n return result;\n}\n\n/**\n * Internal implementation of path parsing.\n */\n// oxlint-disable-next-line complexity/complexity -- path grammar: one branch per optional path part\nfunction parseImpl(path: string): PathParts {\n if (!path || typeof path !== \"string\") {\n throw new Error(`Path must be a non-empty string, got: ${path}`);\n }\n\n const trimmed = path.trim();\n if (trimmed !== path) {\n throw new Error(`Path cannot contain leading/trailing spaces: \"${path}\"`);\n }\n\n const match = PATH_REGEX.exec(path);\n if (!match) {\n throw new Error(\n `Invalid HL7 path format: \"${path}\". Expected [GROUP[N]-]...NAME[N][-FIELD[REPETITION][.COMPONENT[.SUBCOMPONENT]]].`\n );\n }\n\n const [\n ,\n groupsRaw,\n segmentName,\n segmentRep,\n fieldStr,\n repetitionStr,\n componentStr,\n subcomponentStr,\n ] = match;\n\n if (!segmentName) {\n throw new Error(`Path must include a segment identifier: \"${path}\"`);\n }\n\n const parts: PathParts = {\n segment: { name: segmentName },\n };\n\n if (segmentRep) {\n const repetition = Number.parseInt(segmentRep, 10);\n if (repetition < 1) {\n throw new Error(\n `Segment repetition must be ≥1, got: ${segmentRep} in \"${path}\"`\n );\n }\n parts.segment.repetition = repetition;\n }\n\n if (groupsRaw) {\n const groups: GroupLocator[] = [];\n for (const groupMatch of groupsRaw.matchAll(\n /([A-Z][A-Z0-9]*)(?:\\[(\\d+)\\])?-/g\n )) {\n const name = groupMatch[1];\n if (!name) {\n continue;\n }\n\n const repStr = groupMatch[2];\n const group: GroupLocator = { name };\n if (repStr) {\n const repetition = Number.parseInt(repStr, 10);\n if (repetition < 1) {\n throw new Error(\n `Group repetition must be ≥1, got: ${repStr} in \"${path}\"`\n );\n }\n group.repetition = repetition;\n }\n groups.push(group);\n }\n if (groups.length > 0) {\n parts.groups = groups;\n }\n }\n\n if (fieldStr) {\n const field = Number.parseInt(fieldStr, 10);\n if (field < 1) {\n throw new Error(`Field number must be ≥1, got: ${fieldStr}`);\n }\n parts.field = field;\n }\n\n if (repetitionStr) {\n const repetition = Number.parseInt(repetitionStr, 10);\n if (repetition < 1) {\n throw new Error(`Repetition number must be ≥1, got: ${repetitionStr}`);\n }\n parts.repetition = repetition;\n }\n\n if (componentStr) {\n const component = Number.parseInt(componentStr, 10);\n if (component < 1) {\n throw new Error(`Component number must be ≥1, got: ${componentStr}`);\n }\n parts.component = component;\n }\n\n if (subcomponentStr) {\n const subcomponent = Number.parseInt(subcomponentStr, 10);\n if (subcomponent < 1) {\n throw new Error(\n `Subcomponent number must be ≥1, got: ${subcomponentStr}`\n );\n }\n parts.subcomponent = subcomponent;\n }\n\n return parts;\n}\n","// -------------\n// Internal Helpers\n// -------------\n\nimport type {\n Component,\n Field,\n FieldRepetition,\n Group,\n Nodes,\n Root,\n Segment,\n Subcomponent,\n} from \"@glion/ast\";\n\nimport type { GroupLocator, PathParts } from \"./types\";\n\nexport function locateSegmentOrGroup(\n root: Root,\n parts: PathParts\n): [Segment | Group, Nodes[]] | null {\n const ancestors: Nodes[] = [root];\n const scope = followGroups(root, parts.groups ?? [], ancestors);\n if (!scope) {\n return null;\n }\n\n const targetName = parts.segment.name;\n const targetRepetition = parts.segment.repetition;\n\n // Try to find a segment first\n const matchedSegments = collectSegments(scope, targetName, ancestors);\n if (matchedSegments.length > 0) {\n const index = (targetRepetition ?? 1) - 1;\n const match = matchedSegments[index];\n if (match) {\n return [match.segment, match.ancestors];\n }\n }\n\n // If no segment found, try to find a group\n const matchedGroups = collectGroups(scope, targetName, ancestors);\n if (matchedGroups.length > 0) {\n const index = (targetRepetition ?? 1) - 1;\n const match = matchedGroups[index];\n if (match) {\n return [match.group, match.ancestors];\n }\n }\n\n return null;\n}\n\nexport function locateSegment(\n root: Root,\n parts: PathParts\n): [Segment, Nodes[]] | null {\n const ancestors: Nodes[] = [root];\n const scope = followGroups(root, parts.groups ?? [], ancestors);\n if (!scope) {\n return null;\n }\n\n const matchedSegments = collectSegments(scope, parts.segment.name, ancestors);\n if (matchedSegments.length === 0) {\n return null;\n }\n\n const index = (parts.segment.repetition ?? 1) - 1;\n const match = matchedSegments[index];\n if (!match) {\n return null;\n }\n\n return [match.segment, match.ancestors];\n}\n\nexport function followGroups(\n root: Root,\n groups: GroupLocator[],\n ancestorChain: Nodes[]\n): Array<Segment | Group> | null {\n let children = filterSegmentsAndGroups(root.children);\n\n for (const locator of groups) {\n const matchedGroups = children.filter(\n (node): node is Group =>\n node.type === \"group\" && node.name === locator.name\n );\n\n if (matchedGroups.length === 0) {\n return null;\n }\n\n const index = (locator.repetition ?? 1) - 1;\n const selected = matchedGroups[index];\n if (!selected) {\n return null;\n }\n\n ancestorChain.push(selected);\n children = filterSegmentsAndGroups(selected.children);\n }\n\n return children;\n}\n\n/**\n * Collect all possible scopes when groups can match multiple instances.\n * Used by selectAll to find nodes across all matching groups.\n */\nexport function collectAllScopes(\n root: Root,\n groups: GroupLocator[]\n): { scope: (Segment | Group)[]; ancestors: Nodes[] }[] {\n if (groups.length === 0) {\n return [\n { ancestors: [root], scope: filterSegmentsAndGroups(root.children) },\n ];\n }\n\n const results: { scope: (Segment | Group)[]; ancestors: Nodes[] }[] = [];\n const firstLocator = groups[0];\n const remainingGroups = groups.slice(1);\n\n if (!firstLocator) {\n return [\n { ancestors: [root], scope: filterSegmentsAndGroups(root.children) },\n ];\n }\n\n const children = filterSegmentsAndGroups(root.children);\n const matchingGroups = children.filter(\n (node): node is Group =>\n node.type === \"group\" && node.name === firstLocator.name\n );\n\n // If a specific repetition is requested, only follow that one\n if (firstLocator.repetition !== undefined) {\n const index = firstLocator.repetition - 1;\n const selected = matchingGroups[index];\n if (!selected) {\n return [];\n }\n const ancestors = [root, selected];\n return collectAllScopesRecursive(\n selected.children,\n remainingGroups,\n ancestors\n );\n }\n\n // Otherwise, follow ALL matching groups\n for (const group of matchingGroups) {\n const ancestors = [root, group];\n const subScopes = collectAllScopesRecursive(\n group.children,\n remainingGroups,\n ancestors\n );\n results.push(...subScopes);\n }\n\n return results;\n}\n\nexport function collectAllScopesRecursive(\n children: Nodes[],\n groups: GroupLocator[],\n ancestors: Nodes[]\n): { scope: (Segment | Group)[]; ancestors: Nodes[] }[] {\n if (groups.length === 0) {\n return [{ ancestors, scope: filterSegmentsAndGroups(children) }];\n }\n\n const results: { scope: (Segment | Group)[]; ancestors: Nodes[] }[] = [];\n const firstLocator = groups[0];\n const remainingGroups = groups.slice(1);\n\n if (!firstLocator) {\n return [{ ancestors, scope: filterSegmentsAndGroups(children) }];\n }\n\n const filteredChildren = filterSegmentsAndGroups(children);\n const matchingGroups = filteredChildren.filter(\n (node): node is Group =>\n node.type === \"group\" && node.name === firstLocator.name\n );\n\n // If a specific repetition is requested, only follow that one\n if (firstLocator.repetition !== undefined) {\n const index = firstLocator.repetition - 1;\n const selected = matchingGroups[index];\n if (!selected) {\n return [];\n }\n const newAncestors = [...ancestors, selected];\n return collectAllScopesRecursive(\n selected.children,\n remainingGroups,\n newAncestors\n );\n }\n\n // Otherwise, follow ALL matching groups\n for (const group of matchingGroups) {\n const newAncestors = [...ancestors, group];\n const subScopes = collectAllScopesRecursive(\n group.children,\n remainingGroups,\n newAncestors\n );\n results.push(...subScopes);\n }\n\n return results;\n}\n\nexport function collectSegments(\n nodes: (Segment | Group)[],\n targetSegmentName: string,\n ancestors: Nodes[]\n): { segment: Segment; ancestors: Nodes[] }[] {\n const result: { segment: Segment; ancestors: Nodes[] }[] = [];\n\n for (const node of nodes) {\n if (node.type === \"segment\") {\n const name = getSegmentName(node);\n if (name === targetSegmentName) {\n result.push({ ancestors: [...ancestors], segment: node });\n }\n }\n\n if (node.type === \"group\") {\n const nextAncestors = [...ancestors, node];\n result.push(\n ...collectSegments(\n filterSegmentsAndGroups(node.children),\n targetSegmentName,\n nextAncestors\n )\n );\n }\n }\n\n return result;\n}\n\nexport function collectGroups(\n nodes: (Segment | Group)[],\n targetGroupName: string,\n ancestors: Nodes[]\n): { group: Group; ancestors: Nodes[] }[] {\n const result: { group: Group; ancestors: Nodes[] }[] = [];\n\n for (const node of nodes) {\n if (node.type === \"group\" && node.name === targetGroupName) {\n result.push({ ancestors: [...ancestors], group: node });\n }\n\n if (node.type === \"group\") {\n const nextAncestors = [...ancestors, node];\n result.push(\n ...collectGroups(\n filterSegmentsAndGroups(node.children),\n targetGroupName,\n nextAncestors\n )\n );\n }\n }\n\n return result;\n}\n\nexport function locateField(\n segment: Segment,\n fieldNum: number,\n parentAncestors: Nodes[]\n): [Field, Nodes[]] | null {\n const fields = getFields(segment);\n const field = fields[fieldNum - 1];\n if (!field) {\n return null;\n }\n\n return [field, [...parentAncestors, segment]];\n}\n\nexport function locateRepetition(\n field: Field,\n repetition: number,\n parentAncestors: Nodes[]\n): [FieldRepetition, Nodes[]] | null {\n if (repetition < 1) {\n return null;\n }\n\n const node = field.children?.[repetition - 1];\n if (!node) {\n return null;\n }\n\n return [node as FieldRepetition, [...parentAncestors, field]];\n}\n\nexport function locateComponent(\n repetition: FieldRepetition,\n componentNum: number,\n parentAncestors: Nodes[]\n): [Component, Nodes[]] | null {\n if (componentNum < 1) {\n return null;\n }\n\n const component = repetition.children?.[componentNum - 1];\n if (!component) {\n return null;\n }\n\n return [component as Component, [...parentAncestors, repetition]];\n}\n\nexport function locateSubcomponent(\n component: Component,\n subcomponentNum: number,\n parentAncestors: Nodes[]\n): [Subcomponent, Nodes[]] | null {\n if (subcomponentNum < 1) {\n return null;\n }\n\n const node = component.children?.[subcomponentNum - 1];\n if (!node) {\n return null;\n }\n\n return [node as Subcomponent, [...parentAncestors, component]];\n}\n\nexport function getSegmentName(segment: Segment): string {\n return segment.name;\n}\n\nexport function getFields(segment: Segment): Field[] {\n return segment.children;\n}\n\nexport function filterSegmentsAndGroups(nodes: Nodes[]): (Segment | Group)[] {\n return nodes.filter(\n (node): node is Segment | Group =>\n node.type === \"segment\" || node.type === \"group\"\n );\n}\n","import type { Group, Nodes, Root, Segment } from \"@glion/ast\";\n\nimport { parse } from \"./parse\";\nimport type { InferNodeType } from \"./types\";\nimport {\n collectAllScopes,\n collectGroups,\n collectSegments,\n locateComponent,\n locateField,\n locateRepetition,\n locateSegment,\n locateSegmentOrGroup,\n locateSubcomponent,\n} from \"./utils\";\n\n/**\n * Select the first node at the given path and return it with its ancestor\n * chain.\n *\n * This function finds the first matching node for the given path. For paths\n * that can match multiple nodes (e.g., \"PID\" when multiple PID segments exist),\n * use {@link selectAll} to retrieve all matches.\n *\n * @example\n * ```typescript\n * const result = select(root, \"PID-5\");\n * if (result) {\n * result.node; // Type: Field\n * result.ancestors; // [Root, Segment]\n * }\n * ```;\n *\n * @param root - The root node to search from\n * @param path - The HL7 path string\n * @returns Object containing the node and its ancestors, or null if not found\n */\nexport function select<Path extends string>(\n root: Root,\n path: Path\n): { node: InferNodeType<Path>; ancestors: Nodes[] } | null {\n const parts = parse(path);\n\n // If no field access, we might be selecting a segment OR a group\n if (parts.field === undefined) {\n const result = locateSegmentOrGroup(root, parts);\n if (!result) {\n return null;\n }\n return {\n ancestors: result[1],\n node: result[0] as unknown as InferNodeType<Path>,\n };\n }\n\n // Field access means we're definitely accessing a segment\n const segmentResult = locateSegment(root, parts);\n if (!segmentResult) {\n return null;\n }\n const [segment, segmentAncestors] = segmentResult;\n\n const fieldResult = locateField(segment, parts.field, segmentAncestors);\n if (!fieldResult) {\n return null;\n }\n const [field, fieldAncestors] = fieldResult;\n\n if (\n parts.component === undefined &&\n parts.subcomponent === undefined &&\n parts.repetition === undefined\n ) {\n return {\n ancestors: fieldAncestors,\n node: field as unknown as InferNodeType<Path>,\n };\n }\n\n const repetitionResult = locateRepetition(\n field,\n parts.repetition ?? 1,\n fieldAncestors\n );\n if (!repetitionResult) {\n return null;\n }\n const [repetitionNode, repetitionAncestors] = repetitionResult;\n\n if (parts.component === undefined) {\n return {\n ancestors: repetitionAncestors,\n node: repetitionNode as unknown as InferNodeType<Path>,\n };\n }\n\n const componentResult = locateComponent(\n repetitionNode,\n parts.component,\n repetitionAncestors\n );\n if (!componentResult) {\n return null;\n }\n const [componentNode, componentAncestors] = componentResult;\n\n if (parts.subcomponent === undefined) {\n return {\n ancestors: componentAncestors,\n node: componentNode as unknown as InferNodeType<Path>,\n };\n }\n\n const subResult = locateSubcomponent(\n componentNode,\n parts.subcomponent,\n componentAncestors\n );\n if (!subResult) {\n return null;\n }\n\n return {\n ancestors: subResult[1],\n node: subResult[0] as unknown as InferNodeType<Path>,\n };\n}\n\n/**\n * Select all nodes that match the given path.\n *\n * This function returns all matching nodes for paths that can match multiple\n * elements. For example, \"PID\" will return all PID segments in the message, and\n * \"OBX-5\" will return all observation values.\n *\n * @example\n * ```typescript\n * // Get all OBX segments\n * const results = selectAll(root, \"OBX\");\n * for (const { node } of results) {\n * console.log(node.type); // 'segment'\n * }\n *\n * // Get all patient name fields\n * const names = selectAll(root, \"PID-5\");\n * ```;\n *\n * @param root - The root node to search from\n * @param path - The HL7 path string (must not include repetition index)\n * @returns Array of objects containing nodes and their ancestor chains\n */\n// oxlint-disable-next-line complexity/complexity -- path walker: one branch per scope level (group, segment, field, component, subcomponent)\nexport function selectAll<Path extends string>(\n root: Root,\n path: Path\n): { node: InferNodeType<Path>; ancestors: Nodes[] }[] {\n const parts = parse(path);\n\n // If path includes a specific repetition, delegate to select()\n if (\n parts.segment.repetition !== undefined ||\n parts.repetition !== undefined\n ) {\n const result = select(root, path);\n return result ? [result] : [];\n }\n\n const results: { node: InferNodeType<Path>; ancestors: Nodes[] }[] = [];\n\n // Get all matching segments from all possible scopes\n const scopes = collectAllScopes(root, parts.groups ?? []);\n const segments: { segment: Segment; ancestors: Nodes[] }[] = [];\n const includeGroups = parts.field === undefined;\n const groups: { group: Group; ancestors: Nodes[] }[] = [];\n\n for (const { scope, ancestors } of scopes) {\n const matchingSegments = collectSegments(\n scope,\n parts.segment.name,\n ancestors\n );\n segments.push(...matchingSegments);\n\n if (includeGroups) {\n const matchingGroups = collectGroups(\n scope,\n parts.segment.name,\n ancestors\n );\n for (const { group, ancestors: groupAncestors } of matchingGroups) {\n groups.push({ ancestors: groupAncestors, group });\n }\n }\n }\n\n // If path is segment-only, return all matching segments and groups\n if (parts.field === undefined) {\n for (const { segment, ancestors } of segments) {\n results.push({\n ancestors,\n node: segment as InferNodeType<Path>,\n });\n }\n\n for (const { group, ancestors } of groups) {\n results.push({\n ancestors,\n node: group as InferNodeType<Path>,\n });\n }\n return results;\n }\n\n // For each segment, try to get the field/component/subcomponent\n for (const { segment, ancestors: segmentAncestors } of segments) {\n const fieldResult = locateField(segment, parts.field, segmentAncestors);\n if (!fieldResult) {\n continue;\n }\n const [field, fieldAncestors] = fieldResult;\n\n if (\n parts.component === undefined &&\n parts.subcomponent === undefined &&\n parts.repetition === undefined\n ) {\n results.push({\n ancestors: fieldAncestors,\n node: field as unknown as InferNodeType<Path>,\n });\n continue;\n }\n\n // For field repetitions, components, and subcomponents,\n // we need to iterate through all repetitions\n if (!field.children) {\n continue;\n }\n\n for (const repetitionNode of field.children) {\n const repetitionAncestors = [...fieldAncestors, field];\n\n if (parts.component === undefined) {\n results.push({\n ancestors: repetitionAncestors,\n node: repetitionNode as unknown as InferNodeType<Path>,\n });\n continue;\n }\n\n const componentResult = locateComponent(\n repetitionNode,\n parts.component,\n repetitionAncestors\n );\n if (!componentResult) {\n continue;\n }\n const [componentNode, componentAncestors] = componentResult;\n\n if (parts.subcomponent === undefined) {\n results.push({\n ancestors: componentAncestors,\n node: componentNode as unknown as InferNodeType<Path>,\n });\n continue;\n }\n\n const subResult = locateSubcomponent(\n componentNode,\n parts.subcomponent,\n componentAncestors\n );\n if (subResult) {\n results.push({\n ancestors: subResult[1],\n node: subResult[0] as unknown as InferNodeType<Path>,\n });\n }\n }\n }\n\n return results;\n}\n","import type { Nodes, Root } from \"@glion/ast\";\n\nimport { select } from \"./select\";\n\n/**\n * Get the string value at the path, drilling down through single-child nodes\n * when needed. Also returns the node and ancestor chain for context.\n *\n * This is a convenience function that automatically traverses through container\n * nodes (Field → FieldRepetition → Component → Subcomponent) to extract the\n * primary string value. When a container has multiple children, the first child\n * is selected (e.g., `value(tree, \"MSH-12\")` returns the first component of a\n * composite VID field).\n *\n * Nodes with no children return `value: null` to differentiate between empty\n * strings (\"\") and missing values.\n *\n * @example\n * ```typescript\n * const result = value(root, \"PID-5.1\");\n * if (result) {\n * console.log(result.value); // string | null\n * console.log(result.node.type); // 'subcomponent'\n * console.log(result.ancestors); // [Root, Segment, Field, ...]\n * }\n * ```;\n *\n * @param root - The root node to search from\n * @param path - The HL7 path string\n * @returns Object containing the value, node, and ancestors, or null if not\n * found\n */\nexport function value(\n root: Root,\n path: string\n): { value: string | null; node: Nodes; ancestors: Nodes[] } | null {\n const selectResult = select(root, path);\n if (!selectResult) {\n return null;\n }\n\n let { node } = selectResult;\n let { ancestors } = selectResult;\n\n // Drill down through single children until we reach a subcomponent\n while (node.type !== \"subcomponent\") {\n // Segments and groups can't be drilled down\n if (\n node.type === \"segment\" ||\n node.type === \"group\" ||\n node.type === \"root\"\n ) {\n return null;\n }\n\n // Type guard: at this point, node must be Field | FieldRepetition | Component\n if (!(\"children\" in node && node.children)) {\n return null;\n }\n\n if (node.children.length === 0) {\n return {\n ancestors: [...ancestors],\n node,\n value: null,\n };\n }\n\n const next = node.children[0];\n if (!next) {\n return null;\n }\n\n ancestors = [...ancestors, node];\n node = next;\n }\n\n // At this point, node.type === \"subcomponent\" is guaranteed\n return {\n ancestors,\n node,\n value: node.value,\n };\n}\n","import type { Delimiters, Root } from \"@glion/ast\";\nimport { DEFAULT_DELIMITERS } from \"@glion/utils\";\n\nimport { value } from \"./value\";\n\n/** Keys of MSH-2 encoding characters in positional order. */\nconst MSH2_KEYS = [\n \"component\",\n \"repetition\",\n \"escape\",\n \"subcomponent\",\n] as const;\n\n/**\n * Extract delimiters from a Root AST by reading MSH-1 and MSH-2.\n *\n * MSH-1 contains the field separator character (e.g., `|`).\n * MSH-2 contains up to 4 encoding characters: component, repetition,\n * escape, and subcomponent (e.g., `^~\\&`).\n *\n * Falls back to DEFAULT_DELIMITERS for any values that cannot be derived.\n *\n * @param root - The Root AST node to extract delimiters from.\n * @returns The resolved Delimiters object.\n */\nexport function delimiters(root: Root): Delimiters {\n const result = { ...DEFAULT_DELIMITERS };\n\n // MSH-1: field separator (single character)\n const msh1 = value(root, \"MSH-1\")?.value;\n if (msh1 && msh1.length === 1) {\n result.field = msh1;\n }\n\n // MSH-2: encoding characters (up to 4 positional chars)\n const msh2 = value(root, \"MSH-2\")?.value;\n if (msh2) {\n const chars = [...msh2];\n for (const [i, key] of MSH2_KEYS.entries()) {\n const ch = chars[i];\n if (ch) {\n result[key] = ch;\n }\n }\n }\n\n return result;\n}\n","import type { Nodes } from \"@glion/ast\";\n\n/**\n * Format a node and its ancestor chain into a canonical HL7v2 path string.\n *\n * This is the inverse of `select`: given a node and the ancestors\n * returned by `visit` or `select`, it produces the path string that\n * would select that node.\n *\n * @example\n * ```typescript\n * visit(tree, \"field\", (node, ancestors) => {\n * format(node, ancestors); // \"PID-5\"\n * });\n *\n * const result = select(root, \"PID-5.2\");\n * format(result.node, result.ancestors); // \"PID-5.2\"\n * ```;\n *\n * @param node - The target AST node\n * @param ancestors - Ancestor chain from root to parent (as provided by\n * visit/select)\n * @returns Canonical path string (e.g., \"PID-5.2\", \"ORDER-ORC-1\"), or `null` if the\n * ancestor chain contains no segment or group\n */\n// oxlint-disable-next-line complexity\nexport function format(node: Nodes, ancestors: Nodes[]): string | null {\n let result: string | null = null;\n const chain = [...ancestors, node];\n\n for (const [i, current] of chain.entries()) {\n const parent = chain[i - 1];\n\n switch (current.type) {\n case \"root\": {\n break;\n }\n\n case \"group\":\n case \"segment\": {\n const pos = positionOf(current, parent);\n result = (result ?? \"\") + current.name;\n if (pos > 1) {\n result += `[${pos}]`;\n }\n if (current.type === \"group\" && current !== node) {\n result += \"-\";\n }\n break;\n }\n\n case \"field\": {\n result += `-${positionOf(current, parent)}`;\n break;\n }\n\n case \"field-repetition\": {\n const pos = positionOf(current, parent);\n if (pos > 1 || current === node) {\n result += `[${pos}]`;\n }\n break;\n }\n\n case \"component\": {\n result += `.${positionOf(current, parent)}`;\n break;\n }\n\n case \"subcomponent\": {\n result += `.${positionOf(current, parent)}`;\n break;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Compute the 1-based position of a node among its parent's children.\n *\n * For named nodes (segments, groups), counts only same-name siblings\n * because segments are identified by name: the 2nd PID in [MSH, PID, OBX, PID]\n * is PID[2], not PID[4].\n *\n * For positional nodes (fields, repetitions, components, subcomponents),\n * uses the array index directly.\n */\nfunction positionOf(node: Nodes, parent: Nodes | undefined): number {\n if (!parent || !(\"children\" in parent)) {\n return 1;\n }\n\n const children = parent.children as Nodes[];\n\n // Named nodes: count same-name siblings before this node\n if (\"name\" in node) {\n const name = node.name as string;\n const { type } = node;\n let count = 0;\n for (const child of children) {\n if (child === node) {\n return count + 1;\n }\n if (child.type === type && \"name\" in child && child.name === name) {\n count++;\n }\n }\n throw new Error(\"format(): node not found in parent's children array\");\n }\n\n // Positional nodes: use array index\n const idx = children.indexOf(node);\n if (idx === -1) {\n throw new Error(\"format(): node not found in parent's children array\");\n }\n return idx + 1;\n}\n","import type { Root } from \"@glion/ast\";\n\nimport { select } from \"./select\";\n\n/**\n * Check if a node exists at the given path.\n *\n * This is a convenience function equivalent to `select(root, path) !== null`,\n * but more semantically clear for existence checks.\n *\n * @example\n * ```typescript\n * if (matches(root, \"PID-5\")) {\n * console.log(\"Patient has a name field\");\n * }\n *\n * if (!matches(root, \"OBX-5\")) {\n * throw new Error(\"Missing observation value\");\n * }\n * ```;\n *\n * @param root - The root node to search from\n * @param path - The HL7 path string\n * @returns True if the path resolves to a node, false otherwise\n */\nexport function matches(root: Root, path: string): boolean {\n return select(root, path) !== null;\n}\n","import type {\n Component,\n Field,\n FieldRepetition,\n Root,\n Subcomponent,\n} from \"@glion/ast\";\n\nimport { parse } from \"./parse\";\nimport { locateSegment } from \"./utils\";\n\n/**\n * Set a string value at the given HL7 path, creating all missing intermediate\n * nodes as needed (fields, repetitions, components, subcomponents).\n *\n * This is the write counterpart to {@link value}. It handles the full HL7v2\n * path syntax including group navigation and segment repetitions.\n *\n * Padding nodes are created with empty children arrays — they represent\n * structurally absent nodes, not empty values. Only the target node gets\n * a fully populated chain down to the subcomponent.\n *\n * @example\n * ```typescript\n * // Update existing value\n * set(tree, \"MSH-12\", \"2.7.1\");\n *\n * // Create missing MSH-9.3 (fills gaps with empty components)\n * set(tree, \"MSH-9.3\", \"ADT_A01\");\n *\n * // Set a specific repetition\n * set(tree, \"PID-3[2]\", \"ID-002\");\n *\n * // Set a subcomponent\n * set(tree, \"PID-5.1.2\", \"suffix\");\n * ```;\n *\n * @param root - The root node to modify\n * @param path - The HL7 path string (must include at least a field)\n * @param val - The string value to set\n * @throws When the path has no field specifier (segment-only paths)\n * @throws When the target segment does not exist in the tree\n */\nexport function set(root: Root, path: string, val: string): void {\n const parts = parse(path);\n\n if (parts.field === undefined) {\n throw new Error(`Cannot set value on segment-only path: \"${path}\"`);\n }\n\n // Use locateSegment for full path support (groups, segment repetitions)\n const segmentResult = locateSegment(root, parts);\n if (!segmentResult) {\n throw new Error(`Segment \"${parts.segment.name}\" not found in tree`);\n }\n const [segment] = segmentResult;\n\n // Ensure fields exist up to the target index\n const fieldIndex = parts.field - 1;\n padArray(segment.children, fieldIndex + 1, stubField);\n\n const field = segment.children[fieldIndex]!;\n\n // Ensure repetitions exist up to the target index\n const repIndex = (parts.repetition ?? 1) - 1;\n padArray(field.children, repIndex + 1, stubRepetition);\n\n const repetition = field.children[repIndex]!;\n\n // Ensure components exist up to the target index\n const compIndex = (parts.component ?? 1) - 1;\n padArray(repetition.children, compIndex + 1, stubComponent);\n\n const component = repetition.children[compIndex]!;\n\n // Ensure subcomponents exist up to the target index\n const subIndex = (parts.subcomponent ?? 1) - 1;\n padArray(component.children, subIndex + 1, stubSubcomponent);\n\n // Set the value\n component.children[subIndex]!.value = val;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Pad an array to a target length using a factory function.\n */\nfunction padArray<T>(arr: T[], targetLength: number, factory: () => T): void {\n while (arr.length < targetLength) {\n arr.push(factory());\n }\n}\n\n/**\n * Stub nodes for padding — created with empty children arrays to represent\n * structurally absent nodes. These are distinguishable from nodes with empty\n * values (which have a subcomponent with value \"\").\n */\n\nfunction stubField(): Field {\n return { children: [], type: \"field\" } as Field;\n}\n\nfunction stubRepetition(): FieldRepetition {\n return { children: [], type: \"field-repetition\" } as FieldRepetition;\n}\n\nfunction stubComponent(): Component {\n return { children: [], type: \"component\" } as Component;\n}\n\nfunction stubSubcomponent(): Subcomponent {\n return { type: \"subcomponent\", value: \"\" } as Subcomponent;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/parse.ts","../src/utils.ts","../src/select.ts","../src/value.ts","../src/delimiters.ts","../src/format.ts","../src/matches.ts","../src/set.ts"],"sourcesContent":["import type { GroupLocator, PathParts } from \"./types\";\n\n/**\n * Regular expression for canonical HL7 paths.\n *\n * Format:\n * [GROUP[N]-]...[GROUP[N]-]NAME[N][-FIELD[REPETITION][.COMPONENT[.SUBCOMPONENT]]]\n *\n * **Design Philosophy**: Groups vs Segments are distinguished by POSITION and\n * USAGE, not name length:\n *\n * - **Navigation (Groups)**: Names appearing as prefixes (before the final name)\n * are treated as group navigation: `ORDER-ORC`, `ORDER-TIMING-TQ1`\n * - **Target (Segments)**: The final name in the path is the query target.\n * Whether it's a segment or group is determined by:\n *\n * 1. Field access (-.digit): Definitively a segment → `ORC-1`, `ORDER-ORC-1`\n * 2. No field access: Query the AST to see what exists → `ORC`, `ORDER`\n *\n * This approach:\n *\n * - Makes no assumptions about name length (works with standard 3-char segments\n * AND edge cases)\n * - Lets the path structure indicate intent (field access = segment internals)\n * - Allows the AST to be the source of truth for what exists\n *\n * Examples:\n *\n * - `MSH-3` → MSH is segment (has field access)\n * - `ORDER-ORC` → ORDER is navigation, ORC is target (could be segment or nested\n * group)\n * - `ORDER-ORC-1` → ORDER is navigation, ORC is segment (has field access)\n */\nconst PATH_REGEX =\n /^((?:[A-Z][A-Z0-9_]*(?:\\[\\d+\\])?-)*)([A-Z][A-Z0-9_]*)(?:\\[(\\d+)\\])?(?:-(\\d+)(?:(?:\\[(\\d+)\\])?(?:\\.(\\d+)(?:\\.(\\d+))?)?)?)?$/;\n\n/**\n * Cache for parsed paths to avoid re-parsing the same path multiple times.\n * No eviction — the realistic set of unique paths in an application is\n * small (50-100 entries) and the memory cost is negligible.\n */\nconst parseCache = new Map<string, PathParts>();\n\nexport function clearParseCache(): void {\n parseCache.clear();\n}\n\nexport function getParseCacheSize(): number {\n return parseCache.size;\n}\n\n/**\n * Pre-computed PathParts for frequently accessed MSH fields.\n *\n * Multiple plugins and lint rules read MSH-9 (message type) and MSH-12\n * (version) on every message. Skipping regex parsing and cache lookups\n * for these paths eliminates ~100ns per call.\n */\nconst HOT_PATHS: Record<string, PathParts> = {\n \"MSH-10\": { field: 10, segment: { name: \"MSH\" } },\n \"MSH-12\": { field: 12, segment: { name: \"MSH\" } },\n \"MSH-3\": { field: 3, segment: { name: \"MSH\" } },\n \"MSH-4\": { field: 4, segment: { name: \"MSH\" } },\n \"MSH-5\": { field: 5, segment: { name: \"MSH\" } },\n \"MSH-6\": { field: 6, segment: { name: \"MSH\" } },\n \"MSH-9\": { field: 9, segment: { name: \"MSH\" } },\n \"MSH-9.1\": { component: 1, field: 9, segment: { name: \"MSH\" } },\n \"MSH-9.2\": { component: 2, field: 9, segment: { name: \"MSH\" } },\n \"MSH-9.3\": { component: 3, field: 9, segment: { name: \"MSH\" } },\n};\n\n/**\n * Parse an HL7 path string into structured parts.\n * Results are memoized for performance. Common MSH paths use\n * pre-computed constants to skip parsing entirely.\n *\n * @example\n * ```typescript\n * parse(\"PID-5[1].2.1\");\n * // {\n * // segment: { name: 'PID' },\n * // field: 5,\n * // repetition: 1,\n * // component: 2,\n * // subcomponent: 1\n * // }\n * ```;\n *\n * @param path - HL7 path string to parse\n * @returns Structured path components\n */\nexport function parse(path: string): PathParts {\n // Hot path: pre-computed results for common MSH field reads\n const hot = HOT_PATHS[path];\n if (hot) {\n return hot;\n }\n\n // Check cache\n const cached = parseCache.get(path);\n if (cached) {\n return cached;\n }\n\n const result = parseImpl(path);\n parseCache.set(path, result);\n return result;\n}\n\n/**\n * Internal implementation of path parsing.\n */\n// oxlint-disable-next-line complexity/complexity -- path grammar: one branch per optional path part\nfunction parseImpl(path: string): PathParts {\n if (!path || typeof path !== \"string\") {\n throw new Error(`Path must be a non-empty string, got: ${path}`);\n }\n\n const trimmed = path.trim();\n if (trimmed !== path) {\n throw new Error(`Path cannot contain leading/trailing spaces: \"${path}\"`);\n }\n\n const match = PATH_REGEX.exec(path);\n if (!match) {\n throw new Error(\n `Invalid HL7 path format: \"${path}\". Expected [GROUP[N]-]...NAME[N][-FIELD[REPETITION][.COMPONENT[.SUBCOMPONENT]]].`\n );\n }\n\n const [\n ,\n groupsRaw,\n segmentName,\n segmentRep,\n fieldStr,\n repetitionStr,\n componentStr,\n subcomponentStr,\n ] = match;\n\n if (!segmentName) {\n throw new Error(`Path must include a segment identifier: \"${path}\"`);\n }\n\n const parts: PathParts = {\n segment: { name: segmentName },\n };\n\n if (segmentRep) {\n const repetition = Number.parseInt(segmentRep, 10);\n if (repetition < 1) {\n throw new Error(\n `Segment repetition must be ≥1, got: ${segmentRep} in \"${path}\"`\n );\n }\n parts.segment.repetition = repetition;\n }\n\n if (groupsRaw) {\n const groups: GroupLocator[] = [];\n for (const groupMatch of groupsRaw.matchAll(\n /([A-Z][A-Z0-9_]*)(?:\\[(\\d+)\\])?-/g\n )) {\n const name = groupMatch[1];\n if (!name) {\n continue;\n }\n\n const repStr = groupMatch[2];\n const group: GroupLocator = { name };\n if (repStr) {\n const repetition = Number.parseInt(repStr, 10);\n if (repetition < 1) {\n throw new Error(\n `Group repetition must be ≥1, got: ${repStr} in \"${path}\"`\n );\n }\n group.repetition = repetition;\n }\n groups.push(group);\n }\n if (groups.length > 0) {\n parts.groups = groups;\n }\n }\n\n if (fieldStr) {\n const field = Number.parseInt(fieldStr, 10);\n if (field < 1) {\n throw new Error(`Field number must be ≥1, got: ${fieldStr}`);\n }\n parts.field = field;\n }\n\n if (repetitionStr) {\n const repetition = Number.parseInt(repetitionStr, 10);\n if (repetition < 1) {\n throw new Error(`Repetition number must be ≥1, got: ${repetitionStr}`);\n }\n parts.repetition = repetition;\n }\n\n if (componentStr) {\n const component = Number.parseInt(componentStr, 10);\n if (component < 1) {\n throw new Error(`Component number must be ≥1, got: ${componentStr}`);\n }\n parts.component = component;\n }\n\n if (subcomponentStr) {\n const subcomponent = Number.parseInt(subcomponentStr, 10);\n if (subcomponent < 1) {\n throw new Error(\n `Subcomponent number must be ≥1, got: ${subcomponentStr}`\n );\n }\n parts.subcomponent = subcomponent;\n }\n\n return parts;\n}\n","// -------------\n// Internal Helpers\n// -------------\n\nimport type {\n Component,\n Field,\n FieldRepetition,\n Group,\n Nodes,\n Root,\n Segment,\n Subcomponent,\n} from \"@glion/ast\";\n\nimport type { GroupLocator, PathParts } from \"./types\";\n\nexport function locateSegmentOrGroup(\n root: Root,\n parts: PathParts\n): [Segment | Group, Nodes[]] | null {\n const ancestors: Nodes[] = [root];\n const scope = followGroups(root, parts.groups ?? [], ancestors);\n if (!scope) {\n return null;\n }\n\n const targetName = parts.segment.name;\n const targetRepetition = parts.segment.repetition;\n\n // Try to find a segment first\n const matchedSegments = collectSegments(scope, targetName, ancestors);\n if (matchedSegments.length > 0) {\n const index = (targetRepetition ?? 1) - 1;\n const match = matchedSegments[index];\n if (match) {\n return [match.segment, match.ancestors];\n }\n }\n\n // If no segment found, try to find a group\n const matchedGroups = collectGroups(scope, targetName, ancestors);\n if (matchedGroups.length > 0) {\n const index = (targetRepetition ?? 1) - 1;\n const match = matchedGroups[index];\n if (match) {\n return [match.group, match.ancestors];\n }\n }\n\n return null;\n}\n\nexport function locateSegment(\n root: Root,\n parts: PathParts\n): [Segment, Nodes[]] | null {\n const ancestors: Nodes[] = [root];\n const scope = followGroups(root, parts.groups ?? [], ancestors);\n if (!scope) {\n return null;\n }\n\n const matchedSegments = collectSegments(scope, parts.segment.name, ancestors);\n if (matchedSegments.length === 0) {\n return null;\n }\n\n const index = (parts.segment.repetition ?? 1) - 1;\n const match = matchedSegments[index];\n if (!match) {\n return null;\n }\n\n return [match.segment, match.ancestors];\n}\n\nexport function followGroups(\n root: Root,\n groups: GroupLocator[],\n ancestorChain: Nodes[]\n): Array<Segment | Group> | null {\n let children = filterSegmentsAndGroups(root.children);\n\n for (const locator of groups) {\n const matchedGroups = children.filter(\n (node): node is Group =>\n node.type === \"group\" && node.name === locator.name\n );\n\n if (matchedGroups.length === 0) {\n return null;\n }\n\n const index = (locator.repetition ?? 1) - 1;\n const selected = matchedGroups[index];\n if (!selected) {\n return null;\n }\n\n ancestorChain.push(selected);\n children = filterSegmentsAndGroups(selected.children);\n }\n\n return children;\n}\n\n/**\n * Collect all possible scopes when groups can match multiple instances.\n * Used by selectAll to find nodes across all matching groups.\n */\nexport function collectAllScopes(\n root: Root,\n groups: GroupLocator[]\n): { scope: (Segment | Group)[]; ancestors: Nodes[] }[] {\n if (groups.length === 0) {\n return [\n { ancestors: [root], scope: filterSegmentsAndGroups(root.children) },\n ];\n }\n\n const results: { scope: (Segment | Group)[]; ancestors: Nodes[] }[] = [];\n const firstLocator = groups[0];\n const remainingGroups = groups.slice(1);\n\n if (!firstLocator) {\n return [\n { ancestors: [root], scope: filterSegmentsAndGroups(root.children) },\n ];\n }\n\n const children = filterSegmentsAndGroups(root.children);\n const matchingGroups = children.filter(\n (node): node is Group =>\n node.type === \"group\" && node.name === firstLocator.name\n );\n\n // If a specific repetition is requested, only follow that one\n if (firstLocator.repetition !== undefined) {\n const index = firstLocator.repetition - 1;\n const selected = matchingGroups[index];\n if (!selected) {\n return [];\n }\n const ancestors = [root, selected];\n return collectAllScopesRecursive(\n selected.children,\n remainingGroups,\n ancestors\n );\n }\n\n // Otherwise, follow ALL matching groups\n for (const group of matchingGroups) {\n const ancestors = [root, group];\n const subScopes = collectAllScopesRecursive(\n group.children,\n remainingGroups,\n ancestors\n );\n results.push(...subScopes);\n }\n\n return results;\n}\n\nexport function collectAllScopesRecursive(\n children: Nodes[],\n groups: GroupLocator[],\n ancestors: Nodes[]\n): { scope: (Segment | Group)[]; ancestors: Nodes[] }[] {\n if (groups.length === 0) {\n return [{ ancestors, scope: filterSegmentsAndGroups(children) }];\n }\n\n const results: { scope: (Segment | Group)[]; ancestors: Nodes[] }[] = [];\n const firstLocator = groups[0];\n const remainingGroups = groups.slice(1);\n\n if (!firstLocator) {\n return [{ ancestors, scope: filterSegmentsAndGroups(children) }];\n }\n\n const filteredChildren = filterSegmentsAndGroups(children);\n const matchingGroups = filteredChildren.filter(\n (node): node is Group =>\n node.type === \"group\" && node.name === firstLocator.name\n );\n\n // If a specific repetition is requested, only follow that one\n if (firstLocator.repetition !== undefined) {\n const index = firstLocator.repetition - 1;\n const selected = matchingGroups[index];\n if (!selected) {\n return [];\n }\n const newAncestors = [...ancestors, selected];\n return collectAllScopesRecursive(\n selected.children,\n remainingGroups,\n newAncestors\n );\n }\n\n // Otherwise, follow ALL matching groups\n for (const group of matchingGroups) {\n const newAncestors = [...ancestors, group];\n const subScopes = collectAllScopesRecursive(\n group.children,\n remainingGroups,\n newAncestors\n );\n results.push(...subScopes);\n }\n\n return results;\n}\n\nexport function collectSegments(\n nodes: (Segment | Group)[],\n targetSegmentName: string,\n ancestors: Nodes[]\n): { segment: Segment; ancestors: Nodes[] }[] {\n const result: { segment: Segment; ancestors: Nodes[] }[] = [];\n\n for (const node of nodes) {\n if (node.type === \"segment\") {\n const name = getSegmentName(node);\n if (name === targetSegmentName) {\n result.push({ ancestors: [...ancestors], segment: node });\n }\n }\n\n if (node.type === \"group\") {\n const nextAncestors = [...ancestors, node];\n result.push(\n ...collectSegments(\n filterSegmentsAndGroups(node.children),\n targetSegmentName,\n nextAncestors\n )\n );\n }\n }\n\n return result;\n}\n\nexport function collectGroups(\n nodes: (Segment | Group)[],\n targetGroupName: string,\n ancestors: Nodes[]\n): { group: Group; ancestors: Nodes[] }[] {\n const result: { group: Group; ancestors: Nodes[] }[] = [];\n\n for (const node of nodes) {\n if (node.type === \"group\" && node.name === targetGroupName) {\n result.push({ ancestors: [...ancestors], group: node });\n }\n\n if (node.type === \"group\") {\n const nextAncestors = [...ancestors, node];\n result.push(\n ...collectGroups(\n filterSegmentsAndGroups(node.children),\n targetGroupName,\n nextAncestors\n )\n );\n }\n }\n\n return result;\n}\n\nexport function locateField(\n segment: Segment,\n fieldNum: number,\n parentAncestors: Nodes[]\n): [Field, Nodes[]] | null {\n const fields = getFields(segment);\n const field = fields[fieldNum - 1];\n if (!field) {\n return null;\n }\n\n return [field, [...parentAncestors, segment]];\n}\n\nexport function locateRepetition(\n field: Field,\n repetition: number,\n parentAncestors: Nodes[]\n): [FieldRepetition, Nodes[]] | null {\n if (repetition < 1) {\n return null;\n }\n\n const node = field.children?.[repetition - 1];\n if (!node) {\n return null;\n }\n\n return [node as FieldRepetition, [...parentAncestors, field]];\n}\n\nexport function locateComponent(\n repetition: FieldRepetition,\n componentNum: number,\n parentAncestors: Nodes[]\n): [Component, Nodes[]] | null {\n if (componentNum < 1) {\n return null;\n }\n\n const component = repetition.children?.[componentNum - 1];\n if (!component) {\n return null;\n }\n\n return [component as Component, [...parentAncestors, repetition]];\n}\n\nexport function locateSubcomponent(\n component: Component,\n subcomponentNum: number,\n parentAncestors: Nodes[]\n): [Subcomponent, Nodes[]] | null {\n if (subcomponentNum < 1) {\n return null;\n }\n\n const node = component.children?.[subcomponentNum - 1];\n if (!node) {\n return null;\n }\n\n return [node as Subcomponent, [...parentAncestors, component]];\n}\n\nexport function getSegmentName(segment: Segment): string {\n return segment.name;\n}\n\nexport function getFields(segment: Segment): Field[] {\n return segment.children;\n}\n\nexport function filterSegmentsAndGroups(nodes: Nodes[]): (Segment | Group)[] {\n return nodes.filter(\n (node): node is Segment | Group =>\n node.type === \"segment\" || node.type === \"group\"\n );\n}\n","import type { Group, Nodes, Root, Segment } from \"@glion/ast\";\n\nimport { parse } from \"./parse\";\nimport type { InferNodeType } from \"./types\";\nimport {\n collectAllScopes,\n collectGroups,\n collectSegments,\n locateComponent,\n locateField,\n locateRepetition,\n locateSegment,\n locateSegmentOrGroup,\n locateSubcomponent,\n} from \"./utils\";\n\n/**\n * Select the first node at the given path and return it with its ancestor\n * chain.\n *\n * This function finds the first matching node for the given path. For paths\n * that can match multiple nodes (e.g., \"PID\" when multiple PID segments exist),\n * use {@link selectAll} to retrieve all matches.\n *\n * @example\n * ```typescript\n * const result = select(root, \"PID-5\");\n * if (result) {\n * result.node; // Type: Field\n * result.ancestors; // [Root, Segment]\n * }\n * ```;\n *\n * @param root - The root node to search from\n * @param path - The HL7 path string\n * @returns Object containing the node and its ancestors, or null if not found\n */\nexport function select<Path extends string>(\n root: Root,\n path: Path\n): { node: InferNodeType<Path>; ancestors: Nodes[] } | null {\n const parts = parse(path);\n\n // If no field access, we might be selecting a segment OR a group\n if (parts.field === undefined) {\n const result = locateSegmentOrGroup(root, parts);\n if (!result) {\n return null;\n }\n return {\n ancestors: result[1],\n node: result[0] as unknown as InferNodeType<Path>,\n };\n }\n\n // Field access means we're definitely accessing a segment\n const segmentResult = locateSegment(root, parts);\n if (!segmentResult) {\n return null;\n }\n const [segment, segmentAncestors] = segmentResult;\n\n const fieldResult = locateField(segment, parts.field, segmentAncestors);\n if (!fieldResult) {\n return null;\n }\n const [field, fieldAncestors] = fieldResult;\n\n if (\n parts.component === undefined &&\n parts.subcomponent === undefined &&\n parts.repetition === undefined\n ) {\n return {\n ancestors: fieldAncestors,\n node: field as unknown as InferNodeType<Path>,\n };\n }\n\n const repetitionResult = locateRepetition(\n field,\n parts.repetition ?? 1,\n fieldAncestors\n );\n if (!repetitionResult) {\n return null;\n }\n const [repetitionNode, repetitionAncestors] = repetitionResult;\n\n if (parts.component === undefined) {\n return {\n ancestors: repetitionAncestors,\n node: repetitionNode as unknown as InferNodeType<Path>,\n };\n }\n\n const componentResult = locateComponent(\n repetitionNode,\n parts.component,\n repetitionAncestors\n );\n if (!componentResult) {\n return null;\n }\n const [componentNode, componentAncestors] = componentResult;\n\n if (parts.subcomponent === undefined) {\n return {\n ancestors: componentAncestors,\n node: componentNode as unknown as InferNodeType<Path>,\n };\n }\n\n const subResult = locateSubcomponent(\n componentNode,\n parts.subcomponent,\n componentAncestors\n );\n if (!subResult) {\n return null;\n }\n\n return {\n ancestors: subResult[1],\n node: subResult[0] as unknown as InferNodeType<Path>,\n };\n}\n\n/**\n * Select all nodes that match the given path.\n *\n * This function returns all matching nodes for paths that can match multiple\n * elements. For example, \"PID\" will return all PID segments in the message, and\n * \"OBX-5\" will return all observation values.\n *\n * @example\n * ```typescript\n * // Get all OBX segments\n * const results = selectAll(root, \"OBX\");\n * for (const { node } of results) {\n * console.log(node.type); // 'segment'\n * }\n *\n * // Get all patient name fields\n * const names = selectAll(root, \"PID-5\");\n * ```;\n *\n * @param root - The root node to search from\n * @param path - The HL7 path string (must not include repetition index)\n * @returns Array of objects containing nodes and their ancestor chains\n */\n// oxlint-disable-next-line complexity/complexity -- path walker: one branch per scope level (group, segment, field, component, subcomponent)\nexport function selectAll<Path extends string>(\n root: Root,\n path: Path\n): { node: InferNodeType<Path>; ancestors: Nodes[] }[] {\n const parts = parse(path);\n\n // If path includes a specific repetition, delegate to select()\n if (\n parts.segment.repetition !== undefined ||\n parts.repetition !== undefined\n ) {\n const result = select(root, path);\n return result ? [result] : [];\n }\n\n const results: { node: InferNodeType<Path>; ancestors: Nodes[] }[] = [];\n\n // Get all matching segments from all possible scopes\n const scopes = collectAllScopes(root, parts.groups ?? []);\n const segments: { segment: Segment; ancestors: Nodes[] }[] = [];\n const includeGroups = parts.field === undefined;\n const groups: { group: Group; ancestors: Nodes[] }[] = [];\n\n for (const { scope, ancestors } of scopes) {\n const matchingSegments = collectSegments(\n scope,\n parts.segment.name,\n ancestors\n );\n segments.push(...matchingSegments);\n\n if (includeGroups) {\n const matchingGroups = collectGroups(\n scope,\n parts.segment.name,\n ancestors\n );\n for (const { group, ancestors: groupAncestors } of matchingGroups) {\n groups.push({ ancestors: groupAncestors, group });\n }\n }\n }\n\n // If path is segment-only, return all matching segments and groups\n if (parts.field === undefined) {\n for (const { segment, ancestors } of segments) {\n results.push({\n ancestors,\n node: segment as InferNodeType<Path>,\n });\n }\n\n for (const { group, ancestors } of groups) {\n results.push({\n ancestors,\n node: group as InferNodeType<Path>,\n });\n }\n return results;\n }\n\n // For each segment, try to get the field/component/subcomponent\n for (const { segment, ancestors: segmentAncestors } of segments) {\n const fieldResult = locateField(segment, parts.field, segmentAncestors);\n if (!fieldResult) {\n continue;\n }\n const [field, fieldAncestors] = fieldResult;\n\n if (\n parts.component === undefined &&\n parts.subcomponent === undefined &&\n parts.repetition === undefined\n ) {\n results.push({\n ancestors: fieldAncestors,\n node: field as unknown as InferNodeType<Path>,\n });\n continue;\n }\n\n // For field repetitions, components, and subcomponents,\n // we need to iterate through all repetitions\n if (!field.children) {\n continue;\n }\n\n for (const repetitionNode of field.children) {\n const repetitionAncestors = [...fieldAncestors, field];\n\n if (parts.component === undefined) {\n results.push({\n ancestors: repetitionAncestors,\n node: repetitionNode as unknown as InferNodeType<Path>,\n });\n continue;\n }\n\n const componentResult = locateComponent(\n repetitionNode,\n parts.component,\n repetitionAncestors\n );\n if (!componentResult) {\n continue;\n }\n const [componentNode, componentAncestors] = componentResult;\n\n if (parts.subcomponent === undefined) {\n results.push({\n ancestors: componentAncestors,\n node: componentNode as unknown as InferNodeType<Path>,\n });\n continue;\n }\n\n const subResult = locateSubcomponent(\n componentNode,\n parts.subcomponent,\n componentAncestors\n );\n if (subResult) {\n results.push({\n ancestors: subResult[1],\n node: subResult[0] as unknown as InferNodeType<Path>,\n });\n }\n }\n }\n\n return results;\n}\n","import type { Nodes, Root } from \"@glion/ast\";\n\nimport { select } from \"./select\";\n\n/**\n * Get the string value at the path, drilling down through single-child nodes\n * when needed. Also returns the node and ancestor chain for context.\n *\n * This is a convenience function that automatically traverses through container\n * nodes (Field → FieldRepetition → Component → Subcomponent) to extract the\n * primary string value. When a container has multiple children, the first child\n * is selected (e.g., `value(tree, \"MSH-12\")` returns the first component of a\n * composite VID field).\n *\n * Nodes with no children return `value: null` to differentiate between empty\n * strings (\"\") and missing values.\n *\n * @example\n * ```typescript\n * const result = value(root, \"PID-5.1\");\n * if (result) {\n * console.log(result.value); // string | null\n * console.log(result.node.type); // 'subcomponent'\n * console.log(result.ancestors); // [Root, Segment, Field, ...]\n * }\n * ```;\n *\n * @param root - The root node to search from\n * @param path - The HL7 path string\n * @returns Object containing the value, node, and ancestors, or null if not\n * found\n */\nexport function value(\n root: Root,\n path: string\n): { value: string | null; node: Nodes; ancestors: Nodes[] } | null {\n const selectResult = select(root, path);\n if (!selectResult) {\n return null;\n }\n\n let { node } = selectResult;\n let { ancestors } = selectResult;\n\n // Drill down through single children until we reach a subcomponent\n while (node.type !== \"subcomponent\") {\n // Segments and groups can't be drilled down\n if (\n node.type === \"segment\" ||\n node.type === \"group\" ||\n node.type === \"root\"\n ) {\n return null;\n }\n\n // Type guard: at this point, node must be Field | FieldRepetition | Component\n if (!(\"children\" in node && node.children)) {\n return null;\n }\n\n if (node.children.length === 0) {\n return {\n ancestors: [...ancestors],\n node,\n value: null,\n };\n }\n\n const next = node.children[0];\n if (!next) {\n return null;\n }\n\n ancestors = [...ancestors, node];\n node = next;\n }\n\n // At this point, node.type === \"subcomponent\" is guaranteed\n return {\n ancestors,\n node,\n value: node.value,\n };\n}\n","import type { Delimiters, Root } from \"@glion/ast\";\nimport { DEFAULT_DELIMITERS } from \"@glion/utils\";\n\nimport { value } from \"./value\";\n\n/** Keys of MSH-2 encoding characters in positional order. */\nconst MSH2_KEYS = [\n \"component\",\n \"repetition\",\n \"escape\",\n \"subcomponent\",\n] as const;\n\n/**\n * Extract delimiters from a Root AST by reading MSH-1 and MSH-2.\n *\n * MSH-1 contains the field separator character (e.g., `|`).\n * MSH-2 contains up to 4 encoding characters: component, repetition,\n * escape, and subcomponent (e.g., `^~\\&`).\n *\n * Falls back to DEFAULT_DELIMITERS for any values that cannot be derived.\n *\n * @param root - The Root AST node to extract delimiters from.\n * @returns The resolved Delimiters object.\n */\nexport function delimiters(root: Root): Delimiters {\n const result = { ...DEFAULT_DELIMITERS };\n\n // MSH-1: field separator (single character)\n const msh1 = value(root, \"MSH-1\")?.value;\n if (msh1 && msh1.length === 1) {\n result.field = msh1;\n }\n\n // MSH-2: encoding characters (up to 4 positional chars)\n const msh2 = value(root, \"MSH-2\")?.value;\n if (msh2) {\n const chars = [...msh2];\n for (const [i, key] of MSH2_KEYS.entries()) {\n const ch = chars[i];\n if (ch) {\n result[key] = ch;\n }\n }\n }\n\n return result;\n}\n","import type { Nodes } from \"@glion/ast\";\n\n/**\n * Format a node and its ancestor chain into a canonical HL7v2 path string.\n *\n * This is the inverse of `select`: given a node and the ancestors\n * returned by `visit` or `select`, it produces the path string that\n * would select that node.\n *\n * @example\n * ```typescript\n * visit(tree, \"field\", (node, ancestors) => {\n * format(node, ancestors); // \"PID-5\"\n * });\n *\n * const result = select(root, \"PID-5.2\");\n * format(result.node, result.ancestors); // \"PID-5.2\"\n * ```;\n *\n * @param node - The target AST node\n * @param ancestors - Ancestor chain from root to parent (as provided by\n * visit/select)\n * @returns Canonical path string (e.g., \"PID-5.2\", \"ORDER-ORC-1\"), or `null` if the\n * ancestor chain contains no segment or group\n */\n// oxlint-disable-next-line complexity\nexport function format(node: Nodes, ancestors: Nodes[]): string | null {\n let result: string | null = null;\n const chain = [...ancestors, node];\n\n for (const [i, current] of chain.entries()) {\n const parent = chain[i - 1];\n\n switch (current.type) {\n case \"root\": {\n break;\n }\n\n case \"group\":\n case \"segment\": {\n const pos = positionOf(current, parent);\n result = (result ?? \"\") + current.name;\n if (pos > 1) {\n result += `[${pos}]`;\n }\n if (current.type === \"group\" && current !== node) {\n result += \"-\";\n }\n break;\n }\n\n case \"field\": {\n result += `-${positionOf(current, parent)}`;\n break;\n }\n\n case \"field-repetition\": {\n const pos = positionOf(current, parent);\n if (pos > 1 || current === node) {\n result += `[${pos}]`;\n }\n break;\n }\n\n case \"component\": {\n result += `.${positionOf(current, parent)}`;\n break;\n }\n\n case \"subcomponent\": {\n result += `.${positionOf(current, parent)}`;\n break;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Compute the 1-based position of a node among its parent's children.\n *\n * For named nodes (segments, groups), counts only same-name siblings\n * because segments are identified by name: the 2nd PID in [MSH, PID, OBX, PID]\n * is PID[2], not PID[4].\n *\n * For positional nodes (fields, repetitions, components, subcomponents),\n * uses the array index directly.\n */\nfunction positionOf(node: Nodes, parent: Nodes | undefined): number {\n if (!parent || !(\"children\" in parent)) {\n return 1;\n }\n\n const children = parent.children as Nodes[];\n\n // Named nodes: count same-name siblings before this node\n if (\"name\" in node) {\n const name = node.name as string;\n const { type } = node;\n let count = 0;\n for (const child of children) {\n if (child === node) {\n return count + 1;\n }\n if (child.type === type && \"name\" in child && child.name === name) {\n count++;\n }\n }\n throw new Error(\"format(): node not found in parent's children array\");\n }\n\n // Positional nodes: use array index\n const idx = children.indexOf(node);\n if (idx === -1) {\n throw new Error(\"format(): node not found in parent's children array\");\n }\n return idx + 1;\n}\n","import type { Root } from \"@glion/ast\";\n\nimport { select } from \"./select\";\n\n/**\n * Check if a node exists at the given path.\n *\n * This is a convenience function equivalent to `select(root, path) !== null`,\n * but more semantically clear for existence checks.\n *\n * @example\n * ```typescript\n * if (matches(root, \"PID-5\")) {\n * console.log(\"Patient has a name field\");\n * }\n *\n * if (!matches(root, \"OBX-5\")) {\n * throw new Error(\"Missing observation value\");\n * }\n * ```;\n *\n * @param root - The root node to search from\n * @param path - The HL7 path string\n * @returns True if the path resolves to a node, false otherwise\n */\nexport function matches(root: Root, path: string): boolean {\n return select(root, path) !== null;\n}\n","import type {\n Component,\n Field,\n FieldRepetition,\n Root,\n Subcomponent,\n} from \"@glion/ast\";\n\nimport { parse } from \"./parse\";\nimport { locateSegment } from \"./utils\";\n\n/**\n * Set a string value at the given HL7 path, creating all missing intermediate\n * nodes as needed (fields, repetitions, components, subcomponents).\n *\n * This is the write counterpart to {@link value}. It handles the full HL7v2\n * path syntax including group navigation and segment repetitions.\n *\n * Padding nodes are created with empty children arrays — they represent\n * structurally absent nodes, not empty values. Only the target node gets\n * a fully populated chain down to the subcomponent.\n *\n * @example\n * ```typescript\n * // Update existing value\n * set(tree, \"MSH-12\", \"2.7.1\");\n *\n * // Create missing MSH-9.3 (fills gaps with empty components)\n * set(tree, \"MSH-9.3\", \"ADT_A01\");\n *\n * // Set a specific repetition\n * set(tree, \"PID-3[2]\", \"ID-002\");\n *\n * // Set a subcomponent\n * set(tree, \"PID-5.1.2\", \"suffix\");\n * ```;\n *\n * @param root - The root node to modify\n * @param path - The HL7 path string (must include at least a field)\n * @param val - The string value to set\n * @throws When the path has no field specifier (segment-only paths)\n * @throws When the target segment does not exist in the tree\n */\nexport function set(root: Root, path: string, val: string): void {\n const parts = parse(path);\n\n if (parts.field === undefined) {\n throw new Error(`Cannot set value on segment-only path: \"${path}\"`);\n }\n\n // Use locateSegment for full path support (groups, segment repetitions)\n const segmentResult = locateSegment(root, parts);\n if (!segmentResult) {\n throw new Error(`Segment \"${parts.segment.name}\" not found in tree`);\n }\n const [segment] = segmentResult;\n\n // Ensure fields exist up to the target index\n const fieldIndex = parts.field - 1;\n padArray(segment.children, fieldIndex + 1, stubField);\n\n const field = segment.children[fieldIndex]!;\n\n // Ensure repetitions exist up to the target index\n const repIndex = (parts.repetition ?? 1) - 1;\n padArray(field.children, repIndex + 1, stubRepetition);\n\n const repetition = field.children[repIndex]!;\n\n // Ensure components exist up to the target index\n const compIndex = (parts.component ?? 1) - 1;\n padArray(repetition.children, compIndex + 1, stubComponent);\n\n const component = repetition.children[compIndex]!;\n\n // Ensure subcomponents exist up to the target index\n const subIndex = (parts.subcomponent ?? 1) - 1;\n padArray(component.children, subIndex + 1, stubSubcomponent);\n\n // Set the value\n component.children[subIndex]!.value = val;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Pad an array to a target length using a factory function.\n */\nfunction padArray<T>(arr: T[], targetLength: number, factory: () => T): void {\n while (arr.length < targetLength) {\n arr.push(factory());\n }\n}\n\n/**\n * Stub nodes for padding — created with empty children arrays to represent\n * structurally absent nodes. These are distinguishable from nodes with empty\n * values (which have a subcomponent with value \"\").\n */\n\nfunction stubField(): Field {\n return { children: [], type: \"field\" } as Field;\n}\n\nfunction stubRepetition(): FieldRepetition {\n return { children: [], type: \"field-repetition\" } as FieldRepetition;\n}\n\nfunction stubComponent(): Component {\n return { children: [], type: \"component\" } as Component;\n}\n\nfunction stubSubcomponent(): Subcomponent {\n return { type: \"subcomponent\", value: \"\" } as Subcomponent;\n}\n"],"mappings":"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"}
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,KAAK,EACL,eAAe,EACf,KAAK,EACL,KAAK,EACL,OAAO,EACP,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,KAAK,CAAC;AAEvE;;GAEG;AACH,KAAK,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,GAAG,IAAI,MAAM,GAAG,GAC3E,GAAG,GACH,CAAC,CAAC;AAEN;;GAEG;AACH,KAAK,QAAQ,CAAC,IAAI,SAAS,MAAM,IAC/B,IAAI,SAAS,GAAG,MAAM,OAAO,IAAI,MAAM,KAAK,EAAE,GAC1C,QAAQ,CAAC,KAAK,CAAC,GACf,IAAI,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,MAAM,aAAa,CAAC,IAAI,SAAS,MAAM,IAE3C,MAAM,SAAS,IAAI,GACf,KAAK,GAEL,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,IAAI,MAAM,EAAE,GAC7D,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,YAAY,GACZ,OAAO,GAAG,KAAK,GACjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,EAAE,GACxE,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,YAAY,GACZ,OAAO,GAAG,KAAK,GAEjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,EAAE,GACnD,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,SAAS,GACT,OAAO,GAAG,KAAK,GACjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,KAAK,MAAM,EAAE,GAC9D,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,SAAS,GACT,OAAO,GAAG,KAAK,GAEjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,GAAG,GACpD,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,eAAe,GACf,OAAO,GAAG,KAAK,GAEjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,IAAI,EAAE,GACpC,QAAQ,CAAC,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,GACvD,KAAK,GACL,OAAO,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,KAAK,EACL,eAAe,EACf,KAAK,EACL,KAAK,EACL,OAAO,EACP,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,KAAK,CAAC;AAEvE;;GAEG;AACH,KAAK,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,GAAG,IAAI,MAAM,GAAG,GAC3E,GAAG,GACH,CAAC,CAAC;AAEN;;GAEG;AACH,KAAK,QAAQ,CAAC,IAAI,SAAS,MAAM,IAC/B,IAAI,SAAS,GAAG,MAAM,OAAO,IAAI,MAAM,KAAK,EAAE,GAC1C,QAAQ,CAAC,KAAK,CAAC,GACf,IAAI,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,MAAM,aAAa,CAAC,IAAI,SAAS,MAAM,IAE3C,MAAM,SAAS,IAAI,GACf,KAAK,GAEL,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,IAAI,MAAM,EAAE,GAC7D,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,YAAY,GACZ,OAAO,GAAG,KAAK,GACjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,EAAE,GACxE,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,YAAY,GACZ,OAAO,GAAG,KAAK,GAEjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,EAAE,GACnD,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,SAAS,GACT,OAAO,GAAG,KAAK,GACjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,KAAK,MAAM,EAAE,GAC9D,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,SAAS,GACT,OAAO,GAAG,KAAK,GAEjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,GAAG,GACpD,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,SAAS,IAAI,GAClD,eAAe,GACf,OAAO,GAAG,KAAK,GAEjB,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,IAAI,EAAE,GACpC,QAAQ,CAAC,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,GACvD,KAAK,GACL,OAAO,GAAG,KAAK,GAEjB,AADA,8CAA8C;AAC9C,OAAO,GAAG,KAAK,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glion/util-query",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Query HL7v2 AST nodes by HL7 location paths",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"health",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@glion/ast": "0.
|
|
37
|
-
"@glion/utils": "0.
|
|
36
|
+
"@glion/ast": "0.21.0",
|
|
37
|
+
"@glion/utils": "0.21.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@stryker-mutator/core": "10.0.0",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"tsdown": "0.21.10",
|
|
47
47
|
"typescript": "6.0.3",
|
|
48
48
|
"vitest": "4.1.11",
|
|
49
|
-
"@glion/builder": "0.
|
|
49
|
+
"@glion/builder": "0.21.0",
|
|
50
50
|
"@glion/check-readme": "0.18.0",
|
|
51
|
-
"@glion/parser": "0.
|
|
51
|
+
"@glion/parser": "0.21.0",
|
|
52
52
|
"@glion/testing": "0.18.0",
|
|
53
53
|
"@glion/tsconfig": "0.18.0"
|
|
54
54
|
},
|