@glion/util-visit 0.15.1 → 0.15.2
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 +50 -171
- package/package.json +12 -8
package/README.md
CHANGED
|
@@ -1,32 +1,14 @@
|
|
|
1
1
|
# @glion/util-visit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Visitor for traversing HL7v2 AST trees with ancestor context, depth, and HL7v2-aware sequence numbers.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## What it does
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
`hl7v2-util-visit` enables you to walk through any HL7v2 AST tree — from the root message down to individual subcomponents — with full context about where you are in the hierarchy. The visitor pattern:
|
|
10
|
-
|
|
11
|
-
- **Works from any starting node** (Root, Segment, Field, Component, etc.)
|
|
12
|
-
- **Tracks ancestors** from traversal root to current node
|
|
13
|
-
- **Provides visit info** (index, sequence, depth, metadata)
|
|
14
|
-
- **Efficient O(n) traversal** — Pre-computed index map for O(1) lookups
|
|
15
|
-
- **Battle-tested core** — Delegates traversal to `unist-util-visit-parents`
|
|
16
|
-
|
|
17
|
-
### When should I use this?
|
|
18
|
-
|
|
19
|
-
Use `hl7v2-util-visit` when you need to:
|
|
20
|
-
|
|
21
|
-
- Validate HL7v2 message structure
|
|
22
|
-
- Transform or annotate AST nodes
|
|
23
|
-
- Extract specific fields with context
|
|
24
|
-
- Analyze message patterns across the tree
|
|
25
|
-
- Implement custom processing rules that need parent/ancestor awareness
|
|
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` and pre-computes sibling indices for O(1) lookups.
|
|
26
8
|
|
|
27
9
|
## Install
|
|
28
10
|
|
|
29
|
-
```
|
|
11
|
+
```bash
|
|
30
12
|
npm install @glion/util-visit
|
|
31
13
|
```
|
|
32
14
|
|
|
@@ -42,8 +24,6 @@ const message = parse("MSH|^~\\&|...\rPID|...");
|
|
|
42
24
|
visit(message, "segment", (node, ancestors, info) => {
|
|
43
25
|
console.log(`Segment: ${info.metadata?.header} at depth ${info.depth}`);
|
|
44
26
|
});
|
|
45
|
-
// => Segment: MSH at depth 2
|
|
46
|
-
// => Segment: PID at depth 2
|
|
47
27
|
|
|
48
28
|
// Find fields with parent context
|
|
49
29
|
visit(message, "field", (node, ancestors, info) => {
|
|
@@ -54,7 +34,7 @@ visit(message, "field", (node, ancestors, info) => {
|
|
|
54
34
|
// Skip processing of sensitive segments
|
|
55
35
|
visit(message, (node, ancestors, info) => {
|
|
56
36
|
if (node.type === "segment" && info.metadata?.header === "NTE") {
|
|
57
|
-
return SKIP;
|
|
37
|
+
return SKIP;
|
|
58
38
|
}
|
|
59
39
|
});
|
|
60
40
|
```
|
|
@@ -69,37 +49,37 @@ Visit nodes in an HL7v2 AST tree.
|
|
|
69
49
|
|
|
70
50
|
#### Parameters
|
|
71
51
|
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
- `string
|
|
75
|
-
- `Partial<Nodes
|
|
76
|
-
- `Test
|
|
77
|
-
-
|
|
52
|
+
- `tree` (`Nodes`) — Tree to traverse. Can be any node type, not just `Root`.
|
|
53
|
+
- `test` (`string | Partial<Nodes> | Test`, optional) — Filter:
|
|
54
|
+
- `string` — Match nodes by type (e.g., `"segment"`).
|
|
55
|
+
- `Partial<Nodes>` — Match nodes with matching properties (e.g., `{ name: "PATIENT_GROUP" }`).
|
|
56
|
+
- `Test` — Custom function `(node, ancestors) => boolean`.
|
|
57
|
+
- `visitor` (`Visitor`) — Function called for each matching node.
|
|
78
58
|
|
|
79
59
|
#### Returns
|
|
80
60
|
|
|
81
|
-
`void
|
|
61
|
+
`void`.
|
|
82
62
|
|
|
83
|
-
#### Important:
|
|
63
|
+
#### Important: test vs visitor functions
|
|
84
64
|
|
|
85
65
|
**If you pass a function as the second argument, it is always treated as a Visitor, never as a Test.**
|
|
86
66
|
|
|
87
67
|
```typescript
|
|
88
|
-
// WRONG
|
|
68
|
+
// WRONG — testFn will be treated as a visitor, not a test
|
|
89
69
|
visit(ast, (node) => node.type === 'segment', ...); // Missing visitor!
|
|
90
70
|
|
|
91
|
-
// CORRECT
|
|
71
|
+
// CORRECT — Explicit 3-argument form
|
|
92
72
|
visit(ast, (node) => node.type === 'segment', (node, ancestors, info) => {
|
|
93
73
|
console.log('Visiting segment');
|
|
94
74
|
});
|
|
95
75
|
|
|
96
|
-
// CORRECT
|
|
76
|
+
// CORRECT — Use string or object for simple tests
|
|
97
77
|
visit(ast, 'segment', (node, ancestors, info) => {
|
|
98
78
|
console.log('Visiting segment');
|
|
99
79
|
});
|
|
100
80
|
```
|
|
101
81
|
|
|
102
|
-
#### Visitor
|
|
82
|
+
#### Visitor function
|
|
103
83
|
|
|
104
84
|
```typescript
|
|
105
85
|
type Visitor<T extends Nodes = Nodes> = (
|
|
@@ -111,17 +91,17 @@ type Visitor<T extends Nodes = Nodes> = (
|
|
|
111
91
|
|
|
112
92
|
The visitor receives:
|
|
113
93
|
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
94
|
+
- `node` — Current AST node.
|
|
95
|
+
- `ancestors` — Array of ancestor nodes from root to parent (not including current node).
|
|
96
|
+
- `info` — Visit information with index, sequence, depth, and metadata.
|
|
117
97
|
|
|
118
98
|
The visitor can return:
|
|
119
99
|
|
|
120
|
-
- `undefined` or `void` — Continue traversal normally
|
|
121
|
-
- `SKIP` — Skip children of current node
|
|
122
|
-
- `EXIT` — Stop traversal immediately
|
|
100
|
+
- `undefined` or `void` — Continue traversal normally.
|
|
101
|
+
- `SKIP` — Skip children of current node.
|
|
102
|
+
- `EXIT` — Stop traversal immediately.
|
|
123
103
|
|
|
124
|
-
### VisitInfo
|
|
104
|
+
### `VisitInfo`
|
|
125
105
|
|
|
126
106
|
```typescript
|
|
127
107
|
interface VisitInfo {
|
|
@@ -139,28 +119,27 @@ interface VisitInfo {
|
|
|
139
119
|
}
|
|
140
120
|
```
|
|
141
121
|
|
|
142
|
-
|
|
122
|
+
`index` and `sequence` represent the node's **position in the tree**, not its position among filtered results:
|
|
143
123
|
|
|
144
124
|
```typescript
|
|
145
125
|
// Structure: MSH segment with fields at positions 1, 2, 3, 4
|
|
146
126
|
// Filter matches only field 3
|
|
147
|
-
|
|
148
127
|
visit(
|
|
149
128
|
ast,
|
|
150
129
|
(n) => n.type === "field" && hasContent(n),
|
|
151
130
|
(node, ancestors, info) => {
|
|
152
|
-
console.log(info.sequence); //
|
|
131
|
+
console.log(info.sequence); // 3 (position in segment, not "1st match")
|
|
153
132
|
}
|
|
154
133
|
);
|
|
155
134
|
```
|
|
156
135
|
|
|
157
136
|
This is correct because HL7v2 paths like `PID.3` refer to tree positions, not filtered positions.
|
|
158
137
|
|
|
159
|
-
### Automatic
|
|
138
|
+
### Automatic metadata extraction
|
|
160
139
|
|
|
161
|
-
The `metadata` field is populated automatically
|
|
140
|
+
The `metadata` field is populated automatically:
|
|
162
141
|
|
|
163
|
-
| Node
|
|
142
|
+
| Node type | Metadata key | Description |
|
|
164
143
|
| --------- | ------------ | ------------------------------------------- |
|
|
165
144
|
| `segment` | `header` | Segment identifier (e.g., `"MSH"`, `"PID"`) |
|
|
166
145
|
| `group` | `name` | Group name (e.g., `"PATIENT_GROUP"`) |
|
|
@@ -185,7 +164,7 @@ import type {
|
|
|
185
164
|
|
|
186
165
|
## Examples
|
|
187
166
|
|
|
188
|
-
### Filter by
|
|
167
|
+
### Filter by node type
|
|
189
168
|
|
|
190
169
|
```typescript
|
|
191
170
|
visit(ast, "segment", (node, ancestors, info) => {
|
|
@@ -193,7 +172,7 @@ visit(ast, "segment", (node, ancestors, info) => {
|
|
|
193
172
|
});
|
|
194
173
|
```
|
|
195
174
|
|
|
196
|
-
### Filter by
|
|
175
|
+
### Filter by properties
|
|
197
176
|
|
|
198
177
|
```typescript
|
|
199
178
|
visit(ast, { name: "PATIENT_GROUP" }, (node, ancestors, info) => {
|
|
@@ -201,7 +180,7 @@ visit(ast, { name: "PATIENT_GROUP" }, (node, ancestors, info) => {
|
|
|
201
180
|
});
|
|
202
181
|
```
|
|
203
182
|
|
|
204
|
-
### Custom
|
|
183
|
+
### Custom test function
|
|
205
184
|
|
|
206
185
|
```typescript
|
|
207
186
|
// Visit fields in MSH segment only
|
|
@@ -217,21 +196,17 @@ visit(
|
|
|
217
196
|
);
|
|
218
197
|
```
|
|
219
198
|
|
|
220
|
-
### Access
|
|
199
|
+
### Access parent and ancestors
|
|
221
200
|
|
|
222
201
|
```typescript
|
|
223
202
|
visit(ast, "component", (node, ancestors, info) => {
|
|
224
|
-
// Get immediate parent
|
|
225
203
|
const parent = ancestors.at(-1);
|
|
226
|
-
|
|
227
|
-
// Find closest segment ancestor
|
|
228
204
|
const segment = ancestors.findLast((n) => n.type === "segment");
|
|
229
|
-
|
|
230
205
|
console.log(`Component at depth ${info.depth}`);
|
|
231
206
|
});
|
|
232
207
|
```
|
|
233
208
|
|
|
234
|
-
### Control
|
|
209
|
+
### Control flow: skip children
|
|
235
210
|
|
|
236
211
|
```typescript
|
|
237
212
|
visit(ast, (node, ancestors, info) => {
|
|
@@ -241,13 +216,13 @@ visit(ast, (node, ancestors, info) => {
|
|
|
241
216
|
});
|
|
242
217
|
```
|
|
243
218
|
|
|
244
|
-
### Control
|
|
219
|
+
### Control flow: exit early
|
|
245
220
|
|
|
246
221
|
```typescript
|
|
247
|
-
import { EXIT } from
|
|
222
|
+
import { EXIT } from "@glion/util-visit";
|
|
248
223
|
|
|
249
224
|
let found = false;
|
|
250
|
-
visit(ast,
|
|
225
|
+
visit(ast, "field", (node, ancestors, info) => {
|
|
251
226
|
if (/* some condition */) {
|
|
252
227
|
found = true;
|
|
253
228
|
return EXIT; // Stop traversal completely
|
|
@@ -255,7 +230,7 @@ visit(ast, 'field', (node, ancestors, info) => {
|
|
|
255
230
|
});
|
|
256
231
|
```
|
|
257
232
|
|
|
258
|
-
### Start from
|
|
233
|
+
### Start from any node
|
|
259
234
|
|
|
260
235
|
```typescript
|
|
261
236
|
import { s, f, c } from "@glion/builder";
|
|
@@ -269,14 +244,13 @@ visit(segment, "field", (node, ancestors, info) => {
|
|
|
269
244
|
});
|
|
270
245
|
```
|
|
271
246
|
|
|
272
|
-
### Track
|
|
247
|
+
### Track nesting levels
|
|
273
248
|
|
|
274
249
|
```typescript
|
|
275
250
|
visit(ast, (node, ancestors, info) => {
|
|
276
251
|
const indent = " ".repeat(info.depth - 1);
|
|
277
252
|
console.log(`${indent}${node.type} [${info.sequence}]`);
|
|
278
253
|
});
|
|
279
|
-
// Output:
|
|
280
254
|
// root [1]
|
|
281
255
|
// segment [1]
|
|
282
256
|
// segment-header [0]
|
|
@@ -285,11 +259,10 @@ visit(ast, (node, ancestors, info) => {
|
|
|
285
259
|
// component [1]
|
|
286
260
|
```
|
|
287
261
|
|
|
288
|
-
### Group
|
|
262
|
+
### Group hierarchy navigation
|
|
289
263
|
|
|
290
264
|
```typescript
|
|
291
265
|
visit(ast, "segment", (node, ancestors, info) => {
|
|
292
|
-
// Get all parent groups
|
|
293
266
|
const groups = ancestors
|
|
294
267
|
.filter((n) => n.type === "group")
|
|
295
268
|
.map((n) => (n as any).name)
|
|
@@ -297,12 +270,10 @@ visit(ast, "segment", (node, ancestors, info) => {
|
|
|
297
270
|
|
|
298
271
|
console.log(`${info.metadata?.header} is in groups: ${groups.join(" > ")}`);
|
|
299
272
|
});
|
|
300
|
-
//
|
|
273
|
+
// PID is in groups: PATIENT_GROUP
|
|
301
274
|
```
|
|
302
275
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
### Validate Required Fields
|
|
276
|
+
### Validate required fields
|
|
306
277
|
|
|
307
278
|
```typescript
|
|
308
279
|
function validateRequiredFields(ast: Root): string[] {
|
|
@@ -312,12 +283,10 @@ function validateRequiredFields(ast: Root): string[] {
|
|
|
312
283
|
const segment = node as Segment;
|
|
313
284
|
const header = info.metadata?.header;
|
|
314
285
|
|
|
315
|
-
// MSH segment must have at least 12 fields
|
|
316
286
|
if (header === "MSH" && segment.children.length < 12) {
|
|
317
|
-
errors.push(
|
|
287
|
+
errors.push("MSH segment missing required fields");
|
|
318
288
|
}
|
|
319
289
|
|
|
320
|
-
// PID segment must have patient ID (PID.3)
|
|
321
290
|
if (header === "PID") {
|
|
322
291
|
const patientId = segment.children[3];
|
|
323
292
|
if (!patientId || patientId.children.length === 0) {
|
|
@@ -330,7 +299,7 @@ function validateRequiredFields(ast: Root): string[] {
|
|
|
330
299
|
}
|
|
331
300
|
```
|
|
332
301
|
|
|
333
|
-
### Extract
|
|
302
|
+
### Extract data with context
|
|
334
303
|
|
|
335
304
|
```typescript
|
|
336
305
|
interface PatientName {
|
|
@@ -350,7 +319,6 @@ function extractPatientNames(ast: Root): PatientName[] {
|
|
|
350
319
|
if (nameField?.children[0]?.children[0]) {
|
|
351
320
|
const nameComponent = nameField.children[0].children[0];
|
|
352
321
|
const name = (nameComponent.children[0] as Subcomponent)?.value || "";
|
|
353
|
-
|
|
354
322
|
const groupAncestor = ancestors.find((n) => n.type === "group");
|
|
355
323
|
|
|
356
324
|
names.push({
|
|
@@ -365,46 +333,7 @@ function extractPatientNames(ast: Root): PatientName[] {
|
|
|
365
333
|
}
|
|
366
334
|
```
|
|
367
335
|
|
|
368
|
-
###
|
|
369
|
-
|
|
370
|
-
```typescript
|
|
371
|
-
interface MessageStructure {
|
|
372
|
-
segmentCount: number;
|
|
373
|
-
groupCount: number;
|
|
374
|
-
maxDepth: number;
|
|
375
|
-
segmentTypes: Record<string, number>;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function analyzeStructure(ast: Root): MessageStructure {
|
|
379
|
-
const structure: MessageStructure = {
|
|
380
|
-
segmentCount: 0,
|
|
381
|
-
groupCount: 0,
|
|
382
|
-
maxDepth: 0,
|
|
383
|
-
segmentTypes: {},
|
|
384
|
-
};
|
|
385
|
-
|
|
386
|
-
visit(ast, (node, ancestors, info) => {
|
|
387
|
-
structure.maxDepth = Math.max(structure.maxDepth, info.depth);
|
|
388
|
-
|
|
389
|
-
if (node.type === "segment") {
|
|
390
|
-
structure.segmentCount++;
|
|
391
|
-
const header = info.metadata?.header as string;
|
|
392
|
-
if (header) {
|
|
393
|
-
structure.segmentTypes[header] =
|
|
394
|
-
(structure.segmentTypes[header] || 0) + 1;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
if (node.type === "group") {
|
|
399
|
-
structure.groupCount++;
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
return structure;
|
|
404
|
-
}
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### Find First Match and Exit
|
|
336
|
+
### Find first match and exit
|
|
408
337
|
|
|
409
338
|
```typescript
|
|
410
339
|
function findFirstObservation(ast: Root, targetCode: string): string | null {
|
|
@@ -420,7 +349,7 @@ function findFirstObservation(ast: Root, targetCode: string): string | null {
|
|
|
420
349
|
if (code === targetCode) {
|
|
421
350
|
const valueField = segment.children[5];
|
|
422
351
|
result = valueField?.children[0]?.children[0]?.children[0]?.value || null;
|
|
423
|
-
return EXIT;
|
|
352
|
+
return EXIT;
|
|
424
353
|
}
|
|
425
354
|
});
|
|
426
355
|
|
|
@@ -428,59 +357,9 @@ function findFirstObservation(ast: Root, targetCode: string): string | null {
|
|
|
428
357
|
}
|
|
429
358
|
```
|
|
430
359
|
|
|
431
|
-
##
|
|
432
|
-
|
|
433
|
-
This library is a thin wrapper around [unist-util-visit-parents][] that adds HL7v2-specific features:
|
|
434
|
-
|
|
435
|
-
1. **Core Traversal**: Delegates to `unist-util-visit-parents` (battle-tested with 50M+ weekly downloads)
|
|
436
|
-
2. **Index Optimization**: Pre-computes node indices for O(1) lookups (avoids O(n²) `indexOf` calls)
|
|
437
|
-
3. **HL7v2 Context**: Adds `VisitInfo` with sequence numbers, depth tracking, and metadata extraction
|
|
438
|
-
4. **Domain Conventions**: Implements HL7v2-specific indexing (segment-header sequence = 0, fields = 1,2,3...)
|
|
439
|
-
|
|
440
|
-
This design gives us:
|
|
441
|
-
|
|
442
|
-
- ✅ Proven traversal logic (EXIT/SKIP handling, edge cases)
|
|
443
|
-
- ✅ Mutation support (inherited from unist)
|
|
444
|
-
- ✅ Reverse traversal support (pass `reverse: true` to underlying library)
|
|
445
|
-
- ✅ Small codebase (~120 lines vs previous ~180 lines)
|
|
446
|
-
- ✅ Ecosystem compatibility (works with other unist utilities)
|
|
447
|
-
|
|
448
|
-
## Performance Characteristics
|
|
449
|
-
|
|
450
|
-
- **O(n) traversal** — Single pass through all nodes
|
|
451
|
-
- **O(n) index pre-computation** — One-time upfront cost
|
|
452
|
-
- **O(1) index lookups** — Avoids O(n²) `indexOf()` anti-pattern
|
|
453
|
-
- **O(d) ancestor construction** where d = depth (typically < 10 for HL7v2)
|
|
454
|
-
- **Minimal allocations** — Metadata extracted once per node
|
|
455
|
-
|
|
456
|
-
## Types
|
|
457
|
-
|
|
458
|
-
```typescript
|
|
459
|
-
export type {
|
|
460
|
-
VisitInfo, // { index, sequence, depth, metadata }
|
|
461
|
-
Visitor, // (node, ancestors, info) => VisitorResult
|
|
462
|
-
VisitorResult, // void | false | 'skip' | ActionTuple
|
|
463
|
-
Test, // string | Partial | predicate | null
|
|
464
|
-
Predicate, // (node, ancestors) => boolean
|
|
465
|
-
} from "@glion/util-visit";
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
## Contributing
|
|
469
|
-
|
|
470
|
-
We welcome contributions! Please see our [Contributing Guide][github-contributing] for more details.
|
|
471
|
-
|
|
472
|
-
## Code of Conduct
|
|
473
|
-
|
|
474
|
-
To ensure a welcoming and positive environment, we have a [Code of Conduct][github-code-of-conduct] that all contributors and participants are expected to adhere to.
|
|
475
|
-
|
|
476
|
-
## License
|
|
477
|
-
|
|
478
|
-
Copyright 2025 Rethink Health, SUARL. All rights reserved.
|
|
360
|
+
## Part of Glion
|
|
479
361
|
|
|
480
|
-
|
|
362
|
+
`@glion/util-visit` is part of **[Glion]**, the application framework for HL7v2. See the [Glion README] for the full package catalog and architecture.
|
|
481
363
|
|
|
482
|
-
[
|
|
483
|
-
[
|
|
484
|
-
[github-contributing]: https://github.com/rethinkhealth/glion/blob/main/CONTRIBUTING.md
|
|
485
|
-
[hl7v2-ast]: https://github.com/rethinkhealth/glion/tree/main/packages/hl7v2-ast
|
|
486
|
-
[unist-util-visit-parents]: https://github.com/syntax-tree/unist-util-visit-parents
|
|
364
|
+
[Glion]: https://github.com/rethinkhealth/glion#readme
|
|
365
|
+
[Glion README]: https://github.com/rethinkhealth/glion#readme
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glion/util-visit",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.2",
|
|
4
4
|
"description": "An AST visitor for HL7v2 messages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"health",
|
|
@@ -39,15 +39,17 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^25.5.0",
|
|
41
41
|
"@vitest/coverage-v8": "4.1.2",
|
|
42
|
+
"publint": "0.3.18",
|
|
42
43
|
"tsdown": "0.21.7",
|
|
43
44
|
"typescript": "^5.9.3",
|
|
44
45
|
"vitest": "4.1.2",
|
|
45
|
-
"@glion/
|
|
46
|
-
"@glion/
|
|
47
|
-
"@glion/config": "0.15.
|
|
48
|
-
"@glion/parser": "0.15.
|
|
49
|
-
"@glion/
|
|
50
|
-
"@glion/
|
|
46
|
+
"@glion/builder": "0.15.2",
|
|
47
|
+
"@glion/check-readme": "0.15.2",
|
|
48
|
+
"@glion/config": "0.15.2",
|
|
49
|
+
"@glion/parser": "0.15.2",
|
|
50
|
+
"@glion/ast": "0.15.2",
|
|
51
|
+
"@glion/testing": "0.15.2",
|
|
52
|
+
"@glion/tsconfig": "0.15.2"
|
|
51
53
|
},
|
|
52
54
|
"engines": {
|
|
53
55
|
"node": ">=18"
|
|
@@ -56,8 +58,10 @@
|
|
|
56
58
|
"scripts": {
|
|
57
59
|
"build": "tsdown && tsc --emitDeclarationOnly",
|
|
58
60
|
"check-types": "tsc --noEmit",
|
|
61
|
+
"check:readme": "glion-check-readme",
|
|
59
62
|
"test": "vitest run",
|
|
60
63
|
"test:coverage": "vitest run --coverage",
|
|
61
|
-
"test:watch": "vitest"
|
|
64
|
+
"test:watch": "vitest",
|
|
65
|
+
"publint": "publint --strict"
|
|
62
66
|
}
|
|
63
67
|
}
|