@glion/to-hl7v2 0.16.0 → 0.19.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/dist/index.js +14 -5
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
package/dist/index.js
CHANGED
|
@@ -184,10 +184,10 @@ function locateSegmentOrGroup(root, parts) {
|
|
|
184
184
|
const match = matchedSegments[(targetRepetition ?? 1) - 1];
|
|
185
185
|
if (match) return [match.segment, match.ancestors];
|
|
186
186
|
}
|
|
187
|
-
const matchedGroups = collectGroups(scope, targetName);
|
|
187
|
+
const matchedGroups = collectGroups(scope, targetName, ancestors);
|
|
188
188
|
if (matchedGroups.length > 0) {
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
189
|
+
const match = matchedGroups[(targetRepetition ?? 1) - 1];
|
|
190
|
+
if (match) return [match.group, match.ancestors];
|
|
191
191
|
}
|
|
192
192
|
return null;
|
|
193
193
|
}
|
|
@@ -229,9 +229,18 @@ function collectSegments(nodes, targetSegmentName, ancestors) {
|
|
|
229
229
|
}
|
|
230
230
|
return result;
|
|
231
231
|
}
|
|
232
|
-
function collectGroups(nodes, targetGroupName) {
|
|
232
|
+
function collectGroups(nodes, targetGroupName, ancestors) {
|
|
233
233
|
const result = [];
|
|
234
|
-
for (const node of nodes)
|
|
234
|
+
for (const node of nodes) {
|
|
235
|
+
if (node.type === "group" && node.name === targetGroupName) result.push({
|
|
236
|
+
ancestors: [...ancestors],
|
|
237
|
+
group: node
|
|
238
|
+
});
|
|
239
|
+
if (node.type === "group") {
|
|
240
|
+
const nextAncestors = [...ancestors, node];
|
|
241
|
+
result.push(...collectGroups(filterSegmentsAndGroups(node.children), targetGroupName, nextAncestors));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
235
244
|
return result;
|
|
236
245
|
}
|
|
237
246
|
function locateField(segment, fieldNum, parentAncestors) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["queryDelimiters","delimiters"],"sources":["../../util-query/dist/index.js","../src/index.ts"],"sourcesContent":["import { DEFAULT_DELIMITERS } from \"@glion/utils\";\n//#region src/parse.ts\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 = /^((?:[A-Z][A-Z0-9]*(?:\\[\\d+\\])?-)*)([A-Z][A-Z0-9]*)(?:\\[(\\d+)\\])?(?:-(\\d+)(?:(?:\\[(\\d+)\\])?(?:\\.(\\d+)(?:\\.(\\d+))?)?)?)?$/;\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 = /* @__PURE__ */ new Map();\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 = {\n\t\"MSH-10\": {\n\t\tfield: 10,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-12\": {\n\t\tfield: 12,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-3\": {\n\t\tfield: 3,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-4\": {\n\t\tfield: 4,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-5\": {\n\t\tfield: 5,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-6\": {\n\t\tfield: 6,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-9\": {\n\t\tfield: 9,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-9.1\": {\n\t\tcomponent: 1,\n\t\tfield: 9,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-9.2\": {\n\t\tcomponent: 2,\n\t\tfield: 9,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-9.3\": {\n\t\tcomponent: 3,\n\t\tfield: 9,\n\t\tsegment: { name: \"MSH\" }\n\t}\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*/\nfunction parse(path) {\n\tconst hot = HOT_PATHS[path];\n\tif (hot) return hot;\n\tconst cached = parseCache.get(path);\n\tif (cached) return cached;\n\tconst result = parseImpl(path);\n\tparseCache.set(path, result);\n\treturn result;\n}\n/**\n* Internal implementation of path parsing.\n*/\nfunction parseImpl(path) {\n\tif (!path || typeof path !== \"string\") throw new Error(`Path must be a non-empty string, got: ${path}`);\n\tif (path.trim() !== path) throw new Error(`Path cannot contain leading/trailing spaces: \"${path}\"`);\n\tconst match = PATH_REGEX.exec(path);\n\tif (!match) throw new Error(`Invalid HL7 path format: \"${path}\". Expected [GROUP[N]-]...NAME[N][-FIELD[REPETITION][.COMPONENT[.SUBCOMPONENT]]].`);\n\tconst [, groupsRaw, segmentName, segmentRep, fieldStr, repetitionStr, componentStr, subcomponentStr] = match;\n\tif (!segmentName) throw new Error(`Path must include a segment identifier: \"${path}\"`);\n\tconst parts = { segment: { name: segmentName } };\n\tif (segmentRep) {\n\t\tconst repetition = Number.parseInt(segmentRep, 10);\n\t\tif (repetition < 1) throw new Error(`Segment repetition must be ≥1, got: ${segmentRep} in \"${path}\"`);\n\t\tparts.segment.repetition = repetition;\n\t}\n\tif (groupsRaw) {\n\t\tconst groups = [];\n\t\tfor (const groupMatch of groupsRaw.matchAll(/([A-Z][A-Z0-9]*)(?:\\[(\\d+)\\])?-/g)) {\n\t\t\tconst name = groupMatch[1];\n\t\t\tif (!name) continue;\n\t\t\tconst repStr = groupMatch[2];\n\t\t\tconst group = { name };\n\t\t\tif (repStr) {\n\t\t\t\tconst repetition = Number.parseInt(repStr, 10);\n\t\t\t\tif (repetition < 1) throw new Error(`Group repetition must be ≥1, got: ${repStr} in \"${path}\"`);\n\t\t\t\tgroup.repetition = repetition;\n\t\t\t}\n\t\t\tgroups.push(group);\n\t\t}\n\t\tif (groups.length > 0) parts.groups = groups;\n\t}\n\tif (fieldStr) {\n\t\tconst field = Number.parseInt(fieldStr, 10);\n\t\tif (field < 1) throw new Error(`Field number must be ≥1, got: ${fieldStr}`);\n\t\tparts.field = field;\n\t}\n\tif (repetitionStr) {\n\t\tconst repetition = Number.parseInt(repetitionStr, 10);\n\t\tif (repetition < 1) throw new Error(`Repetition number must be ≥1, got: ${repetitionStr}`);\n\t\tparts.repetition = repetition;\n\t}\n\tif (componentStr) {\n\t\tconst component = Number.parseInt(componentStr, 10);\n\t\tif (component < 1) throw new Error(`Component number must be ≥1, got: ${componentStr}`);\n\t\tparts.component = component;\n\t}\n\tif (subcomponentStr) {\n\t\tconst subcomponent = Number.parseInt(subcomponentStr, 10);\n\t\tif (subcomponent < 1) throw new Error(`Subcomponent number must be ≥1, got: ${subcomponentStr}`);\n\t\tparts.subcomponent = subcomponent;\n\t}\n\treturn parts;\n}\n//#endregion\n//#region src/utils.ts\nfunction locateSegmentOrGroup(root, parts) {\n\tconst ancestors = [root];\n\tconst scope = followGroups(root, parts.groups ?? [], ancestors);\n\tif (!scope) return null;\n\tconst targetName = parts.segment.name;\n\tconst targetRepetition = parts.segment.repetition;\n\tconst matchedSegments = collectSegments(scope, targetName, ancestors);\n\tif (matchedSegments.length > 0) {\n\t\tconst match = matchedSegments[(targetRepetition ?? 1) - 1];\n\t\tif (match) return [match.segment, match.ancestors];\n\t}\n\tconst matchedGroups = collectGroups(scope, targetName);\n\tif (matchedGroups.length > 0) {\n\t\tconst group = matchedGroups[(targetRepetition ?? 1) - 1];\n\t\tif (group) return [group, ancestors];\n\t}\n\treturn null;\n}\nfunction locateSegment(root, parts) {\n\tconst ancestors = [root];\n\tconst scope = followGroups(root, parts.groups ?? [], ancestors);\n\tif (!scope) return null;\n\tconst matchedSegments = collectSegments(scope, parts.segment.name, ancestors);\n\tif (matchedSegments.length === 0) return null;\n\tconst match = matchedSegments[(parts.segment.repetition ?? 1) - 1];\n\tif (!match) return null;\n\treturn [match.segment, match.ancestors];\n}\nfunction followGroups(root, groups, ancestorChain) {\n\tlet children = filterSegmentsAndGroups(root.children);\n\tfor (const locator of groups) {\n\t\tconst matchedGroups = children.filter((node) => node.type === \"group\" && node.name === locator.name);\n\t\tif (matchedGroups.length === 0) return null;\n\t\tconst selected = matchedGroups[(locator.repetition ?? 1) - 1];\n\t\tif (!selected) return null;\n\t\tancestorChain.push(selected);\n\t\tchildren = filterSegmentsAndGroups(selected.children);\n\t}\n\treturn children;\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*/\nfunction collectAllScopes(root, groups) {\n\tif (groups.length === 0) return [{\n\t\tancestors: [root],\n\t\tscope: filterSegmentsAndGroups(root.children)\n\t}];\n\tconst results = [];\n\tconst firstLocator = groups[0];\n\tconst remainingGroups = groups.slice(1);\n\tif (!firstLocator) return [{\n\t\tancestors: [root],\n\t\tscope: filterSegmentsAndGroups(root.children)\n\t}];\n\tconst matchingGroups = filterSegmentsAndGroups(root.children).filter((node) => node.type === \"group\" && node.name === firstLocator.name);\n\tif (firstLocator.repetition !== void 0) {\n\t\tconst selected = matchingGroups[firstLocator.repetition - 1];\n\t\tif (!selected) return [];\n\t\tconst ancestors = [root, selected];\n\t\treturn collectAllScopesRecursive(selected.children, remainingGroups, ancestors);\n\t}\n\tfor (const group of matchingGroups) {\n\t\tconst ancestors = [root, group];\n\t\tconst subScopes = collectAllScopesRecursive(group.children, remainingGroups, ancestors);\n\t\tresults.push(...subScopes);\n\t}\n\treturn results;\n}\nfunction collectAllScopesRecursive(children, groups, ancestors) {\n\tif (groups.length === 0) return [{\n\t\tancestors,\n\t\tscope: filterSegmentsAndGroups(children)\n\t}];\n\tconst results = [];\n\tconst firstLocator = groups[0];\n\tconst remainingGroups = groups.slice(1);\n\tif (!firstLocator) return [{\n\t\tancestors,\n\t\tscope: filterSegmentsAndGroups(children)\n\t}];\n\tconst matchingGroups = filterSegmentsAndGroups(children).filter((node) => node.type === \"group\" && node.name === firstLocator.name);\n\tif (firstLocator.repetition !== void 0) {\n\t\tconst selected = matchingGroups[firstLocator.repetition - 1];\n\t\tif (!selected) return [];\n\t\tconst newAncestors = [...ancestors, selected];\n\t\treturn collectAllScopesRecursive(selected.children, remainingGroups, newAncestors);\n\t}\n\tfor (const group of matchingGroups) {\n\t\tconst newAncestors = [...ancestors, group];\n\t\tconst subScopes = collectAllScopesRecursive(group.children, remainingGroups, newAncestors);\n\t\tresults.push(...subScopes);\n\t}\n\treturn results;\n}\nfunction collectSegments(nodes, targetSegmentName, ancestors) {\n\tconst result = [];\n\tfor (const node of nodes) {\n\t\tif (node.type === \"segment\") {\n\t\t\tif (getSegmentName(node) === targetSegmentName) result.push({\n\t\t\t\tancestors: [...ancestors],\n\t\t\t\tsegment: node\n\t\t\t});\n\t\t}\n\t\tif (node.type === \"group\") {\n\t\t\tconst nextAncestors = [...ancestors, node];\n\t\t\tresult.push(...collectSegments(filterSegmentsAndGroups(node.children), targetSegmentName, nextAncestors));\n\t\t}\n\t}\n\treturn result;\n}\nfunction collectGroups(nodes, targetGroupName) {\n\tconst result = [];\n\tfor (const node of nodes) if (node.type === \"group\" && node.name === targetGroupName) result.push(node);\n\treturn result;\n}\nfunction locateField(segment, fieldNum, parentAncestors) {\n\tconst field = getFields(segment)[fieldNum - 1];\n\tif (!field) return null;\n\treturn [field, [...parentAncestors, segment]];\n}\nfunction locateRepetition(field, repetition, parentAncestors) {\n\tif (repetition < 1) return null;\n\tconst node = field.children?.[repetition - 1];\n\tif (!node) return null;\n\treturn [node, [...parentAncestors, field]];\n}\nfunction locateComponent(repetition, componentNum, parentAncestors) {\n\tif (componentNum < 1) return null;\n\tconst component = repetition.children?.[componentNum - 1];\n\tif (!component) return null;\n\treturn [component, [...parentAncestors, repetition]];\n}\nfunction locateSubcomponent(component, subcomponentNum, parentAncestors) {\n\tif (subcomponentNum < 1) return null;\n\tconst node = component.children?.[subcomponentNum - 1];\n\tif (!node) return null;\n\treturn [node, [...parentAncestors, component]];\n}\nfunction getSegmentName(segment) {\n\treturn segment.name;\n}\nfunction getFields(segment) {\n\treturn segment.children;\n}\nfunction filterSegmentsAndGroups(nodes) {\n\treturn nodes.filter((node) => node.type === \"segment\" || node.type === \"group\");\n}\n//#endregion\n//#region src/select.ts\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*/\nfunction select(root, path) {\n\tconst parts = parse(path);\n\tif (parts.field === void 0) {\n\t\tconst result = locateSegmentOrGroup(root, parts);\n\t\tif (!result) return null;\n\t\treturn {\n\t\t\tancestors: result[1],\n\t\t\tnode: result[0]\n\t\t};\n\t}\n\tconst segmentResult = locateSegment(root, parts);\n\tif (!segmentResult) return null;\n\tconst [segment, segmentAncestors] = segmentResult;\n\tconst fieldResult = locateField(segment, parts.field, segmentAncestors);\n\tif (!fieldResult) return null;\n\tconst [field, fieldAncestors] = fieldResult;\n\tif (parts.component === void 0 && parts.subcomponent === void 0 && parts.repetition === void 0) return {\n\t\tancestors: fieldAncestors,\n\t\tnode: field\n\t};\n\tconst repetitionResult = locateRepetition(field, parts.repetition ?? 1, fieldAncestors);\n\tif (!repetitionResult) return null;\n\tconst [repetitionNode, repetitionAncestors] = repetitionResult;\n\tif (parts.component === void 0) return {\n\t\tancestors: repetitionAncestors,\n\t\tnode: repetitionNode\n\t};\n\tconst componentResult = locateComponent(repetitionNode, parts.component, repetitionAncestors);\n\tif (!componentResult) return null;\n\tconst [componentNode, componentAncestors] = componentResult;\n\tif (parts.subcomponent === void 0) return {\n\t\tancestors: componentAncestors,\n\t\tnode: componentNode\n\t};\n\tconst subResult = locateSubcomponent(componentNode, parts.subcomponent, componentAncestors);\n\tif (!subResult) return null;\n\treturn {\n\t\tancestors: subResult[1],\n\t\tnode: subResult[0]\n\t};\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*/\nfunction selectAll(root, path) {\n\tconst parts = parse(path);\n\tif (parts.segment.repetition !== void 0 || parts.repetition !== void 0) {\n\t\tconst result = select(root, path);\n\t\treturn result ? [result] : [];\n\t}\n\tconst results = [];\n\tconst scopes = collectAllScopes(root, parts.groups ?? []);\n\tconst segments = [];\n\tconst includeGroups = parts.field === void 0;\n\tconst groups = [];\n\tfor (const { scope, ancestors } of scopes) {\n\t\tconst matchingSegments = collectSegments(scope, parts.segment.name, ancestors);\n\t\tsegments.push(...matchingSegments);\n\t\tif (includeGroups) {\n\t\t\tconst matchingGroups = collectGroups(scope, parts.segment.name);\n\t\t\tfor (const group of matchingGroups) groups.push({\n\t\t\t\tancestors: [...ancestors],\n\t\t\t\tgroup\n\t\t\t});\n\t\t}\n\t}\n\tif (parts.field === void 0) {\n\t\tfor (const { segment, ancestors } of segments) results.push({\n\t\t\tancestors,\n\t\t\tnode: segment\n\t\t});\n\t\tfor (const { group, ancestors } of groups) results.push({\n\t\t\tancestors,\n\t\t\tnode: group\n\t\t});\n\t\treturn results;\n\t}\n\tfor (const { segment, ancestors: segmentAncestors } of segments) {\n\t\tconst fieldResult = locateField(segment, parts.field, segmentAncestors);\n\t\tif (!fieldResult) continue;\n\t\tconst [field, fieldAncestors] = fieldResult;\n\t\tif (parts.component === void 0 && parts.subcomponent === void 0 && parts.repetition === void 0) {\n\t\t\tresults.push({\n\t\t\t\tancestors: fieldAncestors,\n\t\t\t\tnode: field\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (!field.children) continue;\n\t\tfor (const repetitionNode of field.children) {\n\t\t\tconst repetitionAncestors = [...fieldAncestors, field];\n\t\t\tif (parts.component === void 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\tancestors: repetitionAncestors,\n\t\t\t\t\tnode: repetitionNode\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst componentResult = locateComponent(repetitionNode, parts.component, repetitionAncestors);\n\t\t\tif (!componentResult) continue;\n\t\t\tconst [componentNode, componentAncestors] = componentResult;\n\t\t\tif (parts.subcomponent === void 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\tancestors: componentAncestors,\n\t\t\t\t\tnode: componentNode\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst subResult = locateSubcomponent(componentNode, parts.subcomponent, componentAncestors);\n\t\t\tif (subResult) results.push({\n\t\t\t\tancestors: subResult[1],\n\t\t\t\tnode: subResult[0]\n\t\t\t});\n\t\t}\n\t}\n\treturn results;\n}\n//#endregion\n//#region src/value.ts\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*/\nfunction value(root, path) {\n\tconst selectResult = select(root, path);\n\tif (!selectResult) return null;\n\tlet { node } = selectResult;\n\tlet { ancestors } = selectResult;\n\twhile (node.type !== \"subcomponent\") {\n\t\tif (node.type === \"segment\" || node.type === \"group\" || node.type === \"root\") return null;\n\t\tif (!(\"children\" in node && node.children)) return null;\n\t\tif (node.children.length === 0) return {\n\t\t\tancestors: [...ancestors],\n\t\t\tnode,\n\t\t\tvalue: null\n\t\t};\n\t\tconst next = node.children[0];\n\t\tif (!next) return null;\n\t\tancestors = [...ancestors, node];\n\t\tnode = next;\n\t}\n\treturn {\n\t\tancestors,\n\t\tnode,\n\t\tvalue: node.value\n\t};\n}\n//#endregion\n//#region src/delimiters.ts\n/** Keys of MSH-2 encoding characters in positional order. */\nconst MSH2_KEYS = [\n\t\"component\",\n\t\"repetition\",\n\t\"escape\",\n\t\"subcomponent\"\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*/\nfunction delimiters(root) {\n\tconst result = { ...DEFAULT_DELIMITERS };\n\tconst msh1 = value(root, \"MSH-1\")?.value;\n\tif (msh1 && msh1.length === 1) result.field = msh1;\n\tconst msh2 = value(root, \"MSH-2\")?.value;\n\tif (msh2) {\n\t\tconst chars = [...msh2];\n\t\tfor (const [i, key] of MSH2_KEYS.entries()) {\n\t\t\tconst ch = chars[i];\n\t\t\tif (ch) result[key] = ch;\n\t\t}\n\t}\n\treturn result;\n}\n//#endregion\n//#region src/format.ts\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*/\nfunction format(node, ancestors) {\n\tlet result = null;\n\tconst chain = [...ancestors, node];\n\tfor (const [i, current] of chain.entries()) {\n\t\tconst parent = chain[i - 1];\n\t\tswitch (current.type) {\n\t\t\tcase \"root\": break;\n\t\t\tcase \"group\":\n\t\t\tcase \"segment\": {\n\t\t\t\tconst pos = positionOf(current, parent);\n\t\t\t\tresult = (result ?? \"\") + current.name;\n\t\t\t\tif (pos > 1) result += `[${pos}]`;\n\t\t\t\tif (current.type === \"group\" && current !== node) result += \"-\";\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"field\":\n\t\t\t\tresult += `-${positionOf(current, parent)}`;\n\t\t\t\tbreak;\n\t\t\tcase \"field-repetition\": {\n\t\t\t\tconst pos = positionOf(current, parent);\n\t\t\t\tif (pos > 1 || current === node) result += `[${pos}]`;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"component\":\n\t\t\t\tresult += `.${positionOf(current, parent)}`;\n\t\t\t\tbreak;\n\t\t\tcase \"subcomponent\":\n\t\t\t\tresult += `.${positionOf(current, parent)}`;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn result;\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, parent) {\n\tif (!parent || !(\"children\" in parent)) return 1;\n\tconst children = parent.children;\n\tif (\"name\" in node) {\n\t\tconst name = node.name;\n\t\tconst { type } = node;\n\t\tlet count = 0;\n\t\tfor (const child of children) {\n\t\t\tif (child === node) return count + 1;\n\t\t\tif (child.type === type && \"name\" in child && child.name === name) count++;\n\t\t}\n\t\tthrow new Error(\"format(): node not found in parent's children array\");\n\t}\n\tconst idx = children.indexOf(node);\n\tif (idx === -1) throw new Error(\"format(): node not found in parent's children array\");\n\treturn idx + 1;\n}\n//#endregion\n//#region src/matches.ts\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*/\nfunction matches(root, path) {\n\treturn select(root, path) !== null;\n}\n//#endregion\n//#region src/set.ts\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*/\nfunction set(root, path, val) {\n\tconst parts = parse(path);\n\tif (parts.field === void 0) throw new Error(`Cannot set value on segment-only path: \"${path}\"`);\n\tconst segmentResult = locateSegment(root, parts);\n\tif (!segmentResult) throw new Error(`Segment \"${parts.segment.name}\" not found in tree`);\n\tconst [segment] = segmentResult;\n\tconst fieldIndex = parts.field - 1;\n\tpadArray(segment.children, fieldIndex + 1, stubField);\n\tconst field = segment.children[fieldIndex];\n\tconst repIndex = (parts.repetition ?? 1) - 1;\n\tpadArray(field.children, repIndex + 1, stubRepetition);\n\tconst repetition = field.children[repIndex];\n\tconst compIndex = (parts.component ?? 1) - 1;\n\tpadArray(repetition.children, compIndex + 1, stubComponent);\n\tconst component = repetition.children[compIndex];\n\tconst subIndex = (parts.subcomponent ?? 1) - 1;\n\tpadArray(component.children, subIndex + 1, stubSubcomponent);\n\tcomponent.children[subIndex].value = val;\n}\n/**\n* Pad an array to a target length using a factory function.\n*/\nfunction padArray(arr, targetLength, factory) {\n\twhile (arr.length < targetLength) arr.push(factory());\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*/\nfunction stubField() {\n\treturn {\n\t\tchildren: [],\n\t\ttype: \"field\"\n\t};\n}\nfunction stubRepetition() {\n\treturn {\n\t\tchildren: [],\n\t\ttype: \"field-repetition\"\n\t};\n}\nfunction stubComponent() {\n\treturn {\n\t\tchildren: [],\n\t\ttype: \"component\"\n\t};\n}\nfunction stubSubcomponent() {\n\treturn {\n\t\ttype: \"subcomponent\",\n\t\tvalue: \"\"\n\t};\n}\n//#endregion\nexport { delimiters, format, matches, parse, select, selectAll, set, value };\n\n//# sourceMappingURL=index.js.map","import type {\n Component,\n Delimiters,\n Field,\n FieldRepetition,\n Nodes,\n Root,\n Segment,\n Subcomponent,\n} from \"@glion/ast\";\nimport { delimiters as queryDelimiters } from \"@glion/util-query\";\nimport { DEFAULT_DELIMITERS } from \"@glion/utils\";\nimport type { Plugin } from \"unified\";\nimport type { Node } from \"unist\";\nimport type { VFile } from \"vfile\";\n\nexport interface Hl7v2ToHl7v2Options {\n /** Append a field delimiter after the last field in each segment. */\n trailingDelimiter?: boolean;\n}\n\n/**\n * Unified compiler plugin: HL7v2 AST → HL7v2 string.\n *\n * Reads `file.data.delimiters` if set by hl7v2-annotate-delimiters,\n * otherwise derives from MSH-1/MSH-2 via `delimiters()` for standalone use.\n */\nexport const hl7v2ToHl7v2: Plugin<[Hl7v2ToHl7v2Options?], Root, string> =\n function hl7v2ToHl7v2(options?: Hl7v2ToHl7v2Options): void {\n // biome-ignore lint/complexity/noUselessThisAlias: unified plugin shape\n const self = this;\n self.compiler = (tree: Node, file: VFile): string =>\n toHl7v2(\n tree as Nodes,\n file.data.delimiters as Delimiters | undefined,\n options\n );\n };\n\n/**\n * Serialize an HL7v2 AST node back to its wire format.\n *\n * Works on any node in the tree — a full Root, a single Segment, or\n * even a lone Field. Delimiters default to the standard set unless\n * overridden or derivable from an MSH segment in the tree.\n */\nexport function toHl7v2(\n node: Nodes,\n delimiters?: Partial<Delimiters>,\n options?: Hl7v2ToHl7v2Options\n): string {\n const d = {\n ...(node.type === \"root\" ? queryDelimiters(node) : DEFAULT_DELIMITERS),\n ...delimiters,\n };\n const trailing = options?.trailingDelimiter === true;\n\n // -- leaf & field-level serializers (no options needed) ----------------\n\n const sub = (s: Subcomponent): string => s.value ?? \"\";\n\n const comp = (c: Component): string =>\n ((c.children || []) as Subcomponent[]).map(sub).join(d.subcomponent);\n\n const rep = (r: FieldRepetition): string =>\n (r.children as Component[]).map(comp).join(d.component);\n\n const field = (f: Field): string =>\n (f.children as FieldRepetition[]).map(rep).join(d.repetition);\n\n // -- segment-level serializers ----------------------------------------\n\n const fields = (parts: string[]): string => {\n const joined = parts.join(d.field);\n return trailing && joined.length > 0 ? `${joined}${d.field}` : joined;\n };\n\n const segment = (seg: Segment): string => {\n const body = fields(seg.children.map(field));\n if (!seg.name) {\n return body;\n }\n return body ? `${seg.name}${d.field}${body}` : seg.name;\n };\n\n // MSH-1 is the field separator itself — skip it and emit structurally.\n const msh = (seg: Segment): string => {\n const tail = fields(seg.children.slice(1).map(field));\n return tail.length ? `MSH${d.field}${tail}` : `MSH${d.field}`;\n };\n\n const root = (r: Root): string =>\n (r.children as Segment[])\n .map((seg) => (seg.name === \"MSH\" ? msh(seg) : segment(seg)))\n .join(d.segment);\n\n // -- dispatch ----------------------------------------------------------\n\n switch (node.type) {\n case \"root\": {\n return root(node);\n }\n case \"segment\": {\n return node.name === \"MSH\" ? msh(node) : segment(node);\n }\n case \"field\": {\n return field(node);\n }\n case \"field-repetition\": {\n return rep(node);\n }\n case \"component\": {\n return comp(node);\n }\n case \"subcomponent\": {\n return sub(node);\n }\n default: {\n // @ts-expect-error – ensure exhaustiveness\n (() => node satisfies never)();\n throw new Error(`Unsupported node type: ${(node as Node).type}`);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["queryDelimiters","delimiters"],"sources":["../../util-query/dist/index.js","../src/index.ts"],"sourcesContent":["import { DEFAULT_DELIMITERS } from \"@glion/utils\";\n//#region src/parse.ts\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 = /^((?:[A-Z][A-Z0-9]*(?:\\[\\d+\\])?-)*)([A-Z][A-Z0-9]*)(?:\\[(\\d+)\\])?(?:-(\\d+)(?:(?:\\[(\\d+)\\])?(?:\\.(\\d+)(?:\\.(\\d+))?)?)?)?$/;\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 = /* @__PURE__ */ new Map();\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 = {\n\t\"MSH-10\": {\n\t\tfield: 10,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-12\": {\n\t\tfield: 12,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-3\": {\n\t\tfield: 3,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-4\": {\n\t\tfield: 4,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-5\": {\n\t\tfield: 5,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-6\": {\n\t\tfield: 6,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-9\": {\n\t\tfield: 9,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-9.1\": {\n\t\tcomponent: 1,\n\t\tfield: 9,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-9.2\": {\n\t\tcomponent: 2,\n\t\tfield: 9,\n\t\tsegment: { name: \"MSH\" }\n\t},\n\t\"MSH-9.3\": {\n\t\tcomponent: 3,\n\t\tfield: 9,\n\t\tsegment: { name: \"MSH\" }\n\t}\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*/\nfunction parse(path) {\n\tconst hot = HOT_PATHS[path];\n\tif (hot) return hot;\n\tconst cached = parseCache.get(path);\n\tif (cached) return cached;\n\tconst result = parseImpl(path);\n\tparseCache.set(path, result);\n\treturn result;\n}\n/**\n* Internal implementation of path parsing.\n*/\nfunction parseImpl(path) {\n\tif (!path || typeof path !== \"string\") throw new Error(`Path must be a non-empty string, got: ${path}`);\n\tif (path.trim() !== path) throw new Error(`Path cannot contain leading/trailing spaces: \"${path}\"`);\n\tconst match = PATH_REGEX.exec(path);\n\tif (!match) throw new Error(`Invalid HL7 path format: \"${path}\". Expected [GROUP[N]-]...NAME[N][-FIELD[REPETITION][.COMPONENT[.SUBCOMPONENT]]].`);\n\tconst [, groupsRaw, segmentName, segmentRep, fieldStr, repetitionStr, componentStr, subcomponentStr] = match;\n\tif (!segmentName) throw new Error(`Path must include a segment identifier: \"${path}\"`);\n\tconst parts = { segment: { name: segmentName } };\n\tif (segmentRep) {\n\t\tconst repetition = Number.parseInt(segmentRep, 10);\n\t\tif (repetition < 1) throw new Error(`Segment repetition must be ≥1, got: ${segmentRep} in \"${path}\"`);\n\t\tparts.segment.repetition = repetition;\n\t}\n\tif (groupsRaw) {\n\t\tconst groups = [];\n\t\tfor (const groupMatch of groupsRaw.matchAll(/([A-Z][A-Z0-9]*)(?:\\[(\\d+)\\])?-/g)) {\n\t\t\tconst name = groupMatch[1];\n\t\t\tif (!name) continue;\n\t\t\tconst repStr = groupMatch[2];\n\t\t\tconst group = { name };\n\t\t\tif (repStr) {\n\t\t\t\tconst repetition = Number.parseInt(repStr, 10);\n\t\t\t\tif (repetition < 1) throw new Error(`Group repetition must be ≥1, got: ${repStr} in \"${path}\"`);\n\t\t\t\tgroup.repetition = repetition;\n\t\t\t}\n\t\t\tgroups.push(group);\n\t\t}\n\t\tif (groups.length > 0) parts.groups = groups;\n\t}\n\tif (fieldStr) {\n\t\tconst field = Number.parseInt(fieldStr, 10);\n\t\tif (field < 1) throw new Error(`Field number must be ≥1, got: ${fieldStr}`);\n\t\tparts.field = field;\n\t}\n\tif (repetitionStr) {\n\t\tconst repetition = Number.parseInt(repetitionStr, 10);\n\t\tif (repetition < 1) throw new Error(`Repetition number must be ≥1, got: ${repetitionStr}`);\n\t\tparts.repetition = repetition;\n\t}\n\tif (componentStr) {\n\t\tconst component = Number.parseInt(componentStr, 10);\n\t\tif (component < 1) throw new Error(`Component number must be ≥1, got: ${componentStr}`);\n\t\tparts.component = component;\n\t}\n\tif (subcomponentStr) {\n\t\tconst subcomponent = Number.parseInt(subcomponentStr, 10);\n\t\tif (subcomponent < 1) throw new Error(`Subcomponent number must be ≥1, got: ${subcomponentStr}`);\n\t\tparts.subcomponent = subcomponent;\n\t}\n\treturn parts;\n}\n//#endregion\n//#region src/utils.ts\nfunction locateSegmentOrGroup(root, parts) {\n\tconst ancestors = [root];\n\tconst scope = followGroups(root, parts.groups ?? [], ancestors);\n\tif (!scope) return null;\n\tconst targetName = parts.segment.name;\n\tconst targetRepetition = parts.segment.repetition;\n\tconst matchedSegments = collectSegments(scope, targetName, ancestors);\n\tif (matchedSegments.length > 0) {\n\t\tconst match = matchedSegments[(targetRepetition ?? 1) - 1];\n\t\tif (match) return [match.segment, match.ancestors];\n\t}\n\tconst matchedGroups = collectGroups(scope, targetName, ancestors);\n\tif (matchedGroups.length > 0) {\n\t\tconst match = matchedGroups[(targetRepetition ?? 1) - 1];\n\t\tif (match) return [match.group, match.ancestors];\n\t}\n\treturn null;\n}\nfunction locateSegment(root, parts) {\n\tconst ancestors = [root];\n\tconst scope = followGroups(root, parts.groups ?? [], ancestors);\n\tif (!scope) return null;\n\tconst matchedSegments = collectSegments(scope, parts.segment.name, ancestors);\n\tif (matchedSegments.length === 0) return null;\n\tconst match = matchedSegments[(parts.segment.repetition ?? 1) - 1];\n\tif (!match) return null;\n\treturn [match.segment, match.ancestors];\n}\nfunction followGroups(root, groups, ancestorChain) {\n\tlet children = filterSegmentsAndGroups(root.children);\n\tfor (const locator of groups) {\n\t\tconst matchedGroups = children.filter((node) => node.type === \"group\" && node.name === locator.name);\n\t\tif (matchedGroups.length === 0) return null;\n\t\tconst selected = matchedGroups[(locator.repetition ?? 1) - 1];\n\t\tif (!selected) return null;\n\t\tancestorChain.push(selected);\n\t\tchildren = filterSegmentsAndGroups(selected.children);\n\t}\n\treturn children;\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*/\nfunction collectAllScopes(root, groups) {\n\tif (groups.length === 0) return [{\n\t\tancestors: [root],\n\t\tscope: filterSegmentsAndGroups(root.children)\n\t}];\n\tconst results = [];\n\tconst firstLocator = groups[0];\n\tconst remainingGroups = groups.slice(1);\n\tif (!firstLocator) return [{\n\t\tancestors: [root],\n\t\tscope: filterSegmentsAndGroups(root.children)\n\t}];\n\tconst matchingGroups = filterSegmentsAndGroups(root.children).filter((node) => node.type === \"group\" && node.name === firstLocator.name);\n\tif (firstLocator.repetition !== void 0) {\n\t\tconst selected = matchingGroups[firstLocator.repetition - 1];\n\t\tif (!selected) return [];\n\t\tconst ancestors = [root, selected];\n\t\treturn collectAllScopesRecursive(selected.children, remainingGroups, ancestors);\n\t}\n\tfor (const group of matchingGroups) {\n\t\tconst ancestors = [root, group];\n\t\tconst subScopes = collectAllScopesRecursive(group.children, remainingGroups, ancestors);\n\t\tresults.push(...subScopes);\n\t}\n\treturn results;\n}\nfunction collectAllScopesRecursive(children, groups, ancestors) {\n\tif (groups.length === 0) return [{\n\t\tancestors,\n\t\tscope: filterSegmentsAndGroups(children)\n\t}];\n\tconst results = [];\n\tconst firstLocator = groups[0];\n\tconst remainingGroups = groups.slice(1);\n\tif (!firstLocator) return [{\n\t\tancestors,\n\t\tscope: filterSegmentsAndGroups(children)\n\t}];\n\tconst matchingGroups = filterSegmentsAndGroups(children).filter((node) => node.type === \"group\" && node.name === firstLocator.name);\n\tif (firstLocator.repetition !== void 0) {\n\t\tconst selected = matchingGroups[firstLocator.repetition - 1];\n\t\tif (!selected) return [];\n\t\tconst newAncestors = [...ancestors, selected];\n\t\treturn collectAllScopesRecursive(selected.children, remainingGroups, newAncestors);\n\t}\n\tfor (const group of matchingGroups) {\n\t\tconst newAncestors = [...ancestors, group];\n\t\tconst subScopes = collectAllScopesRecursive(group.children, remainingGroups, newAncestors);\n\t\tresults.push(...subScopes);\n\t}\n\treturn results;\n}\nfunction collectSegments(nodes, targetSegmentName, ancestors) {\n\tconst result = [];\n\tfor (const node of nodes) {\n\t\tif (node.type === \"segment\") {\n\t\t\tif (getSegmentName(node) === targetSegmentName) result.push({\n\t\t\t\tancestors: [...ancestors],\n\t\t\t\tsegment: node\n\t\t\t});\n\t\t}\n\t\tif (node.type === \"group\") {\n\t\t\tconst nextAncestors = [...ancestors, node];\n\t\t\tresult.push(...collectSegments(filterSegmentsAndGroups(node.children), targetSegmentName, nextAncestors));\n\t\t}\n\t}\n\treturn result;\n}\nfunction collectGroups(nodes, targetGroupName, ancestors) {\n\tconst result = [];\n\tfor (const node of nodes) {\n\t\tif (node.type === \"group\" && node.name === targetGroupName) result.push({\n\t\t\tancestors: [...ancestors],\n\t\t\tgroup: node\n\t\t});\n\t\tif (node.type === \"group\") {\n\t\t\tconst nextAncestors = [...ancestors, node];\n\t\t\tresult.push(...collectGroups(filterSegmentsAndGroups(node.children), targetGroupName, nextAncestors));\n\t\t}\n\t}\n\treturn result;\n}\nfunction locateField(segment, fieldNum, parentAncestors) {\n\tconst field = getFields(segment)[fieldNum - 1];\n\tif (!field) return null;\n\treturn [field, [...parentAncestors, segment]];\n}\nfunction locateRepetition(field, repetition, parentAncestors) {\n\tif (repetition < 1) return null;\n\tconst node = field.children?.[repetition - 1];\n\tif (!node) return null;\n\treturn [node, [...parentAncestors, field]];\n}\nfunction locateComponent(repetition, componentNum, parentAncestors) {\n\tif (componentNum < 1) return null;\n\tconst component = repetition.children?.[componentNum - 1];\n\tif (!component) return null;\n\treturn [component, [...parentAncestors, repetition]];\n}\nfunction locateSubcomponent(component, subcomponentNum, parentAncestors) {\n\tif (subcomponentNum < 1) return null;\n\tconst node = component.children?.[subcomponentNum - 1];\n\tif (!node) return null;\n\treturn [node, [...parentAncestors, component]];\n}\nfunction getSegmentName(segment) {\n\treturn segment.name;\n}\nfunction getFields(segment) {\n\treturn segment.children;\n}\nfunction filterSegmentsAndGroups(nodes) {\n\treturn nodes.filter((node) => node.type === \"segment\" || node.type === \"group\");\n}\n//#endregion\n//#region src/select.ts\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*/\nfunction select(root, path) {\n\tconst parts = parse(path);\n\tif (parts.field === void 0) {\n\t\tconst result = locateSegmentOrGroup(root, parts);\n\t\tif (!result) return null;\n\t\treturn {\n\t\t\tancestors: result[1],\n\t\t\tnode: result[0]\n\t\t};\n\t}\n\tconst segmentResult = locateSegment(root, parts);\n\tif (!segmentResult) return null;\n\tconst [segment, segmentAncestors] = segmentResult;\n\tconst fieldResult = locateField(segment, parts.field, segmentAncestors);\n\tif (!fieldResult) return null;\n\tconst [field, fieldAncestors] = fieldResult;\n\tif (parts.component === void 0 && parts.subcomponent === void 0 && parts.repetition === void 0) return {\n\t\tancestors: fieldAncestors,\n\t\tnode: field\n\t};\n\tconst repetitionResult = locateRepetition(field, parts.repetition ?? 1, fieldAncestors);\n\tif (!repetitionResult) return null;\n\tconst [repetitionNode, repetitionAncestors] = repetitionResult;\n\tif (parts.component === void 0) return {\n\t\tancestors: repetitionAncestors,\n\t\tnode: repetitionNode\n\t};\n\tconst componentResult = locateComponent(repetitionNode, parts.component, repetitionAncestors);\n\tif (!componentResult) return null;\n\tconst [componentNode, componentAncestors] = componentResult;\n\tif (parts.subcomponent === void 0) return {\n\t\tancestors: componentAncestors,\n\t\tnode: componentNode\n\t};\n\tconst subResult = locateSubcomponent(componentNode, parts.subcomponent, componentAncestors);\n\tif (!subResult) return null;\n\treturn {\n\t\tancestors: subResult[1],\n\t\tnode: subResult[0]\n\t};\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*/\nfunction selectAll(root, path) {\n\tconst parts = parse(path);\n\tif (parts.segment.repetition !== void 0 || parts.repetition !== void 0) {\n\t\tconst result = select(root, path);\n\t\treturn result ? [result] : [];\n\t}\n\tconst results = [];\n\tconst scopes = collectAllScopes(root, parts.groups ?? []);\n\tconst segments = [];\n\tconst includeGroups = parts.field === void 0;\n\tconst groups = [];\n\tfor (const { scope, ancestors } of scopes) {\n\t\tconst matchingSegments = collectSegments(scope, parts.segment.name, ancestors);\n\t\tsegments.push(...matchingSegments);\n\t\tif (includeGroups) {\n\t\t\tconst matchingGroups = collectGroups(scope, parts.segment.name, ancestors);\n\t\t\tfor (const { group, ancestors: groupAncestors } of matchingGroups) groups.push({\n\t\t\t\tancestors: groupAncestors,\n\t\t\t\tgroup\n\t\t\t});\n\t\t}\n\t}\n\tif (parts.field === void 0) {\n\t\tfor (const { segment, ancestors } of segments) results.push({\n\t\t\tancestors,\n\t\t\tnode: segment\n\t\t});\n\t\tfor (const { group, ancestors } of groups) results.push({\n\t\t\tancestors,\n\t\t\tnode: group\n\t\t});\n\t\treturn results;\n\t}\n\tfor (const { segment, ancestors: segmentAncestors } of segments) {\n\t\tconst fieldResult = locateField(segment, parts.field, segmentAncestors);\n\t\tif (!fieldResult) continue;\n\t\tconst [field, fieldAncestors] = fieldResult;\n\t\tif (parts.component === void 0 && parts.subcomponent === void 0 && parts.repetition === void 0) {\n\t\t\tresults.push({\n\t\t\t\tancestors: fieldAncestors,\n\t\t\t\tnode: field\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (!field.children) continue;\n\t\tfor (const repetitionNode of field.children) {\n\t\t\tconst repetitionAncestors = [...fieldAncestors, field];\n\t\t\tif (parts.component === void 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\tancestors: repetitionAncestors,\n\t\t\t\t\tnode: repetitionNode\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst componentResult = locateComponent(repetitionNode, parts.component, repetitionAncestors);\n\t\t\tif (!componentResult) continue;\n\t\t\tconst [componentNode, componentAncestors] = componentResult;\n\t\t\tif (parts.subcomponent === void 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\tancestors: componentAncestors,\n\t\t\t\t\tnode: componentNode\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst subResult = locateSubcomponent(componentNode, parts.subcomponent, componentAncestors);\n\t\t\tif (subResult) results.push({\n\t\t\t\tancestors: subResult[1],\n\t\t\t\tnode: subResult[0]\n\t\t\t});\n\t\t}\n\t}\n\treturn results;\n}\n//#endregion\n//#region src/value.ts\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*/\nfunction value(root, path) {\n\tconst selectResult = select(root, path);\n\tif (!selectResult) return null;\n\tlet { node } = selectResult;\n\tlet { ancestors } = selectResult;\n\twhile (node.type !== \"subcomponent\") {\n\t\tif (node.type === \"segment\" || node.type === \"group\" || node.type === \"root\") return null;\n\t\tif (!(\"children\" in node && node.children)) return null;\n\t\tif (node.children.length === 0) return {\n\t\t\tancestors: [...ancestors],\n\t\t\tnode,\n\t\t\tvalue: null\n\t\t};\n\t\tconst next = node.children[0];\n\t\tif (!next) return null;\n\t\tancestors = [...ancestors, node];\n\t\tnode = next;\n\t}\n\treturn {\n\t\tancestors,\n\t\tnode,\n\t\tvalue: node.value\n\t};\n}\n//#endregion\n//#region src/delimiters.ts\n/** Keys of MSH-2 encoding characters in positional order. */\nconst MSH2_KEYS = [\n\t\"component\",\n\t\"repetition\",\n\t\"escape\",\n\t\"subcomponent\"\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*/\nfunction delimiters(root) {\n\tconst result = { ...DEFAULT_DELIMITERS };\n\tconst msh1 = value(root, \"MSH-1\")?.value;\n\tif (msh1 && msh1.length === 1) result.field = msh1;\n\tconst msh2 = value(root, \"MSH-2\")?.value;\n\tif (msh2) {\n\t\tconst chars = [...msh2];\n\t\tfor (const [i, key] of MSH2_KEYS.entries()) {\n\t\t\tconst ch = chars[i];\n\t\t\tif (ch) result[key] = ch;\n\t\t}\n\t}\n\treturn result;\n}\n//#endregion\n//#region src/format.ts\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*/\nfunction format(node, ancestors) {\n\tlet result = null;\n\tconst chain = [...ancestors, node];\n\tfor (const [i, current] of chain.entries()) {\n\t\tconst parent = chain[i - 1];\n\t\tswitch (current.type) {\n\t\t\tcase \"root\": break;\n\t\t\tcase \"group\":\n\t\t\tcase \"segment\": {\n\t\t\t\tconst pos = positionOf(current, parent);\n\t\t\t\tresult = (result ?? \"\") + current.name;\n\t\t\t\tif (pos > 1) result += `[${pos}]`;\n\t\t\t\tif (current.type === \"group\" && current !== node) result += \"-\";\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"field\":\n\t\t\t\tresult += `-${positionOf(current, parent)}`;\n\t\t\t\tbreak;\n\t\t\tcase \"field-repetition\": {\n\t\t\t\tconst pos = positionOf(current, parent);\n\t\t\t\tif (pos > 1 || current === node) result += `[${pos}]`;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"component\":\n\t\t\t\tresult += `.${positionOf(current, parent)}`;\n\t\t\t\tbreak;\n\t\t\tcase \"subcomponent\":\n\t\t\t\tresult += `.${positionOf(current, parent)}`;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn result;\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, parent) {\n\tif (!parent || !(\"children\" in parent)) return 1;\n\tconst children = parent.children;\n\tif (\"name\" in node) {\n\t\tconst name = node.name;\n\t\tconst { type } = node;\n\t\tlet count = 0;\n\t\tfor (const child of children) {\n\t\t\tif (child === node) return count + 1;\n\t\t\tif (child.type === type && \"name\" in child && child.name === name) count++;\n\t\t}\n\t\tthrow new Error(\"format(): node not found in parent's children array\");\n\t}\n\tconst idx = children.indexOf(node);\n\tif (idx === -1) throw new Error(\"format(): node not found in parent's children array\");\n\treturn idx + 1;\n}\n//#endregion\n//#region src/matches.ts\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*/\nfunction matches(root, path) {\n\treturn select(root, path) !== null;\n}\n//#endregion\n//#region src/set.ts\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*/\nfunction set(root, path, val) {\n\tconst parts = parse(path);\n\tif (parts.field === void 0) throw new Error(`Cannot set value on segment-only path: \"${path}\"`);\n\tconst segmentResult = locateSegment(root, parts);\n\tif (!segmentResult) throw new Error(`Segment \"${parts.segment.name}\" not found in tree`);\n\tconst [segment] = segmentResult;\n\tconst fieldIndex = parts.field - 1;\n\tpadArray(segment.children, fieldIndex + 1, stubField);\n\tconst field = segment.children[fieldIndex];\n\tconst repIndex = (parts.repetition ?? 1) - 1;\n\tpadArray(field.children, repIndex + 1, stubRepetition);\n\tconst repetition = field.children[repIndex];\n\tconst compIndex = (parts.component ?? 1) - 1;\n\tpadArray(repetition.children, compIndex + 1, stubComponent);\n\tconst component = repetition.children[compIndex];\n\tconst subIndex = (parts.subcomponent ?? 1) - 1;\n\tpadArray(component.children, subIndex + 1, stubSubcomponent);\n\tcomponent.children[subIndex].value = val;\n}\n/**\n* Pad an array to a target length using a factory function.\n*/\nfunction padArray(arr, targetLength, factory) {\n\twhile (arr.length < targetLength) arr.push(factory());\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*/\nfunction stubField() {\n\treturn {\n\t\tchildren: [],\n\t\ttype: \"field\"\n\t};\n}\nfunction stubRepetition() {\n\treturn {\n\t\tchildren: [],\n\t\ttype: \"field-repetition\"\n\t};\n}\nfunction stubComponent() {\n\treturn {\n\t\tchildren: [],\n\t\ttype: \"component\"\n\t};\n}\nfunction stubSubcomponent() {\n\treturn {\n\t\ttype: \"subcomponent\",\n\t\tvalue: \"\"\n\t};\n}\n//#endregion\nexport { delimiters, format, matches, parse, select, selectAll, set, value };\n\n//# sourceMappingURL=index.js.map","import type {\n Component,\n Delimiters,\n Field,\n FieldRepetition,\n Nodes,\n Root,\n Segment,\n Subcomponent,\n} from \"@glion/ast\";\nimport { delimiters as queryDelimiters } from \"@glion/util-query\";\nimport { DEFAULT_DELIMITERS } from \"@glion/utils\";\nimport type { Plugin } from \"unified\";\nimport type { Node } from \"unist\";\nimport type { VFile } from \"vfile\";\n\nexport interface Hl7v2ToHl7v2Options {\n /** Append a field delimiter after the last field in each segment. */\n trailingDelimiter?: boolean;\n}\n\n/**\n * Unified compiler plugin: HL7v2 AST → HL7v2 string.\n *\n * Reads `file.data.delimiters` if set by hl7v2-annotate-delimiters,\n * otherwise derives from MSH-1/MSH-2 via `delimiters()` for standalone use.\n */\nexport const hl7v2ToHl7v2: Plugin<[Hl7v2ToHl7v2Options?], Root, string> =\n function hl7v2ToHl7v2(options?: Hl7v2ToHl7v2Options): void {\n // biome-ignore lint/complexity/noUselessThisAlias: unified plugin shape\n const self = this;\n self.compiler = (tree: Node, file: VFile): string =>\n toHl7v2(\n tree as Nodes,\n file.data.delimiters as Delimiters | undefined,\n options\n );\n };\n\n/**\n * Serialize an HL7v2 AST node back to its wire format.\n *\n * Works on any node in the tree — a full Root, a single Segment, or\n * even a lone Field. Delimiters default to the standard set unless\n * overridden or derivable from an MSH segment in the tree.\n */\nexport function toHl7v2(\n node: Nodes,\n delimiters?: Partial<Delimiters>,\n options?: Hl7v2ToHl7v2Options\n): string {\n const d = {\n ...(node.type === \"root\" ? queryDelimiters(node) : DEFAULT_DELIMITERS),\n ...delimiters,\n };\n const trailing = options?.trailingDelimiter === true;\n\n // -- leaf & field-level serializers (no options needed) ----------------\n\n const sub = (s: Subcomponent): string => s.value ?? \"\";\n\n const comp = (c: Component): string =>\n ((c.children || []) as Subcomponent[]).map(sub).join(d.subcomponent);\n\n const rep = (r: FieldRepetition): string =>\n (r.children as Component[]).map(comp).join(d.component);\n\n const field = (f: Field): string =>\n (f.children as FieldRepetition[]).map(rep).join(d.repetition);\n\n // -- segment-level serializers ----------------------------------------\n\n const fields = (parts: string[]): string => {\n const joined = parts.join(d.field);\n return trailing && joined.length > 0 ? `${joined}${d.field}` : joined;\n };\n\n const segment = (seg: Segment): string => {\n const body = fields(seg.children.map(field));\n if (!seg.name) {\n return body;\n }\n return body ? `${seg.name}${d.field}${body}` : seg.name;\n };\n\n // MSH-1 is the field separator itself — skip it and emit structurally.\n const msh = (seg: Segment): string => {\n const tail = fields(seg.children.slice(1).map(field));\n return tail.length ? `MSH${d.field}${tail}` : `MSH${d.field}`;\n };\n\n const root = (r: Root): string =>\n (r.children as Segment[])\n .map((seg) => (seg.name === \"MSH\" ? msh(seg) : segment(seg)))\n .join(d.segment);\n\n // -- dispatch ----------------------------------------------------------\n\n switch (node.type) {\n case \"root\": {\n return root(node);\n }\n case \"segment\": {\n return node.name === \"MSH\" ? msh(node) : segment(node);\n }\n case \"field\": {\n return field(node);\n }\n case \"field-repetition\": {\n return rep(node);\n }\n case \"component\": {\n return comp(node);\n }\n case \"subcomponent\": {\n return sub(node);\n }\n default: {\n // @ts-expect-error – ensure exhaustiveness\n (() => node satisfies never)();\n throw new Error(`Unsupported node type: ${(node as Node).type}`);\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glion/to-hl7v2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "hl7v2 plugin to transform hl7v2 messages to a hl7v2. Useful for sanitizing messages.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"health",
|
|
@@ -36,31 +36,31 @@
|
|
|
36
36
|
"unified": "11.0.5",
|
|
37
37
|
"unist-util-visit": "5.1.0",
|
|
38
38
|
"unist-util-visit-parents": "6.0.2",
|
|
39
|
-
"@glion/utils": "0.
|
|
39
|
+
"@glion/utils": "0.19.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "25.6.0",
|
|
43
43
|
"@types/unist": "^3.0.3",
|
|
44
|
-
"@vitest/coverage-v8": "4.1.
|
|
44
|
+
"@vitest/coverage-v8": "4.1.11",
|
|
45
45
|
"publint": "0.3.18",
|
|
46
46
|
"tsdown": "0.21.10",
|
|
47
47
|
"typescript": "6.0.3",
|
|
48
48
|
"unist-builder": "^4.0.0",
|
|
49
49
|
"vfile": "^6.0.3",
|
|
50
|
-
"vitest": "4.1.
|
|
51
|
-
"@glion/ast": "0.
|
|
52
|
-
"@glion/
|
|
53
|
-
"@glion/
|
|
54
|
-
"@glion/testing": "0.
|
|
55
|
-
"@glion/
|
|
56
|
-
"@glion/
|
|
50
|
+
"vitest": "4.1.11",
|
|
51
|
+
"@glion/ast": "0.19.0",
|
|
52
|
+
"@glion/builder": "0.19.0",
|
|
53
|
+
"@glion/check-readme": "0.18.0",
|
|
54
|
+
"@glion/testing": "0.18.0",
|
|
55
|
+
"@glion/tsconfig": "0.18.0",
|
|
56
|
+
"@glion/util-query": "0.19.0"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
|
-
"node": ">=
|
|
59
|
+
"node": ">=22"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "tsdown && tsc --emitDeclarationOnly",
|
|
63
|
-
"check-types": "tsc --noEmit",
|
|
63
|
+
"check-types": "tsc --noEmit && tsc --noEmit -p tests/tsconfig.json",
|
|
64
64
|
"check:readme": "glion-check-readme",
|
|
65
65
|
"test": "vitest run",
|
|
66
66
|
"test:coverage": "vitest run --coverage",
|