@glion/lint-profile-field-max-length 0.23.0 → 0.25.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 +16 -15
- package/dist/index.d.ts +8 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -32
- package/dist/index.js.map +1 -1
- package/package.json +10 -6
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @glion/lint-profile-field-max-length
|
|
2
2
|
|
|
3
|
-
Lint rule
|
|
3
|
+
Lint rule that reports a field value longer than HL7v2 allows.
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
7
|
-
Flags field
|
|
7
|
+
Flags a field value longer than the maximum length the HL7v2 standard gives that field in the message's version. Each repetition of a field is measured on its own, and delimiters (`^`, `&`) are not counted. It needs the plugins `@glion/annotate-profile-context` and `@glion/annotate-profile-fields` to run before it; `@glion/preset-lint-profile-recommended` includes them.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -16,21 +16,24 @@ npm install @glion/lint-profile-field-max-length
|
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
18
|
import { hl7v2AnnotateProfileContext } from "@glion/annotate-profile-context";
|
|
19
|
-
import {
|
|
19
|
+
import { hl7v2AnnotateProfileFields } from "@glion/annotate-profile-fields";
|
|
20
20
|
import hl7v2LintFieldMaxLength from "@glion/lint-profile-field-max-length";
|
|
21
|
+
import { parseHL7v2 } from "@glion/parser";
|
|
21
22
|
import { unified } from "unified";
|
|
23
|
+
import { VFile } from "vfile";
|
|
22
24
|
import { reporter } from "vfile-reporter";
|
|
23
25
|
|
|
24
26
|
const message = [
|
|
25
|
-
"MSH|^~\\&|SENDER|FAC|RECV|RFAC|20250601120000||ADT^A01^ADT_A01|
|
|
27
|
+
"MSH|^~\\&|SENDER|FAC|RECV|RFAC|20250601120000||ADT^A01^ADT_A01|MSG0000000000000000000000001|P|2.5",
|
|
26
28
|
"PID|1||PATID1234^^^HOSP^MR||DOE^JANE||19800101|F",
|
|
27
29
|
].join("\r");
|
|
28
30
|
|
|
29
|
-
const file =
|
|
30
|
-
|
|
31
|
+
const file = new VFile();
|
|
32
|
+
await unified()
|
|
31
33
|
.use(hl7v2AnnotateProfileContext)
|
|
34
|
+
.use(hl7v2AnnotateProfileFields)
|
|
32
35
|
.use(hl7v2LintFieldMaxLength)
|
|
33
|
-
.
|
|
36
|
+
.run(parseHL7v2(message), file);
|
|
34
37
|
|
|
35
38
|
console.error(reporter([file]));
|
|
36
39
|
```
|
|
@@ -39,9 +42,7 @@ console.error(reporter([file]));
|
|
|
39
42
|
|
|
40
43
|
### `unified().use(hl7v2LintFieldMaxLength)`
|
|
41
44
|
|
|
42
|
-
A `unified` lint rule plugin. Takes no options.
|
|
43
|
-
|
|
44
|
-
Reads `file.data.profile`. For each segment in the tree it walks its fields, looks up the profile entry by sequence, and — if a `maxLength` is declared — compares it against `getLength()` from `@glion/utils` for every repetition. Each repetition over the limit produces one message.
|
|
45
|
+
A `unified` lint rule plugin. Takes no options. Reports one message for each field repetition over the limit.
|
|
45
46
|
|
|
46
47
|
```ts
|
|
47
48
|
import type { Plugin } from "unified";
|
|
@@ -53,11 +54,11 @@ export default hl7v2LintFieldMaxLength;
|
|
|
53
54
|
|
|
54
55
|
## What it checks
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
Each repetition of a field is at most as long as the field's maximum length in the message's version. For example, `MSH-10` (Message Control ID) allows 20 characters in v2.5.
|
|
57
58
|
|
|
58
59
|
### Valid
|
|
59
60
|
|
|
60
|
-
`MSH-10`
|
|
61
|
+
`MSH-10` has 8 characters:
|
|
61
62
|
|
|
62
63
|
```hl7
|
|
63
64
|
MSH|^~\&|SENDER|FAC|RECV|RFAC|20250601120000||ADT^A01^ADT_A01|MSG00001|P|2.5
|
|
@@ -66,7 +67,7 @@ PID|1||PATID1234^^^HOSP^MR||DOE^JANE||19800101|F
|
|
|
66
67
|
|
|
67
68
|
### Invalid
|
|
68
69
|
|
|
69
|
-
`MSH-10`
|
|
70
|
+
`MSH-10` has 28 characters:
|
|
70
71
|
|
|
71
72
|
```hl7
|
|
72
73
|
MSH|^~\&|SENDER|FAC|RECV|RFAC|20250601120000||ADT^A01^ADT_A01|MSG0000000000000000000000001|P|2.5
|
|
@@ -76,10 +77,10 @@ PID|1||PATID1234^^^HOSP^MR||DOE^JANE||19800101|F
|
|
|
76
77
|
Reported message:
|
|
77
78
|
|
|
78
79
|
```
|
|
79
|
-
Field MSH-10
|
|
80
|
+
Field `MSH-10` (Message Control ID) is 28 characters long; it allows at most 20 characters.
|
|
80
81
|
```
|
|
81
82
|
|
|
82
|
-
|
|
83
|
+
A composite value such as `DOE^JANE` counts as 7 characters, not 8.
|
|
83
84
|
|
|
84
85
|
## Part of Glion
|
|
85
86
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import type { Root } from "@glion/ast";
|
|
2
2
|
/**
|
|
3
|
-
* Lint rule that
|
|
3
|
+
* Lint rule that reports a field repetition longer than the field's LEN.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* The length is measured using `getLength()` from `hl7v2-utils`, which
|
|
9
|
-
* recursively sums the string lengths of all subcomponent values.
|
|
10
|
-
* Delimiters are not included in the count.
|
|
11
|
-
*
|
|
12
|
-
* Fields without `maxLength` in the profile and empty fields are skipped.
|
|
13
|
-
* Segments without a known profile (e.g., Z-segments) are silently skipped.
|
|
5
|
+
* Reads `maxLength` from `field.data`, so `@glion/annotate-profile-fields`
|
|
6
|
+
* MUST run before it. The length of a repetition is the sum of its values,
|
|
7
|
+
* delimiters excluded.
|
|
14
8
|
*
|
|
15
9
|
* @example
|
|
16
10
|
* ```typescript
|
|
17
|
-
* unified()
|
|
11
|
+
* unified()
|
|
12
|
+
* .use(hl7v2AnnotateProfileContext)
|
|
13
|
+
* .use(hl7v2AnnotateProfileFields)
|
|
14
|
+
* .use(hl7v2LintFieldMaxLength);
|
|
18
15
|
* ```;
|
|
19
16
|
*/
|
|
20
17
|
declare const hl7v2LintFieldMaxLength: import("unified-lint-rule").Plugin<Root, unknown>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAWvC;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,uBAAuB,mDA8B5B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,50 +1,46 @@
|
|
|
1
1
|
import { SKIP, visit } from "@glion/util-visit";
|
|
2
|
-
import { getLength
|
|
2
|
+
import { getLength } from "@glion/utils";
|
|
3
|
+
import pluralize from "pluralize";
|
|
3
4
|
import { lintRule } from "unified-lint-rule";
|
|
4
5
|
//#region src/index.ts
|
|
6
|
+
const messages = { tooLong: (field, name, length, max) => `Field \`${field}\` (${name}) is ${pluralize("character", length, true)} long; it allows at most ${pluralize("character", max, true)}.` };
|
|
5
7
|
/**
|
|
6
|
-
* Lint rule that
|
|
8
|
+
* Lint rule that reports a field repetition longer than the field's LEN.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* The length is measured using `getLength()` from `hl7v2-utils`, which
|
|
12
|
-
* recursively sums the string lengths of all subcomponent values.
|
|
13
|
-
* Delimiters are not included in the count.
|
|
14
|
-
*
|
|
15
|
-
* Fields without `maxLength` in the profile and empty fields are skipped.
|
|
16
|
-
* Segments without a known profile (e.g., Z-segments) are silently skipped.
|
|
10
|
+
* Reads `maxLength` from `field.data`, so `@glion/annotate-profile-fields`
|
|
11
|
+
* MUST run before it. The length of a repetition is the sum of its values,
|
|
12
|
+
* delimiters excluded.
|
|
17
13
|
*
|
|
18
14
|
* @example
|
|
19
15
|
* ```typescript
|
|
20
|
-
* unified()
|
|
16
|
+
* unified()
|
|
17
|
+
* .use(hl7v2AnnotateProfileContext)
|
|
18
|
+
* .use(hl7v2AnnotateProfileFields)
|
|
19
|
+
* .use(hl7v2LintFieldMaxLength);
|
|
21
20
|
* ```;
|
|
22
21
|
*/
|
|
23
|
-
const hl7v2LintFieldMaxLength = lintRule({
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
if (len === 0) continue;
|
|
36
|
-
if (len > profile.maxLength) file.message(`Field ${segment.name}-${info.sequence} exceeds max length of ${profile.maxLength} (actual: ${len})`, {
|
|
22
|
+
const hl7v2LintFieldMaxLength = lintRule({
|
|
23
|
+
origin: "hl7v2-lint:field-max-length",
|
|
24
|
+
url: "https://github.com/rethinkhealth/glion/tree/main/packages/lint-profile-field-max-length#readme"
|
|
25
|
+
}, (tree, file) => {
|
|
26
|
+
visit(tree, "field", (field, ancestors) => {
|
|
27
|
+
const id = field.data?.id;
|
|
28
|
+
const maxLength = field.data?.maxLength;
|
|
29
|
+
if (id === void 0 || maxLength === void 0) return SKIP;
|
|
30
|
+
for (const repetition of field.children) {
|
|
31
|
+
const length = getLength(repetition);
|
|
32
|
+
if (length > maxLength) {
|
|
33
|
+
const message = file.message(messages.tooLong(id, field.data?.name ?? "", length, maxLength), {
|
|
37
34
|
ancestors: [
|
|
38
|
-
...
|
|
39
|
-
|
|
40
|
-
fieldNode,
|
|
35
|
+
...ancestors,
|
|
36
|
+
field,
|
|
41
37
|
repetition
|
|
42
38
|
],
|
|
43
|
-
place: repetition.position ??
|
|
39
|
+
place: repetition.position ?? field.position
|
|
44
40
|
});
|
|
41
|
+
message.actual = String(length);
|
|
45
42
|
}
|
|
46
|
-
|
|
47
|
-
});
|
|
43
|
+
}
|
|
48
44
|
return SKIP;
|
|
49
45
|
});
|
|
50
46
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// oxlint-disable-next-line no-unused-vars -- triggers
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// oxlint-disable-next-line no-unused-vars -- triggers FieldData augmentation\nimport type { hl7v2AnnotateProfileFields } from \"@glion/annotate-profile-fields\";\nimport type { Root } from \"@glion/ast\";\nimport { SKIP, visit } from \"@glion/util-visit\";\nimport { getLength } from \"@glion/utils\";\nimport pluralize from \"pluralize\";\nimport { lintRule } from \"unified-lint-rule\";\n\nconst messages = {\n tooLong: (field: string, name: string, length: number, max: number) =>\n `Field \\`${field}\\` (${name}) is ${pluralize(\"character\", length, true)} long; it allows at most ${pluralize(\"character\", max, true)}.`,\n} as const;\n\n/**\n * Lint rule that reports a field repetition longer than the field's LEN.\n *\n * Reads `maxLength` from `field.data`, so `@glion/annotate-profile-fields`\n * MUST run before it. The length of a repetition is the sum of its values,\n * delimiters excluded.\n *\n * @example\n * ```typescript\n * unified()\n * .use(hl7v2AnnotateProfileContext)\n * .use(hl7v2AnnotateProfileFields)\n * .use(hl7v2LintFieldMaxLength);\n * ```;\n */\nconst hl7v2LintFieldMaxLength = lintRule<Root>(\n {\n origin: \"hl7v2-lint:field-max-length\",\n url: \"https://github.com/rethinkhealth/glion/tree/main/packages/lint-profile-field-max-length#readme\",\n },\n (tree, file) => {\n visit(tree, \"field\", (field, ancestors) => {\n const id = field.data?.id;\n const maxLength = field.data?.maxLength;\n if (id === undefined || maxLength === undefined) {\n return SKIP;\n }\n\n // HL7v2 applies LEN to each repetition, not to the whole field.\n for (const repetition of field.children) {\n const length = getLength(repetition);\n if (length > maxLength) {\n const message = file.message(\n messages.tooLong(id, field.data?.name ?? \"\", length, maxLength),\n {\n ancestors: [...ancestors, field, repetition],\n place: repetition.position ?? field.position,\n }\n );\n message.actual = String(length);\n }\n }\n return SKIP;\n });\n }\n);\n\nexport default hl7v2LintFieldMaxLength;\n"],"mappings":";;;;;AAQA,MAAM,WAAW,EACf,UAAU,OAAe,MAAc,QAAgB,QACrD,WAAW,MAAM,MAAM,KAAK,OAAO,UAAU,aAAa,QAAQ,KAAK,CAAC,2BAA2B,UAAU,aAAa,KAAK,KAAK,CAAC,IACxI;;;;;;;;;;;;;;;;AAiBD,MAAM,0BAA0B,SAC9B;CACE,QAAQ;CACR,KAAK;CACN,GACA,MAAM,SAAS;AACd,OAAM,MAAM,UAAU,OAAO,cAAc;EACzC,MAAM,KAAK,MAAM,MAAM;EACvB,MAAM,YAAY,MAAM,MAAM;AAC9B,MAAI,OAAO,KAAA,KAAa,cAAc,KAAA,EACpC,QAAO;AAIT,OAAK,MAAM,cAAc,MAAM,UAAU;GACvC,MAAM,SAAS,UAAU,WAAW;AACpC,OAAI,SAAS,WAAW;IACtB,MAAM,UAAU,KAAK,QACnB,SAAS,QAAQ,IAAI,MAAM,MAAM,QAAQ,IAAI,QAAQ,UAAU,EAC/D;KACE,WAAW;MAAC,GAAG;MAAW;MAAO;MAAW;KAC5C,OAAO,WAAW,YAAY,MAAM;KACrC,CACF;AACD,YAAQ,SAAS,OAAO,OAAO;;;AAGnC,SAAO;GACP;EAEL"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glion/lint-profile-field-max-length",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Lint rule to validate field value lengths against HL7v2 profile maxLength",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"health",
|
|
@@ -33,13 +33,16 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
+
"pluralize": "8.0.0",
|
|
36
37
|
"unified-lint-rule": "3.0.1",
|
|
37
|
-
"@glion/
|
|
38
|
-
"@glion/
|
|
39
|
-
"@glion/
|
|
38
|
+
"@glion/annotate-profile-fields": "0.25.0",
|
|
39
|
+
"@glion/ast": "0.25.0",
|
|
40
|
+
"@glion/util-visit": "0.25.0",
|
|
41
|
+
"@glion/utils": "0.25.0"
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {
|
|
42
44
|
"@types/node": "25.6.0",
|
|
45
|
+
"@types/pluralize": "^0.0.33",
|
|
43
46
|
"@vitest/coverage-v8": "4.1.11",
|
|
44
47
|
"publint": "0.3.18",
|
|
45
48
|
"tsdown": "0.21.10",
|
|
@@ -47,9 +50,10 @@
|
|
|
47
50
|
"unified": "^11.0.5",
|
|
48
51
|
"vfile": "^6.0.3",
|
|
49
52
|
"vitest": "4.1.11",
|
|
50
|
-
"@glion/annotate-profile-context": "0.
|
|
51
|
-
"@glion/builder": "0.
|
|
53
|
+
"@glion/annotate-profile-context": "0.25.0",
|
|
54
|
+
"@glion/builder": "0.25.0",
|
|
52
55
|
"@glion/check-readme": "0.18.0",
|
|
56
|
+
"@glion/parser": "0.25.0",
|
|
53
57
|
"@glion/testing": "0.18.0",
|
|
54
58
|
"@glion/tsconfig": "0.18.0"
|
|
55
59
|
},
|