@glion/util-visit 0.22.0 → 0.23.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 +20 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -49
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +6 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +31 -10
- package/dist/utils.d.ts.map +1 -1
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Visitor for traversing HL7v2 AST trees with ancestor context, depth, and HL7v2-a
|
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
7
|
-
Walks an HL7v2 AST from any starting node — Root, Segment, Field, Component, or Subcomponent — calling a visitor function for each matching node. Each call receives the node, its ancestors (root-to-parent), and a `VisitInfo` record with index, HL7v2 sequence number, depth, and extracted metadata. Supports filtering by type string, property object, or predicate, and exposes `SKIP`/`EXIT` control actions. Delegates core traversal to `unist-util-visit-parents
|
|
7
|
+
Walks an HL7v2 AST from any starting node — Root, Segment, Field, Component, or Subcomponent — calling a visitor function for each matching node. Each call receives the node, its ancestors (root-to-parent), and a `VisitInfo` record with index, HL7v2 sequence number, depth, and extracted metadata. Supports filtering by type string, property object, or predicate, and exposes `SKIP`/`EXIT` control actions. Delegates core traversal to `unist-util-visit-parents`.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -52,7 +52,7 @@ Visit nodes in an HL7v2 AST tree.
|
|
|
52
52
|
- `tree` (`Nodes`) — Tree to traverse. Can be any node type, not just `Root`.
|
|
53
53
|
- `test` (`string | Partial<Nodes> | Test`, optional) — Filter:
|
|
54
54
|
- `string` — Match nodes by type (e.g., `"segment"`).
|
|
55
|
-
- `Partial<Nodes>` — Match nodes
|
|
55
|
+
- `Partial<Nodes>` — Match nodes whose own properties equal (`===`) each value (e.g., `{ name: "PATIENT_GROUP" }`). A property the node does not own reads as `undefined`: an `undefined` value matches an absent property, and a key naming an inherited member (`constructor`, `toString`) matches no node.
|
|
56
56
|
- `Test` — Custom function `(node, ancestors) => boolean`.
|
|
57
57
|
- `visitor` (`Visitor`) — Function called for each matching node.
|
|
58
58
|
|
|
@@ -105,16 +105,16 @@ The visitor can return:
|
|
|
105
105
|
|
|
106
106
|
```typescript
|
|
107
107
|
interface VisitInfo {
|
|
108
|
-
/** 0-based index among
|
|
108
|
+
/** 0-based index among the parent's children when the node is visited */
|
|
109
109
|
index: number;
|
|
110
110
|
|
|
111
|
-
/** 1
|
|
111
|
+
/** `index` + 1, the HL7v2 sequence number */
|
|
112
112
|
sequence: number;
|
|
113
113
|
|
|
114
114
|
/** 1-based depth in tree (root = 1) */
|
|
115
115
|
depth: number;
|
|
116
116
|
|
|
117
|
-
/** Metadata (e.g., {
|
|
117
|
+
/** Metadata (e.g., { name: "MSH" } or { name: "PATIENT" }) */
|
|
118
118
|
metadata: Record<string, unknown> | undefined;
|
|
119
119
|
}
|
|
120
120
|
```
|
|
@@ -135,6 +135,17 @@ visit(
|
|
|
135
135
|
|
|
136
136
|
This is correct because HL7v2 paths like `PID.3` refer to tree positions, not filtered positions.
|
|
137
137
|
|
|
138
|
+
The position is read when the node is visited, so it reflects siblings a visitor inserted or removed earlier in the same visit. A visitor that removes the current node can return `info.index` to continue with the sibling that moved into its place:
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
visit(segment, "field", (node, ancestors, info) => {
|
|
142
|
+
if (isEmptyNode(node)) {
|
|
143
|
+
ancestors.at(-1).children.splice(info.index, 1);
|
|
144
|
+
return info.index;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
138
149
|
### Automatic metadata extraction
|
|
139
150
|
|
|
140
151
|
The `metadata` field is populated automatically:
|
|
@@ -319,12 +330,14 @@ function extractPatientNames(ast: Root): PatientName[] {
|
|
|
319
330
|
if (nameField?.children[0]?.children[0]) {
|
|
320
331
|
const nameComponent = nameField.children[0].children[0];
|
|
321
332
|
const name = (nameComponent.children[0] as Subcomponent)?.value || "";
|
|
322
|
-
const groupAncestor = ancestors.find(
|
|
333
|
+
const groupAncestor = ancestors.find(
|
|
334
|
+
(n): n is Group => n.type === "group"
|
|
335
|
+
);
|
|
323
336
|
|
|
324
337
|
names.push({
|
|
325
338
|
name,
|
|
326
339
|
sequence: info.sequence,
|
|
327
|
-
inGroup: groupAncestor
|
|
340
|
+
inGroup: groupAncestor?.name,
|
|
328
341
|
});
|
|
329
342
|
}
|
|
330
343
|
});
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC,OAAO,KAAK,EAAE,IAAI,EAAa,OAAO,EAAE,MAAM,SAAS,CAAC;AAGxD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC,OAAO,KAAK,EAAE,IAAI,EAAa,OAAO,EAAE,MAAM,SAAS,CAAC;AAGxD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEtD,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGnE,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;AAC3D,wBAAgB,KAAK,CAAC,IAAI,SAAS,KAAK,CAAC,MAAM,CAAC,EAC9C,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC,GAC/C,IAAI,CAAC;AACR,wBAAgB,KAAK,CAAC,CAAC,SAAS,KAAK,EACnC,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EACb,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,IAAI,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,60 +1,51 @@
|
|
|
1
1
|
import { EXIT, SKIP, visitParents } from "unist-util-visit-parents";
|
|
2
2
|
//#region src/utils.ts
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* The predicate a `visit` test describes.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* - `null` matches every node.
|
|
7
|
+
* - A string matches nodes whose `type` equals it.
|
|
8
|
+
* - A function is the predicate.
|
|
9
|
+
* - An object matches nodes whose own property equals (`===`) each of its values.
|
|
10
|
+
* A property the node does not own reads as `undefined`, so an `undefined`
|
|
11
|
+
* value matches an absent property, and a key that names an inherited member
|
|
12
|
+
* (`constructor`, `toString`, an own `__proto__`) matches no node. The
|
|
13
|
+
* object's entries are read once, when the predicate is created.
|
|
7
14
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* - Explicit undefined values in test object check for property absence
|
|
12
|
-
* - Dangerous keys (**proto**, constructor, prototype) are filtered for security
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const msh = s("MSH", f("|"));
|
|
13
18
|
*
|
|
14
|
-
*
|
|
15
|
-
* (
|
|
16
|
-
*
|
|
19
|
+
* createTest(null)(msh, []); // true
|
|
20
|
+
* createTest("segment")(msh, []); // true
|
|
21
|
+
* createTest("field")(msh, []); // false
|
|
22
|
+
*
|
|
23
|
+
* createTest({ type: "segment", name: "MSH" })(msh, []); // true
|
|
24
|
+
* createTest({ name: "PID" })(msh, []); // false
|
|
25
|
+
*
|
|
26
|
+
* // `undefined` matches a property the node does not have
|
|
27
|
+
* createTest({ name: undefined })(f("|"), []); // true
|
|
28
|
+
*
|
|
29
|
+
* // An inherited member is never matched
|
|
30
|
+
* createTest({ constructor: Object })(msh, []); // false
|
|
31
|
+
*
|
|
32
|
+
* // A function receives the ancestors as well
|
|
33
|
+
* const inGroup = createTest((_node, ancestors) => ancestors.length > 1);
|
|
34
|
+
* ```;
|
|
35
|
+
*
|
|
36
|
+
* @param test - `null`, a node type, a property object, or a predicate.
|
|
37
|
+
* @returns The predicate.
|
|
17
38
|
*/
|
|
18
39
|
function createTest(test) {
|
|
19
40
|
if (test === null) return () => true;
|
|
20
41
|
if (typeof test === "string") return (node) => node.type === test;
|
|
21
42
|
if (typeof test === "function") return test;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
25
|
-
const testValue = test[key];
|
|
26
|
-
const nodeValue = node[key];
|
|
27
|
-
if (testValue === void 0) {
|
|
28
|
-
if (Object.hasOwn(node, key) && nodeValue !== void 0) return false;
|
|
29
|
-
} else if (nodeValue !== testValue) return false;
|
|
30
|
-
}
|
|
31
|
-
return true;
|
|
32
|
-
};
|
|
43
|
+
const entries = Object.entries(test);
|
|
44
|
+
return (node) => entries.every(([key, value]) => (Object.hasOwn(node, key) ? Reflect.get(node, key) : void 0) === value);
|
|
33
45
|
}
|
|
34
46
|
//#endregion
|
|
35
47
|
//#region src/index.ts
|
|
36
48
|
/**
|
|
37
|
-
* Build index map for O(1) child index lookups.
|
|
38
|
-
* Pre-computes the index of each node within its parent's children array.
|
|
39
|
-
*
|
|
40
|
-
* @param tree - Root of tree to index
|
|
41
|
-
* @returns WeakMap mapping each node to its index in parent.children
|
|
42
|
-
*/
|
|
43
|
-
function buildIndexMap(tree) {
|
|
44
|
-
const map = /* @__PURE__ */ new WeakMap();
|
|
45
|
-
function traverse(node) {
|
|
46
|
-
if ("children" in node && Array.isArray(node.children)) for (let i = 0; i < node.children.length; i++) {
|
|
47
|
-
const child = node.children[i];
|
|
48
|
-
if (child) {
|
|
49
|
-
map.set(child, i);
|
|
50
|
-
traverse(child);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
traverse(tree);
|
|
55
|
-
return map;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
49
|
* Visit nodes in an HL7 AST tree.
|
|
59
50
|
* Wraps unist-util-visit-parents to add HL7v2-specific context.
|
|
60
51
|
*
|
|
@@ -77,16 +68,18 @@ function visit(tree, arg2, arg3) {
|
|
|
77
68
|
visitor = arg3;
|
|
78
69
|
}
|
|
79
70
|
const predicate = createTest(test);
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
let currentIndex = 0;
|
|
72
|
+
const captureIndex = (_node, index) => {
|
|
73
|
+
currentIndex = index ?? 0;
|
|
74
|
+
return true;
|
|
75
|
+
};
|
|
76
|
+
visitParents(tree, captureIndex, (node, ancestors) => {
|
|
82
77
|
if (!predicate(node, ancestors)) return;
|
|
83
|
-
const parent = ancestors.at(-1);
|
|
84
|
-
const childIndex = parent ? indexMap.get(node) ?? 0 : 0;
|
|
85
78
|
const info = {
|
|
86
79
|
depth: ancestors.length + 1,
|
|
87
|
-
index:
|
|
88
|
-
metadata: "name" in node
|
|
89
|
-
sequence:
|
|
80
|
+
index: currentIndex,
|
|
81
|
+
metadata: "name" in node ? { name: node.name } : void 0,
|
|
82
|
+
sequence: currentIndex + 1
|
|
90
83
|
};
|
|
91
84
|
return visitor(node, ancestors, info);
|
|
92
85
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/utils.ts","../src/index.ts"],"sourcesContent":["import type { Nodes } from \"@glion/ast\";\n\nimport type { Predicate, Test } from \"./types\";\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/utils.ts","../src/index.ts"],"sourcesContent":["import type { Nodes } from \"@glion/ast\";\n\nimport type { Predicate, Test } from \"./types\";\n\n/**\n * The predicate a `visit` test describes.\n *\n * - `null` matches every node.\n * - A string matches nodes whose `type` equals it.\n * - A function is the predicate.\n * - An object matches nodes whose own property equals (`===`) each of its values.\n * A property the node does not own reads as `undefined`, so an `undefined`\n * value matches an absent property, and a key that names an inherited member\n * (`constructor`, `toString`, an own `__proto__`) matches no node. The\n * object's entries are read once, when the predicate is created.\n *\n * @example\n * ```typescript\n * const msh = s(\"MSH\", f(\"|\"));\n *\n * createTest(null)(msh, []); // true\n * createTest(\"segment\")(msh, []); // true\n * createTest(\"field\")(msh, []); // false\n *\n * createTest({ type: \"segment\", name: \"MSH\" })(msh, []); // true\n * createTest({ name: \"PID\" })(msh, []); // false\n *\n * // `undefined` matches a property the node does not have\n * createTest({ name: undefined })(f(\"|\"), []); // true\n *\n * // An inherited member is never matched\n * createTest({ constructor: Object })(msh, []); // false\n *\n * // A function receives the ancestors as well\n * const inGroup = createTest((_node, ancestors) => ancestors.length > 1);\n * ```;\n *\n * @param test - `null`, a node type, a property object, or a predicate.\n * @returns The predicate.\n */\nexport function createTest(test: Test<Nodes>): Predicate {\n if (test === null) {\n return () => true;\n }\n if (typeof test === \"string\") {\n return (node) => node.type === test;\n }\n if (typeof test === \"function\") {\n // Used as is: `visit` calls it with `(node, ancestors)`, so it may match on\n // a node's position in the tree as well as on the node itself.\n return test;\n }\n\n // Read once here rather than per visited node: a visit calls the predicate\n // for every node, and a test object changed during the visit does not change\n // which nodes match.\n const entries = Object.entries(test);\n\n return (node) =>\n entries.every(\n ([key, value]) =>\n // `Object.hasOwn` limits the match to the node's own properties. Without\n // it, `node[key]` also finds inherited members, so `{ constructor: x }`\n // or `{ toString: x }` would be compared against `Object.prototype`.\n // `Reflect.get(node, key)` is `node[key]`; it compiles for an arbitrary\n // string key, which `Nodes` (no index signature) does not allow.\n (Object.hasOwn(node, key) ? Reflect.get(node, key) : undefined) ===\n value\n );\n}\n","/**\n * HL7v2 AST Visitor\n *\n * Wraps unist-util-visit-parents to add HL7v2-specific context\n * (index, sequence, depth, metadata) while delegating core traversal.\n */\n\nimport type { Nodes } from \"@glion/ast\";\nimport { visitParents } from \"unist-util-visit-parents\";\n\nimport type { Test, VisitInfo, Visitor } from \"./types\";\nimport { createTest } from \"./utils\";\n\nexport type { VisitorResult } from \"unist-util-visit-parents\";\n\nexport { EXIT, SKIP } from \"unist-util-visit-parents\";\n\nexport type { Predicate, Test, VisitInfo, Visitor } from \"./types\";\n\n// Overload signatures\nexport function visit(tree: Nodes, visitor: Visitor): void;\nexport function visit<Type extends Nodes[\"type\"]>(\n tree: Nodes,\n test: Type,\n visitor: Visitor<Extract<Nodes, { type: Type }>>\n): void;\nexport function visit<T extends Nodes>(\n tree: Nodes,\n test: Test<T>,\n visitor: Visitor<T>\n): void;\n\n/**\n * Visit nodes in an HL7 AST tree.\n * Wraps unist-util-visit-parents to add HL7v2-specific context.\n *\n * @param tree - The tree to traverse (can be any node type, not just Root)\n * @param test - Optional test to filter nodes (type string, partial match, or\n * Test function)\n * @param visitor - Function called for each matching node\n *\n * **Important**: If you pass a function as the second argument, it is always\n * treated as a Visitor, never as a Test. To use a Test function, you MUST\n * provide both the test and visitor parameters: `visit(tree, testFn,\n * visitorFn)`.\n */\nexport function visit<T extends Nodes>(\n tree: Nodes,\n arg2: Visitor<T> | Test<T>,\n arg3?: Visitor<T>\n): void {\n let test: Test<T> = null;\n let visitor: Visitor<T>;\n\n if (arg3 === undefined) {\n visitor = arg2 as Visitor<T>;\n } else {\n test = arg2 as Test<T>;\n visitor = arg3;\n }\n\n const predicate = createTest(test as Test<Nodes>);\n\n // visit-parents passes a node's index among its parent's children only to\n // its test, `test(node, index, parent)`, never to its visitor. It calls the\n // test and, when the test passes, the visitor on that same node with nothing\n // in between (unist-util-visit-parents 6.0.2, lib/index.js; the version is\n // pinned). `captureIndex` is that test: it stores the index for the visitor\n // to read and passes every node. The index is the node's position when it\n // is visited, so it reflects siblings a visitor inserted or removed earlier.\n let currentIndex = 0;\n const captureIndex = (_node: unknown, index?: number): boolean => {\n // The node `visit` starts from has no parent, so it has no index.\n currentIndex = index ?? 0;\n return true;\n };\n\n visitParents(tree, captureIndex, (node, ancestors) => {\n // The caller's test runs here, not in `captureIndex`: it may read\n // `ancestors`, which visit-parents gives only to the visitor.\n if (!predicate(node, ancestors)) {\n // Returning nothing means \"continue\": visit-parents still walks into\n // this node's children, so `visit(tree, \"field\", …)` reaches the fields\n // of segments it does not match.\n return;\n }\n\n const info: VisitInfo = {\n depth: ancestors.length + 1,\n index: currentIndex,\n metadata: \"name\" in node ? { name: node.name } : undefined,\n sequence: currentIndex + 1,\n };\n\n // visit-parents reads the visitor's return value to decide what to visit\n // next, so the caller's result is passed through unchanged:\n // - nothing or CONTINUE: walk into this node's children;\n // - SKIP: skip this node's children;\n // - EXIT: stop the walk;\n // - a number: continue at that index among this node's siblings, as after\n // removing the current node with `splice(info.index, 1)`;\n // - [action, index]: both.\n // Calling the visitor without returning its result would turn every one\n // of these into \"continue\".\n return visitor(node as T, ancestors, info);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,WAAW,MAA8B;AACvD,KAAI,SAAS,KACX,cAAa;AAEf,KAAI,OAAO,SAAS,SAClB,SAAQ,SAAS,KAAK,SAAS;AAEjC,KAAI,OAAO,SAAS,WAGlB,QAAO;CAMT,MAAM,UAAU,OAAO,QAAQ,KAAK;AAEpC,SAAQ,SACN,QAAQ,OACL,CAAC,KAAK,YAMJ,OAAO,OAAO,MAAM,IAAI,GAAG,QAAQ,IAAI,MAAM,IAAI,GAAG,KAAA,OACrD,MACH;;;;;;;;;;;;;;;;;;ACtBL,SAAgB,MACd,MACA,MACA,MACM;CACN,IAAI,OAAgB;CACpB,IAAI;AAEJ,KAAI,SAAS,KAAA,EACX,WAAU;MACL;AACL,SAAO;AACP,YAAU;;CAGZ,MAAM,YAAY,WAAW,KAAoB;CASjD,IAAI,eAAe;CACnB,MAAM,gBAAgB,OAAgB,UAA4B;AAEhE,iBAAe,SAAS;AACxB,SAAO;;AAGT,cAAa,MAAM,eAAe,MAAM,cAAc;AAGpD,MAAI,CAAC,UAAU,MAAM,UAAU,CAI7B;EAGF,MAAM,OAAkB;GACtB,OAAO,UAAU,SAAS;GAC1B,OAAO;GACP,UAAU,UAAU,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,KAAA;GACjD,UAAU,eAAe;GAC1B;AAYD,SAAO,QAAQ,MAAW,WAAW,KAAK;GAC1C"}
|
package/dist/types.d.ts
CHANGED
|
@@ -5,9 +5,13 @@ import type { VisitorResult } from "unist-util-visit-parents";
|
|
|
5
5
|
* This is HL7v2-specific context not provided by unist-util-visit-parents.
|
|
6
6
|
*/
|
|
7
7
|
export interface VisitInfo {
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* 0-based index among the parent's children when the node is visited, or 0
|
|
10
|
+
* for the node the visit starts from. Reflects changes a visitor made to
|
|
11
|
+
* those children earlier in the same visit.
|
|
12
|
+
*/
|
|
9
13
|
index: number;
|
|
10
|
-
/** 1
|
|
14
|
+
/** `index` + 1, the HL7v2 sequence number. */
|
|
11
15
|
sequence: number;
|
|
12
16
|
/** 1-based depth in tree (root = 1) */
|
|
13
17
|
depth: number;
|
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,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IAEjB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IAEd,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC/C;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,IAAI,CAC7C,IAAI,EAAE,CAAC,EACP,SAAS,EAAE,KAAK,EAAE,EAClB,IAAI,EAAE,SAAS,KACZ,aAAa,CAAC;AAEnB;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC;AAErE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,IACpC,MAAM,GACN,OAAO,CAAC,CAAC,CAAC,GACV,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,GAChD,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,GAC9C,IAAI,CAAC"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,19 +1,40 @@
|
|
|
1
1
|
import type { Nodes } from "@glion/ast";
|
|
2
2
|
import type { Predicate, Test } from "./types";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* The predicate a `visit` test describes.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* - `null` matches every node.
|
|
7
|
+
* - A string matches nodes whose `type` equals it.
|
|
8
|
+
* - A function is the predicate.
|
|
9
|
+
* - An object matches nodes whose own property equals (`===`) each of its values.
|
|
10
|
+
* A property the node does not own reads as `undefined`, so an `undefined`
|
|
11
|
+
* value matches an absent property, and a key that names an inherited member
|
|
12
|
+
* (`constructor`, `toString`, an own `__proto__`) matches no node. The
|
|
13
|
+
* object's entries are read once, when the predicate is created.
|
|
7
14
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* - Explicit undefined values in test object check for property absence
|
|
12
|
-
* - Dangerous keys (**proto**, constructor, prototype) are filtered for security
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const msh = s("MSH", f("|"));
|
|
13
18
|
*
|
|
14
|
-
*
|
|
15
|
-
* (
|
|
16
|
-
*
|
|
19
|
+
* createTest(null)(msh, []); // true
|
|
20
|
+
* createTest("segment")(msh, []); // true
|
|
21
|
+
* createTest("field")(msh, []); // false
|
|
22
|
+
*
|
|
23
|
+
* createTest({ type: "segment", name: "MSH" })(msh, []); // true
|
|
24
|
+
* createTest({ name: "PID" })(msh, []); // false
|
|
25
|
+
*
|
|
26
|
+
* // `undefined` matches a property the node does not have
|
|
27
|
+
* createTest({ name: undefined })(f("|"), []); // true
|
|
28
|
+
*
|
|
29
|
+
* // An inherited member is never matched
|
|
30
|
+
* createTest({ constructor: Object })(msh, []); // false
|
|
31
|
+
*
|
|
32
|
+
* // A function receives the ancestors as well
|
|
33
|
+
* const inGroup = createTest((_node, ancestors) => ancestors.length > 1);
|
|
34
|
+
* ```;
|
|
35
|
+
*
|
|
36
|
+
* @param test - `null`, a node type, a property object, or a predicate.
|
|
37
|
+
* @returns The predicate.
|
|
17
38
|
*/
|
|
18
39
|
export declare function createTest(test: Test<Nodes>): Predicate;
|
|
19
40
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/C
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,SAAS,CA6BvD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glion/util-visit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "An AST visitor for HL7v2 messages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"health",
|
|
@@ -37,18 +37,20 @@
|
|
|
37
37
|
"unist-util-visit-parents": "6.0.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
+
"@stryker-mutator/core": "10.0.0",
|
|
41
|
+
"@stryker-mutator/vitest-runner": "10.0.0",
|
|
40
42
|
"@types/node": "25.6.0",
|
|
41
43
|
"@vitest/coverage-v8": "4.1.11",
|
|
42
44
|
"publint": "0.3.18",
|
|
43
45
|
"tsdown": "0.21.10",
|
|
44
46
|
"typescript": "6.0.3",
|
|
45
47
|
"vitest": "4.1.11",
|
|
46
|
-
"@glion/ast": "0.
|
|
47
|
-
"@glion/builder": "0.
|
|
48
|
-
"@glion/
|
|
48
|
+
"@glion/ast": "0.23.0",
|
|
49
|
+
"@glion/builder": "0.23.0",
|
|
50
|
+
"@glion/check-readme": "0.18.0",
|
|
51
|
+
"@glion/parser": "0.23.0",
|
|
49
52
|
"@glion/testing": "0.18.0",
|
|
50
|
-
"@glion/tsconfig": "0.18.0"
|
|
51
|
-
"@glion/check-readme": "0.18.0"
|
|
53
|
+
"@glion/tsconfig": "0.18.0"
|
|
52
54
|
},
|
|
53
55
|
"engines": {
|
|
54
56
|
"node": ">=22"
|
|
@@ -57,6 +59,7 @@
|
|
|
57
59
|
"build": "tsdown && tsc --emitDeclarationOnly",
|
|
58
60
|
"check-types": "tsc --noEmit && tsc --noEmit -p tests/tsconfig.json",
|
|
59
61
|
"check:readme": "glion-check-readme",
|
|
62
|
+
"mutate": "stryker run",
|
|
60
63
|
"test": "vitest run",
|
|
61
64
|
"test:coverage": "vitest run --coverage",
|
|
62
65
|
"test:watch": "vitest",
|