@glion/lint-message-version 0.21.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 CHANGED
@@ -4,7 +4,7 @@ Lint rule that checks an HL7v2 message's `MSH-12` version satisfies a semver ran
4
4
 
5
5
  ## What it does
6
6
 
7
- Reads `MSH-12.1` from the tree and evaluates it against the configured `expression` using `@glion/util-semver`. Reports a message when `MSH-12` is missing or empty, when the value is not a valid semver-like version, or when it falls outside the allowed range. The default expression (`"<3.0.0 >=2.3"`) accepts HL7v2 versions 2.3 through 2.9 and excludes future v3 values.
7
+ Reads `MSH-12.1` from the tree and evaluates it against the configured `expression` using `@glion/util-semver`. Reports a message when `MSH-12` is missing, when it is empty, when the value is not a valid semver-like version, or when it falls outside the allowed range. The default expression (`"<3.0.0 >=2.3"`) accepts HL7v2 versions 2.3 through 2.9 and excludes future v3 values.
8
8
 
9
9
  ## Install
10
10
 
@@ -78,22 +78,28 @@ MSH|^~\&|SENDER|FAC|RCVR|FAC|20250101010101||ADT^A01^ADT_A01|MSG00001|P|2.2
78
78
  Reported message:
79
79
 
80
80
  ```
81
- MSH-12 (version) field value '2.2' does not satisfy expression '<3.0.0 >=2.3'
81
+ The version in `MSH-12` (Version ID) is `2.2`; it must satisfy `<3.0.0 >=2.3`.
82
82
  ```
83
83
 
84
84
  `MSH-12` is missing:
85
85
 
86
86
  ```
87
- Required MSH-12 (version) field is missing or empty
87
+ The message has no `MSH-12` (Version ID); a message must declare its HL7v2 version.
88
+ ```
89
+
90
+ `MSH-12` is present but empty:
91
+
92
+ ```
93
+ The version in `MSH-12` (Version ID) is empty; a message must declare its HL7v2 version.
88
94
  ```
89
95
 
90
96
  `MSH-12` contains a value that cannot be parsed as semver:
91
97
 
92
98
  ```
93
- MSH-12 (version) field value 'abc' is not valid
99
+ The version in `MSH-12` (Version ID) is `abc`; a version must be numbers separated by dots, such as `2.5` or `2.5.1`.
94
100
  ```
95
101
 
96
- Both the offending value and the configured expression are interpolated into the message. The rule reports at most one message per tree and exits as soon as the first problem is detected.
102
+ Each report on a value sets `actual` to that value; a version outside the range also sets `expected` to the configured expression. The rule reports at most one message per tree and exits as soon as the first problem is detected.
97
103
 
98
104
  ## Part of Glion
99
105
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAQ,MAAM,YAAY,CAAC;AAM9C,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD,QAAA,MAAM,uBAAuB,sEAmE5B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAMxC,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC;CACpB;AAmBD,QAAA,MAAM,uBAAuB,sEAiE5B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,49 +1,70 @@
1
- import { value } from "@glion/util-query";
1
+ import { select, value } from "@glion/util-query";
2
2
  import { satisfies } from "@glion/util-semver";
3
3
  import ensureError from "ensure-error";
4
4
  import { lintRule } from "unified-lint-rule";
5
5
  //#region src/index.ts
6
6
  const defaultOptions = { expression: "<3.0.0 >=2.3" };
7
+ const messages = {
8
+ emptyVersion: "The version in `MSH-12` (Version ID) is empty; a message must declare its HL7v2 version.",
9
+ missingVersion: "The message has no `MSH-12` (Version ID); a message must declare its HL7v2 version.",
10
+ notMessage: (kind) => `The input is a ${kind}; the version can be read only from \`MSH-12\` (Version ID) of a whole message.`,
11
+ unparsableVersion: (version) => `The version in \`MSH-12\` (Version ID) is \`${version}\`; a version must be numbers separated by dots, such as \`2.5\` or \`2.5.1\`.`,
12
+ unsupportedVersion: (version, expression) => `The version in \`MSH-12\` (Version ID) is \`${version}\`; it must satisfy \`${expression}\`.`
13
+ };
7
14
  const hl7v2LintMessageVersion = lintRule({
8
15
  origin: "hl7v2-lint:message-version",
9
- url: "https://github.com/rethinkhealth/hl7v2/tree/main/packages/hl7v2-lint-message-version#readme"
16
+ url: "https://github.com/rethinkhealth/glion/tree/main/packages/lint-message-version#readme"
10
17
  }, (tree, file, opts) => {
11
18
  const options = {
12
19
  ...defaultOptions,
13
20
  ...opts
14
21
  };
15
22
  if (tree.type !== "root") {
16
- file.message(`Root node type must be 'root' — received '${tree.type}' instead`, {
23
+ file.message(messages.notMessage(tree.type), {
17
24
  ancestors: [tree],
18
25
  place: tree.position
19
26
  });
20
27
  return;
21
28
  }
22
- const rootTree = tree;
23
- const result = value(rootTree, "MSH-12.1");
24
- if (!result?.value || result.value === "") {
25
- file.message("Required MSH-12 (version) field is missing or empty", {
26
- ancestors: result ? [...result.ancestors, result.node] : [rootTree],
27
- place: result?.node?.position || result?.ancestors.at(-1)?.position || rootTree.position
29
+ const field = select(tree, "MSH-12");
30
+ if (!field) {
31
+ file.message(messages.missingVersion, {
32
+ ancestors: [tree],
33
+ place: tree.position
28
34
  });
29
35
  return;
30
36
  }
37
+ const result = value(tree, "MSH-12.1");
38
+ if (!result?.value) {
39
+ const message = file.message(messages.emptyVersion, {
40
+ ancestors: [...field.ancestors, field.node],
41
+ place: field.node.position || field.ancestors.at(-1)?.position
42
+ });
43
+ message.actual = "";
44
+ return;
45
+ }
46
+ const ancestors = [...result.ancestors, result.node];
47
+ const place = result.node.position || result.ancestors.at(-1)?.position || tree.position;
31
48
  let isValid = false;
32
49
  try {
33
50
  isValid = satisfies(result.value, options.expression);
34
51
  } catch (caughtError) {
35
- const error = ensureError(caughtError);
36
- file.message(`MSH-12 (version) field value '${result.value}' is not valid`, {
37
- ancestors: result ? [...result.ancestors, result.node] : [rootTree],
38
- cause: error,
39
- place: result?.node?.position || rootTree.position
52
+ const message = file.message(messages.unparsableVersion(result.value), {
53
+ ancestors,
54
+ cause: ensureError(caughtError),
55
+ place: result.node.position || tree.position
40
56
  });
57
+ message.actual = result.value;
41
58
  return;
42
59
  }
43
- if (!isValid) file.message(`MSH-12 (version) field value '${result.value}' does not satisfy expression '${options.expression}'`, {
44
- ancestors: result ? [...result.ancestors, result.node] : [rootTree],
45
- place: result?.node?.position || result?.ancestors.at(-1)?.position || rootTree.position
46
- });
60
+ if (!isValid) {
61
+ const message = file.message(messages.unsupportedVersion(result.value, options.expression), {
62
+ ancestors,
63
+ place
64
+ });
65
+ message.actual = result.value;
66
+ message.expected = [options.expression];
67
+ }
47
68
  });
48
69
  //#endregion
49
70
  export { hl7v2LintMessageVersion as default };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Nodes, Root } from \"@glion/ast\";\nimport { value } from \"@glion/util-query\";\nimport { satisfies } from \"@glion/util-semver\";\nimport ensureError from \"ensure-error\";\nimport { lintRule } from \"unified-lint-rule\";\n\nexport interface MessageVersionLintOptions {\n expression: string;\n}\n\nconst defaultOptions = {\n expression: \"<3.0.0 >=2.3\",\n} as const;\n\nconst hl7v2LintMessageVersion = lintRule<Nodes, MessageVersionLintOptions>(\n {\n origin: \"hl7v2-lint:message-version\",\n url: \"https://github.com/rethinkhealth/hl7v2/tree/main/packages/hl7v2-lint-message-version#readme\",\n },\n // oxlint-disable-next-line complexity\n (tree, file, opts) => {\n const options = { ...defaultOptions, ...opts };\n\n // 1. Validate tree is a Root node.\n if (tree.type !== \"root\") {\n file.message(\n `Root node type must be 'root' — received '${tree.type}' instead`,\n {\n ancestors: [tree],\n place: tree.position,\n }\n );\n return;\n }\n\n const rootTree = tree as Root;\n\n // 2. Extract message info from annotated data or parse from MSH segment.\n const result = value(rootTree, \"MSH-12.1\");\n\n if (!result?.value || result.value === \"\") {\n file.message(\"Required MSH-12 (version) field is missing or empty\", {\n ancestors: result ? [...result.ancestors, result.node] : [rootTree],\n place:\n result?.node?.position ||\n result?.ancestors.at(-1)?.position ||\n rootTree.position,\n });\n return;\n }\n\n // 5. Ensure version satisfies allowed expression.\n let isValid = false;\n try {\n isValid = satisfies(result.value, options.expression);\n } catch (caughtError) {\n const error = ensureError(caughtError);\n file.message(\n `MSH-12 (version) field value '${result.value}' is not valid`,\n {\n ancestors: result ? [...result.ancestors, result.node] : [rootTree],\n cause: error,\n place: result?.node?.position || rootTree.position,\n }\n );\n return;\n }\n\n if (!isValid) {\n file.message(\n `MSH-12 (version) field value '${result.value}' does not satisfy expression '${options.expression}'`,\n {\n ancestors: result ? [...result.ancestors, result.node] : [rootTree],\n place:\n result?.node?.position ||\n result?.ancestors.at(-1)?.position ||\n rootTree.position,\n }\n );\n }\n }\n);\n\nexport default hl7v2LintMessageVersion;\n"],"mappings":";;;;;AAUA,MAAM,iBAAiB,EACrB,YAAY,gBACb;AAED,MAAM,0BAA0B,SAC9B;CACE,QAAQ;CACR,KAAK;CACN,GAEA,MAAM,MAAM,SAAS;CACpB,MAAM,UAAU;EAAE,GAAG;EAAgB,GAAG;EAAM;AAG9C,KAAI,KAAK,SAAS,QAAQ;AACxB,OAAK,QACH,6CAA6C,KAAK,KAAK,YACvD;GACE,WAAW,CAAC,KAAK;GACjB,OAAO,KAAK;GACb,CACF;AACD;;CAGF,MAAM,WAAW;CAGjB,MAAM,SAAS,MAAM,UAAU,WAAW;AAE1C,KAAI,CAAC,QAAQ,SAAS,OAAO,UAAU,IAAI;AACzC,OAAK,QAAQ,uDAAuD;GAClE,WAAW,SAAS,CAAC,GAAG,OAAO,WAAW,OAAO,KAAK,GAAG,CAAC,SAAS;GACnE,OACE,QAAQ,MAAM,YACd,QAAQ,UAAU,GAAG,GAAG,EAAE,YAC1B,SAAS;GACZ,CAAC;AACF;;CAIF,IAAI,UAAU;AACd,KAAI;AACF,YAAU,UAAU,OAAO,OAAO,QAAQ,WAAW;UAC9C,aAAa;EACpB,MAAM,QAAQ,YAAY,YAAY;AACtC,OAAK,QACH,iCAAiC,OAAO,MAAM,iBAC9C;GACE,WAAW,SAAS,CAAC,GAAG,OAAO,WAAW,OAAO,KAAK,GAAG,CAAC,SAAS;GACnE,OAAO;GACP,OAAO,QAAQ,MAAM,YAAY,SAAS;GAC3C,CACF;AACD;;AAGF,KAAI,CAAC,QACH,MAAK,QACH,iCAAiC,OAAO,MAAM,iCAAiC,QAAQ,WAAW,IAClG;EACE,WAAW,SAAS,CAAC,GAAG,OAAO,WAAW,OAAO,KAAK,GAAG,CAAC,SAAS;EACnE,OACE,QAAQ,MAAM,YACd,QAAQ,UAAU,GAAG,GAAG,EAAE,YAC1B,SAAS;EACZ,CACF;EAGN"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Nodes } from \"@glion/ast\";\nimport { select, value } from \"@glion/util-query\";\nimport { satisfies } from \"@glion/util-semver\";\nimport ensureError from \"ensure-error\";\nimport { lintRule } from \"unified-lint-rule\";\n\nexport interface MessageVersionLintOptions {\n expression: string;\n}\n\nconst defaultOptions = {\n expression: \"<3.0.0 >=2.3\",\n} as const;\n\nconst messages = {\n emptyVersion:\n \"The version in `MSH-12` (Version ID) is empty; a message must declare its HL7v2 version.\",\n missingVersion:\n \"The message has no `MSH-12` (Version ID); a message must declare its HL7v2 version.\",\n notMessage: (kind: string) =>\n `The input is a ${kind}; the version can be read only from \\`MSH-12\\` (Version ID) of a whole message.`,\n unparsableVersion: (version: string) =>\n `The version in \\`MSH-12\\` (Version ID) is \\`${version}\\`; a version must be numbers separated by dots, such as \\`2.5\\` or \\`2.5.1\\`.`,\n unsupportedVersion: (version: string, expression: string) =>\n `The version in \\`MSH-12\\` (Version ID) is \\`${version}\\`; it must satisfy \\`${expression}\\`.`,\n} as const;\n\nconst hl7v2LintMessageVersion = lintRule<Nodes, MessageVersionLintOptions>(\n {\n origin: \"hl7v2-lint:message-version\",\n url: \"https://github.com/rethinkhealth/glion/tree/main/packages/lint-message-version#readme\",\n },\n (tree, file, opts) => {\n const options = { ...defaultOptions, ...opts };\n\n if (tree.type !== \"root\") {\n file.message(messages.notMessage(tree.type), {\n ancestors: [tree],\n place: tree.position,\n });\n return;\n }\n\n const field = select(tree, \"MSH-12\");\n\n if (!field) {\n file.message(messages.missingVersion, {\n ancestors: [tree],\n place: tree.position,\n });\n return;\n }\n\n const result = value(tree, \"MSH-12.1\");\n\n if (!result?.value) {\n const message = file.message(messages.emptyVersion, {\n ancestors: [...field.ancestors, field.node],\n place: field.node.position || field.ancestors.at(-1)?.position,\n });\n message.actual = \"\";\n return;\n }\n\n const ancestors = [...result.ancestors, result.node];\n const place =\n result.node.position ||\n result.ancestors.at(-1)?.position ||\n tree.position;\n\n let isValid = false;\n try {\n isValid = satisfies(result.value, options.expression);\n } catch (caughtError) {\n const message = file.message(messages.unparsableVersion(result.value), {\n ancestors,\n cause: ensureError(caughtError),\n place: result.node.position || tree.position,\n });\n message.actual = result.value;\n return;\n }\n\n if (!isValid) {\n const message = file.message(\n messages.unsupportedVersion(result.value, options.expression),\n { ancestors, place }\n );\n message.actual = result.value;\n message.expected = [options.expression];\n }\n }\n);\n\nexport default hl7v2LintMessageVersion;\n"],"mappings":";;;;;AAUA,MAAM,iBAAiB,EACrB,YAAY,gBACb;AAED,MAAM,WAAW;CACf,cACE;CACF,gBACE;CACF,aAAa,SACX,kBAAkB,KAAK;CACzB,oBAAoB,YAClB,+CAA+C,QAAQ;CACzD,qBAAqB,SAAiB,eACpC,+CAA+C,QAAQ,wBAAwB,WAAW;CAC7F;AAED,MAAM,0BAA0B,SAC9B;CACE,QAAQ;CACR,KAAK;CACN,GACA,MAAM,MAAM,SAAS;CACpB,MAAM,UAAU;EAAE,GAAG;EAAgB,GAAG;EAAM;AAE9C,KAAI,KAAK,SAAS,QAAQ;AACxB,OAAK,QAAQ,SAAS,WAAW,KAAK,KAAK,EAAE;GAC3C,WAAW,CAAC,KAAK;GACjB,OAAO,KAAK;GACb,CAAC;AACF;;CAGF,MAAM,QAAQ,OAAO,MAAM,SAAS;AAEpC,KAAI,CAAC,OAAO;AACV,OAAK,QAAQ,SAAS,gBAAgB;GACpC,WAAW,CAAC,KAAK;GACjB,OAAO,KAAK;GACb,CAAC;AACF;;CAGF,MAAM,SAAS,MAAM,MAAM,WAAW;AAEtC,KAAI,CAAC,QAAQ,OAAO;EAClB,MAAM,UAAU,KAAK,QAAQ,SAAS,cAAc;GAClD,WAAW,CAAC,GAAG,MAAM,WAAW,MAAM,KAAK;GAC3C,OAAO,MAAM,KAAK,YAAY,MAAM,UAAU,GAAG,GAAG,EAAE;GACvD,CAAC;AACF,UAAQ,SAAS;AACjB;;CAGF,MAAM,YAAY,CAAC,GAAG,OAAO,WAAW,OAAO,KAAK;CACpD,MAAM,QACJ,OAAO,KAAK,YACZ,OAAO,UAAU,GAAG,GAAG,EAAE,YACzB,KAAK;CAEP,IAAI,UAAU;AACd,KAAI;AACF,YAAU,UAAU,OAAO,OAAO,QAAQ,WAAW;UAC9C,aAAa;EACpB,MAAM,UAAU,KAAK,QAAQ,SAAS,kBAAkB,OAAO,MAAM,EAAE;GACrE;GACA,OAAO,YAAY,YAAY;GAC/B,OAAO,OAAO,KAAK,YAAY,KAAK;GACrC,CAAC;AACF,UAAQ,SAAS,OAAO;AACxB;;AAGF,KAAI,CAAC,SAAS;EACZ,MAAM,UAAU,KAAK,QACnB,SAAS,mBAAmB,OAAO,OAAO,QAAQ,WAAW,EAC7D;GAAE;GAAW;GAAO,CACrB;AACD,UAAQ,SAAS,OAAO;AACxB,UAAQ,WAAW,CAAC,QAAQ,WAAW;;EAG5C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glion/lint-message-version",
3
- "version": "0.21.0",
3
+ "version": "0.23.0",
4
4
  "description": "hl7v2-lint rule to warn when message version is not supported",
5
5
  "keywords": [
6
6
  "definition",
@@ -39,8 +39,8 @@
39
39
  "dependencies": {
40
40
  "ensure-error": "5.0.0",
41
41
  "unified-lint-rule": "3.0.1",
42
- "@glion/util-query": "0.21.0",
43
- "@glion/util-semver": "0.21.0"
42
+ "@glion/util-semver": "0.23.0",
43
+ "@glion/util-query": "0.23.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/node": "25.6.0",
@@ -52,8 +52,8 @@
52
52
  "unified": "^11.0.5",
53
53
  "vfile": "^6.0.3",
54
54
  "vitest": "4.1.11",
55
- "@glion/ast": "0.21.0",
56
- "@glion/builder": "0.21.0",
55
+ "@glion/ast": "0.23.0",
56
+ "@glion/builder": "0.23.0",
57
57
  "@glion/check-readme": "0.18.0",
58
58
  "@glion/testing": "0.18.0",
59
59
  "@glion/tsconfig": "0.18.0"