@rethinkhealth/hl7v2-utils 0.11.0 → 0.13.1

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 CHANGED
@@ -1,239 +1,199 @@
1
- // src/constants.ts
2
- var DEFAULT_DELIMITERS = {
3
- component: "^",
4
- escape: "\\",
5
- field: "|",
6
- repetition: "~",
7
- segment: "\r",
8
- subcomponent: "&"
1
+ //#region src/constants.ts
2
+ const DEFAULT_DELIMITERS = {
3
+ component: "^",
4
+ escape: "\\",
5
+ field: "|",
6
+ repetition: "~",
7
+ segment: "\r",
8
+ subcomponent: "&"
9
9
  };
10
-
11
- // src/utils.ts
10
+ //#endregion
11
+ //#region src/utils.ts
12
+ /**
13
+ * Check if an HL7v2 AST node is semantically empty.
14
+ *
15
+ * A node is empty when it contains no meaningful data — no subcomponent
16
+ * anywhere in its subtree has a non-empty string value.
17
+ *
18
+ * This follows the HL7v2 specification (Chapter 2, Section 2.5.3) and
19
+ * Conformance Methodology R1 (2019) definition of "non-empty value":
20
+ * at least one character must be a non-whitespace character.
21
+ *
22
+ * ## HL7v2 emptiness semantics
23
+ *
24
+ * | Encoding | Wire form | isEmpty? | Meaning |
25
+ * |-------------|---------------|----------|----------------------------------|
26
+ * | `value` | `\|value\|` | `false` | Field has data |
27
+ * | `^DOE` | `\|^DOE\|` | `false` | Component 2 has data |
28
+ * | `~value` | `\|~value\|` | `false` | Repetition 2 has data |
29
+ * | `""` | `\|""\|` | `false` | Explicit null (delete indicator) |
30
+ * | (empty) | `\|\|` | `true` | Not present |
31
+ * | `^^` | `\|^^\|` | `true` | Empty components |
32
+ * | `~` | `\|~\|` | `true` | Empty repetitions |
33
+ * | `~^^` | `\|~^^\|` | `true` | Empty reps with empty components |
34
+ *
35
+ * @param node - The HL7v2 AST node to check (or null/undefined)
36
+ * @returns `true` if the node has no meaningful data
37
+ */
12
38
  function isEmptyNode(node) {
13
- if (!node) {
14
- return true;
15
- }
16
- if ("value" in node) {
17
- return !node.value || node.value.trim() === "";
18
- }
19
- if ("children" in node) {
20
- if (!node.children || node.children.length === 0) {
21
- return true;
22
- }
23
- return node.children.every((child) => isEmptyNode(child));
24
- }
25
- return false;
39
+ if (!node) return true;
40
+ if ("value" in node) return !node.value || node.value.trim() === "";
41
+ if ("children" in node) {
42
+ if (!node.children || node.children.length === 0) return true;
43
+ return node.children.every((child) => isEmptyNode(child));
44
+ }
45
+ return false;
26
46
  }
47
+ /**
48
+ * Calculate the byte length of any HL7v2 AST node.
49
+ *
50
+ * For literal nodes (Subcomponent), returns the UTF-8 byte length of the value.
51
+ * For parent nodes, recursively calculates the length of all children. Delimiters are NOT included.
52
+ *
53
+ * @param node - The HL7v2 AST node to measure
54
+ * @returns The total byte length of the node content
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const field: Field = { type: "field", children: [...] };
59
+ * const length = getByteLength(field); // e.g., 42
60
+ * ```
61
+ */
27
62
  function getByteLength(node) {
28
- if (!node) {
29
- return 0;
30
- }
31
- if ("value" in node) {
32
- return Buffer.byteLength(node.value, "utf8");
33
- }
34
- const nameLength = node.type === "segment" ? Buffer.byteLength(node.name, "utf8") : 0;
35
- return nameLength + node.children.reduce((total, child) => total + getByteLength(child), 0);
63
+ if (!node) return 0;
64
+ if ("value" in node) return Buffer.byteLength(node.value, "utf8");
65
+ return (node.type === "segment" ? Buffer.byteLength(node.name, "utf8") : 0) + node.children.reduce((total, child) => total + getByteLength(child), 0);
36
66
  }
67
+ /**
68
+ * Calculate the string length of any HL7v2 AST node.
69
+ *
70
+ * For literal nodes (Subcomponent), returns `value.length`.
71
+ * For parent nodes, recursively calculates the length of all children. Delimiters are NOT included.
72
+ *
73
+ * Note: Returns JavaScript string length (UTF-16 code units). For UTF-8 byte
74
+ * length (e.g., for wire protocol), use `getByteLength` instead.
75
+ *
76
+ * @param node - The HL7v2 AST node to measure
77
+ * @returns The total string length of the node content
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * const field: Field = { type: "field", children: [...] };
82
+ * const length = getLength(field); // e.g., 42
83
+ * ```
84
+ */
37
85
  function getLength(node) {
38
- if (!node) {
39
- return 0;
40
- }
41
- if ("value" in node) {
42
- return node.value.length;
43
- }
44
- const nameLength = node.type === "segment" ? node.name.length : 0;
45
- return nameLength + node.children.reduce((total, child) => total + getLength(child), 0);
86
+ if (!node) return 0;
87
+ if ("value" in node) return node.value.length;
88
+ return (node.type === "segment" ? node.name.length : 0) + node.children.reduce((total, child) => total + getLength(child), 0);
46
89
  }
47
-
48
- // src/constraints.ts
49
- var OptionalityCode = {
50
- /**
51
- * Backward Compatible
52
- *
53
- * There are no implementation requirements. The “B” usage indicates that the
54
- * element is retained for backwards compatibility of the element. Another
55
- * usage indicator may be assigned in a derived profile.
56
- */
57
- BackwardCompatible: "B",
58
- /**
59
- * Undeclared / Conditional.
60
- *
61
- * There are no implementation requirements. The “C” usage designation is a
62
- * placeholder indicating that the usage for this element has not yet been
63
- * specified.
64
- */
65
- Conditional: "C",
66
- /**
67
- * Not Supported.
68
- *
69
- * There are no implementation requirements. The application must not value an
70
- * element with an “X” usage designation.
71
- */
72
- NotSupported: "X",
73
- /**
74
- * Optional
75
- *
76
- * There are no implementation requirements. The “O” usage designation is a
77
- * placeholder indicating that the usage for this element has not yet been
78
- * specified.
79
- */
80
- Optional: "O",
81
- /**
82
- * Required
83
- */
84
- Required: "R",
85
- /**
86
- * Required, but may be empty.
87
- *
88
- * The use of the RE usage code is qualified with the “if data is known”
89
- * clause. The sender must interpret the clause as “the capability must always
90
- * be supported, and data must always be sent if known”. To clarify, the
91
- * sender does not determine whether the data should be sent; to be conformant
92
- * to the rule, the data must be sent. There is a misconception where the RE
93
- * usage is interpreted as “the capability must always be supported, and data
94
- * may or may not be sent even when known based on a condition external to the
95
- * profile specification”.
96
- *
97
- * The receiving application must process in a meaningful way the information
98
- * conveyed by an element with an “RE” usage designation.
99
- * The receiving application must process the message if the element is omitted
100
- * (that is, an exception must not be raised because the element is missing). A
101
- * receiving application must not raise an exception due to the presence of a
102
- * required element.
103
- */
104
- RequiredOrEmpty: "RE",
105
- /**
106
- * Withdrawn
107
- *
108
- * The element has been withdrawn from the standard. There are no
109
- * implementation requirements. The application must not value an element with
110
- * a "W" usage designation.
111
- */
112
- Withdrawn: "W"
90
+ //#endregion
91
+ //#region src/constraints.ts
92
+ const OptionalityCode = {
93
+ BackwardCompatible: "B",
94
+ Conditional: "C",
95
+ NotSupported: "X",
96
+ Optional: "O",
97
+ Required: "R",
98
+ RequiredOrEmpty: "RE",
99
+ Withdrawn: "W"
113
100
  };
101
+ /**
102
+ * Checks if a field satisfies the cardinality constraint.
103
+ */
114
104
  function checkCardinality(node, min, max) {
115
- if (min < 0 || max !== "*" && max < 0) {
116
- throw new Error("Min and max lengths must be non-negative");
117
- }
118
- if (max !== "*" && min > max) {
119
- throw new Error("Min length cannot be greater than max length");
120
- }
121
- const count = node?.children ? node.children.length : 0;
122
- if (count < min) {
123
- return {
124
- error: {
125
- actual: count,
126
- code: "CARDINALITY_UNDERFLOW",
127
- expected: min,
128
- message: `has ${count} repetitions but requires at least ${min}`
129
- },
130
- ok: false
131
- };
132
- }
133
- if (max !== "*" && count > max) {
134
- return {
135
- error: {
136
- actual: count,
137
- code: "CARDINALITY_OVERFLOW",
138
- expected: max,
139
- message: `has ${count} repetitions but allows at most ${max}`
140
- },
141
- ok: false
142
- };
143
- }
144
- return { ok: true };
105
+ if (min < 0 || max !== "*" && max < 0) throw new Error("Min and max lengths must be non-negative");
106
+ if (max !== "*" && min > max) throw new Error("Min length cannot be greater than max length");
107
+ const count = node?.children ? node.children.length : 0;
108
+ if (count < min) return {
109
+ error: {
110
+ actual: count,
111
+ code: "CARDINALITY_UNDERFLOW",
112
+ expected: min,
113
+ message: `has ${count} repetitions but requires at least ${min}`
114
+ },
115
+ ok: false
116
+ };
117
+ if (max !== "*" && count > max) return {
118
+ error: {
119
+ actual: count,
120
+ code: "CARDINALITY_OVERFLOW",
121
+ expected: max,
122
+ message: `has ${count} repetitions but allows at most ${max}`
123
+ },
124
+ ok: false
125
+ };
126
+ return { ok: true };
145
127
  }
128
+ /**
129
+ * Checks if a node satisfies the length constraint.
130
+ */
146
131
  function checkLength(node, max, min = 0) {
147
- if (min < 0 || max < 0) {
148
- throw new Error("Min and max lengths must be non-negative");
149
- }
150
- if (min > max) {
151
- throw new Error("Min length cannot be greater than max length");
152
- }
153
- const length = getLength(node);
154
- if (length < min) {
155
- return {
156
- error: {
157
- actual: length,
158
- code: "LENGTH_UNDERFLOW",
159
- expected: min,
160
- message: `has length ${length} but requires at least ${min}`
161
- },
162
- ok: false
163
- };
164
- }
165
- if (length > max) {
166
- return {
167
- error: {
168
- actual: length,
169
- code: "LENGTH_OVERFLOW",
170
- expected: max,
171
- message: `has length ${length} but allows at most ${max}`
172
- },
173
- ok: false
174
- };
175
- }
176
- return { ok: true };
132
+ if (min < 0 || max < 0) throw new Error("Min and max lengths must be non-negative");
133
+ if (min > max) throw new Error("Min length cannot be greater than max length");
134
+ const length = getLength(node);
135
+ if (length < min) return {
136
+ error: {
137
+ actual: length,
138
+ code: "LENGTH_UNDERFLOW",
139
+ expected: min,
140
+ message: `has length ${length} but requires at least ${min}`
141
+ },
142
+ ok: false
143
+ };
144
+ if (length > max) return {
145
+ error: {
146
+ actual: length,
147
+ code: "LENGTH_OVERFLOW",
148
+ expected: max,
149
+ message: `has length ${length} but allows at most ${max}`
150
+ },
151
+ ok: false
152
+ };
153
+ return { ok: true };
177
154
  }
155
+ /**
156
+ * Checks if a node satisfies the optionality constraint.
157
+ */
178
158
  function checkOptionality(node, optionality) {
179
- const code = optionality.toUpperCase();
180
- switch (code) {
181
- case OptionalityCode.Required: {
182
- if (!node) {
183
- return {
184
- error: {
185
- code: "MISSING",
186
- expected: "R",
187
- message: "is required but missing"
188
- },
189
- ok: false
190
- };
191
- }
192
- if (isEmptyNode(node)) {
193
- return {
194
- error: {
195
- code: "EMPTY",
196
- expected: "R",
197
- message: "is required but empty"
198
- },
199
- ok: false
200
- };
201
- }
202
- return { ok: true };
203
- }
204
- case OptionalityCode.NotSupported: {
205
- if (node && !isEmptyNode(node)) {
206
- return {
207
- error: {
208
- code: "UNEXPECTED_CONTENT",
209
- expected: "X",
210
- message: "is not supported but present"
211
- },
212
- ok: false
213
- };
214
- }
215
- return { ok: true };
216
- }
217
- case OptionalityCode.RequiredOrEmpty:
218
- case OptionalityCode.Optional:
219
- case OptionalityCode.Conditional:
220
- case OptionalityCode.BackwardCompatible:
221
- case OptionalityCode.Withdrawn: {
222
- return { ok: true };
223
- }
224
- default: {
225
- return { ok: true };
226
- }
227
- }
159
+ switch (optionality.toUpperCase()) {
160
+ case OptionalityCode.Required:
161
+ if (!node) return {
162
+ error: {
163
+ code: "MISSING",
164
+ expected: "R",
165
+ message: "is required but missing"
166
+ },
167
+ ok: false
168
+ };
169
+ if (isEmptyNode(node)) return {
170
+ error: {
171
+ code: "EMPTY",
172
+ expected: "R",
173
+ message: "is required but empty"
174
+ },
175
+ ok: false
176
+ };
177
+ return { ok: true };
178
+ case OptionalityCode.NotSupported:
179
+ if (node && !isEmptyNode(node)) return {
180
+ error: {
181
+ code: "UNEXPECTED_CONTENT",
182
+ expected: "X",
183
+ message: "is not supported but present"
184
+ },
185
+ ok: false
186
+ };
187
+ return { ok: true };
188
+ case OptionalityCode.RequiredOrEmpty:
189
+ case OptionalityCode.Optional:
190
+ case OptionalityCode.Conditional:
191
+ case OptionalityCode.BackwardCompatible:
192
+ case OptionalityCode.Withdrawn: return { ok: true };
193
+ default: return { ok: true };
194
+ }
228
195
  }
229
- export {
230
- DEFAULT_DELIMITERS,
231
- OptionalityCode,
232
- checkCardinality,
233
- checkLength,
234
- checkOptionality,
235
- getByteLength,
236
- getLength,
237
- isEmptyNode
238
- };
196
+ //#endregion
197
+ export { DEFAULT_DELIMITERS, OptionalityCode, checkCardinality, checkLength, checkOptionality, getByteLength, getLength, isEmptyNode };
198
+
239
199
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/utils.ts","../src/constraints.ts"],"sourcesContent":["// -------------\n// Delimiters\n// -------------\n\nexport const DEFAULT_DELIMITERS = {\n component: \"^\",\n escape: \"\\\\\",\n field: \"|\",\n repetition: \"~\",\n segment: \"\\r\",\n subcomponent: \"&\",\n};\n","import type { Nodes } from \"@rethinkhealth/hl7v2-ast\";\n\n// -------------\n// General\n// -------------\n\n/**\n * Check if an HL7v2 AST node is semantically empty.\n *\n * A node is empty when it contains no meaningful data — no subcomponent\n * anywhere in its subtree has a non-empty string value.\n *\n * This follows the HL7v2 specification (Chapter 2, Section 2.5.3) and\n * Conformance Methodology R1 (2019) definition of \"non-empty value\":\n * at least one character must be a non-whitespace character.\n *\n * ## HL7v2 emptiness semantics\n *\n * | Encoding | Wire form | isEmpty? | Meaning |\n * |-------------|---------------|----------|----------------------------------|\n * | `value` | `\\|value\\|` | `false` | Field has data |\n * | `^DOE` | `\\|^DOE\\|` | `false` | Component 2 has data |\n * | `~value` | `\\|~value\\|` | `false` | Repetition 2 has data |\n * | `\"\"` | `\\|\"\"\\|` | `false` | Explicit null (delete indicator) |\n * | (empty) | `\\|\\|` | `true` | Not present |\n * | `^^` | `\\|^^\\|` | `true` | Empty components |\n * | `~` | `\\|~\\|` | `true` | Empty repetitions |\n * | `~^^` | `\\|~^^\\|` | `true` | Empty reps with empty components |\n *\n * @param node - The HL7v2 AST node to check (or null/undefined)\n * @returns `true` if the node has no meaningful data\n */\nexport function isEmptyNode(node?: Nodes | null | undefined): boolean {\n if (!node) {\n return true;\n }\n\n // Leaf node (Subcomponent): check its string value\n if (\"value\" in node) {\n return !node.value || node.value.trim() === \"\";\n }\n\n // Parent node: empty if ALL children are empty\n if (\"children\" in node) {\n if (!node.children || node.children.length === 0) {\n return true;\n }\n\n return node.children.every((child) => isEmptyNode(child));\n }\n\n // Fallback: consider unknown node as non-empty\n return false;\n}\n\n// -------------\n// Byte Length\n// -------------\n\n/**\n * Calculate the byte length of any HL7v2 AST node.\n *\n * For literal nodes (Subcomponent), returns the UTF-8 byte length of the value.\n * For parent nodes, recursively calculates the length of all children. Delimiters are NOT included.\n *\n * @param node - The HL7v2 AST node to measure\n * @returns The total byte length of the node content\n *\n * @example\n * ```ts\n * const field: Field = { type: \"field\", children: [...] };\n * const length = getByteLength(field); // e.g., 42\n * ```\n */\nexport function getByteLength(node?: Nodes | null | undefined): number {\n if (!node) {\n return 0;\n }\n\n if (\"value\" in node) {\n return Buffer.byteLength(node.value, \"utf8\");\n }\n\n const nameLength =\n node.type === \"segment\" ? Buffer.byteLength(node.name, \"utf8\") : 0;\n\n return (\n nameLength +\n node.children.reduce((total, child) => total + getByteLength(child), 0)\n );\n}\n\n// -------------\n// Length\n// -------------\n\n/**\n * Calculate the string length of any HL7v2 AST node.\n *\n * For literal nodes (Subcomponent), returns `value.length`.\n * For parent nodes, recursively calculates the length of all children. Delimiters are NOT included.\n *\n * Note: Returns JavaScript string length (UTF-16 code units). For UTF-8 byte\n * length (e.g., for wire protocol), use `getByteLength` instead.\n *\n * @param node - The HL7v2 AST node to measure\n * @returns The total string length of the node content\n *\n * @example\n * ```ts\n * const field: Field = { type: \"field\", children: [...] };\n * const length = getLength(field); // e.g., 42\n * ```\n */\nexport function getLength(node?: Nodes | null | undefined): number {\n if (!node) {\n return 0;\n }\n\n if (\"value\" in node) {\n return node.value.length;\n }\n\n const nameLength = node.type === \"segment\" ? node.name.length : 0;\n\n return (\n nameLength +\n node.children.reduce((total, child) => total + getLength(child), 0)\n );\n}\n","import type { Field, Nodes } from \"@rethinkhealth/hl7v2-ast\";\n\nimport { getLength, isEmptyNode } from \"./utils\";\n\nexport type ValidationErrorCode =\n // Constraints\n | \"MISSING\"\n | \"EMPTY\"\n | \"UNEXPECTED_CONTENT\"\n | \"CARDINALITY_UNDERFLOW\"\n | \"CARDINALITY_OVERFLOW\"\n | \"LENGTH_UNDERFLOW\"\n | \"LENGTH_OVERFLOW\"\n // Value Sets\n | \"VALUE_NOT_IN_TABLE\";\n\nexport interface ValidationError {\n code: ValidationErrorCode;\n message: string;\n expected?: string | number | Array<string | number>;\n actual?: string | number | Array<string | number>;\n}\n\nexport interface ValidationSuccess {\n ok: true;\n}\n\nexport interface ValidationFailure {\n ok: false;\n error: ValidationError;\n}\n\nexport type ValidationResult = ValidationSuccess | ValidationFailure;\n\nexport const OptionalityCode = {\n /**\n * Backward Compatible\n *\n * There are no implementation requirements. The “B” usage indicates that the\n * element is retained for backwards compatibility of the element. Another\n * usage indicator may be assigned in a derived profile.\n */\n BackwardCompatible: \"B\",\n\n /**\n * Undeclared / Conditional.\n *\n * There are no implementation requirements. The “C” usage designation is a\n * placeholder indicating that the usage for this element has not yet been\n * specified.\n */\n Conditional: \"C\",\n\n /**\n * Not Supported.\n *\n * There are no implementation requirements. The application must not value an\n * element with an “X” usage designation.\n */\n NotSupported: \"X\",\n\n /**\n * Optional\n *\n * There are no implementation requirements. The “O” usage designation is a\n * placeholder indicating that the usage for this element has not yet been\n * specified.\n */\n Optional: \"O\",\n\n /**\n * Required\n */\n Required: \"R\",\n\n /**\n * Required, but may be empty.\n *\n * The use of the RE usage code is qualified with the “if data is known”\n * clause. The sender must interpret the clause as “the capability must always\n * be supported, and data must always be sent if known”. To clarify, the\n * sender does not determine whether the data should be sent; to be conformant\n * to the rule, the data must be sent. There is a misconception where the RE\n * usage is interpreted as “the capability must always be supported, and data\n * may or may not be sent even when known based on a condition external to the\n * profile specification”.\n *\n * The receiving application must process in a meaningful way the information\n * conveyed by an element with an “RE” usage designation.\n * The receiving application must process the message if the element is omitted\n * (that is, an exception must not be raised because the element is missing). A\n * receiving application must not raise an exception due to the presence of a\n * required element.\n */\n RequiredOrEmpty: \"RE\",\n\n /**\n * Withdrawn\n *\n * The element has been withdrawn from the standard. There are no\n * implementation requirements. The application must not value an element with\n * a \"W\" usage designation.\n */\n Withdrawn: \"W\",\n} as const;\n\nexport type OptionalityCode =\n (typeof OptionalityCode)[keyof typeof OptionalityCode];\n\n/**\n * Checks if a field satisfies the cardinality constraint.\n */\nexport function checkCardinality(\n node: Field | undefined,\n min: number,\n max: number | \"*\"\n): ValidationResult {\n if (min < 0 || (max !== \"*\" && max < 0)) {\n throw new Error(\"Min and max lengths must be non-negative\");\n }\n\n if (max !== \"*\" && min > max) {\n throw new Error(\"Min length cannot be greater than max length\");\n }\n\n const count = node?.children ? node.children.length : 0;\n\n if (count < min) {\n return {\n error: {\n actual: count,\n code: \"CARDINALITY_UNDERFLOW\",\n expected: min,\n message: `has ${count} repetitions but requires at least ${min}`,\n },\n ok: false,\n };\n }\n\n if (max !== \"*\" && count > max) {\n return {\n error: {\n actual: count,\n code: \"CARDINALITY_OVERFLOW\",\n expected: max,\n message: `has ${count} repetitions but allows at most ${max}`,\n },\n ok: false,\n };\n }\n\n return { ok: true };\n}\n\n/**\n * Checks if a node satisfies the length constraint.\n */\nexport function checkLength(\n node: Nodes | undefined,\n max: number,\n min = 0\n): ValidationResult {\n if (min < 0 || max < 0) {\n throw new Error(\"Min and max lengths must be non-negative\");\n }\n\n if (min > max) {\n throw new Error(\"Min length cannot be greater than max length\");\n }\n\n const length = getLength(node);\n\n if (length < min) {\n return {\n error: {\n actual: length,\n code: \"LENGTH_UNDERFLOW\",\n expected: min,\n message: `has length ${length} but requires at least ${min}`,\n },\n ok: false,\n };\n }\n\n if (length > max) {\n return {\n error: {\n actual: length,\n code: \"LENGTH_OVERFLOW\",\n expected: max,\n message: `has length ${length} but allows at most ${max}`,\n },\n ok: false,\n };\n }\n\n return { ok: true };\n}\n\n/**\n * Checks if a node satisfies the optionality constraint.\n */\nexport function checkOptionality(\n node: Nodes | undefined,\n optionality: OptionalityCode | string\n): ValidationResult {\n const code = optionality.toUpperCase();\n\n switch (code) {\n case OptionalityCode.Required: {\n if (!node) {\n return {\n error: {\n code: \"MISSING\",\n expected: \"R\",\n message: \"is required but missing\",\n },\n ok: false,\n };\n }\n if (isEmptyNode(node)) {\n return {\n error: {\n code: \"EMPTY\",\n expected: \"R\",\n message: \"is required but empty\",\n },\n ok: false,\n };\n }\n return { ok: true };\n }\n\n case OptionalityCode.NotSupported: {\n if (node && !isEmptyNode(node)) {\n return {\n error: {\n code: \"UNEXPECTED_CONTENT\",\n expected: \"X\",\n message: \"is not supported but present\",\n },\n ok: false,\n };\n }\n return { ok: true };\n }\n\n case OptionalityCode.RequiredOrEmpty:\n case OptionalityCode.Optional:\n case OptionalityCode.Conditional:\n case OptionalityCode.BackwardCompatible:\n case OptionalityCode.Withdrawn: {\n return { ok: true };\n }\n\n default: {\n return { ok: true };\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/constants.ts","../src/utils.ts","../src/constraints.ts"],"sourcesContent":["// -------------\n// Delimiters\n// -------------\n\nexport const DEFAULT_DELIMITERS = {\n component: \"^\",\n escape: \"\\\\\",\n field: \"|\",\n repetition: \"~\",\n segment: \"\\r\",\n subcomponent: \"&\",\n};\n","import type { Nodes } from \"@rethinkhealth/hl7v2-ast\";\n\n// -------------\n// General\n// -------------\n\n/**\n * Check if an HL7v2 AST node is semantically empty.\n *\n * A node is empty when it contains no meaningful data — no subcomponent\n * anywhere in its subtree has a non-empty string value.\n *\n * This follows the HL7v2 specification (Chapter 2, Section 2.5.3) and\n * Conformance Methodology R1 (2019) definition of \"non-empty value\":\n * at least one character must be a non-whitespace character.\n *\n * ## HL7v2 emptiness semantics\n *\n * | Encoding | Wire form | isEmpty? | Meaning |\n * |-------------|---------------|----------|----------------------------------|\n * | `value` | `\\|value\\|` | `false` | Field has data |\n * | `^DOE` | `\\|^DOE\\|` | `false` | Component 2 has data |\n * | `~value` | `\\|~value\\|` | `false` | Repetition 2 has data |\n * | `\"\"` | `\\|\"\"\\|` | `false` | Explicit null (delete indicator) |\n * | (empty) | `\\|\\|` | `true` | Not present |\n * | `^^` | `\\|^^\\|` | `true` | Empty components |\n * | `~` | `\\|~\\|` | `true` | Empty repetitions |\n * | `~^^` | `\\|~^^\\|` | `true` | Empty reps with empty components |\n *\n * @param node - The HL7v2 AST node to check (or null/undefined)\n * @returns `true` if the node has no meaningful data\n */\nexport function isEmptyNode(node?: Nodes | null | undefined): boolean {\n if (!node) {\n return true;\n }\n\n // Leaf node (Subcomponent): check its string value\n if (\"value\" in node) {\n return !node.value || node.value.trim() === \"\";\n }\n\n // Parent node: empty if ALL children are empty\n if (\"children\" in node) {\n if (!node.children || node.children.length === 0) {\n return true;\n }\n\n return node.children.every((child) => isEmptyNode(child));\n }\n\n // Fallback: consider unknown node as non-empty\n return false;\n}\n\n// -------------\n// Byte Length\n// -------------\n\n/**\n * Calculate the byte length of any HL7v2 AST node.\n *\n * For literal nodes (Subcomponent), returns the UTF-8 byte length of the value.\n * For parent nodes, recursively calculates the length of all children. Delimiters are NOT included.\n *\n * @param node - The HL7v2 AST node to measure\n * @returns The total byte length of the node content\n *\n * @example\n * ```ts\n * const field: Field = { type: \"field\", children: [...] };\n * const length = getByteLength(field); // e.g., 42\n * ```\n */\nexport function getByteLength(node?: Nodes | null | undefined): number {\n if (!node) {\n return 0;\n }\n\n if (\"value\" in node) {\n return Buffer.byteLength(node.value, \"utf8\");\n }\n\n const nameLength =\n node.type === \"segment\" ? Buffer.byteLength(node.name, \"utf8\") : 0;\n\n return (\n nameLength +\n node.children.reduce((total, child) => total + getByteLength(child), 0)\n );\n}\n\n// -------------\n// Length\n// -------------\n\n/**\n * Calculate the string length of any HL7v2 AST node.\n *\n * For literal nodes (Subcomponent), returns `value.length`.\n * For parent nodes, recursively calculates the length of all children. Delimiters are NOT included.\n *\n * Note: Returns JavaScript string length (UTF-16 code units). For UTF-8 byte\n * length (e.g., for wire protocol), use `getByteLength` instead.\n *\n * @param node - The HL7v2 AST node to measure\n * @returns The total string length of the node content\n *\n * @example\n * ```ts\n * const field: Field = { type: \"field\", children: [...] };\n * const length = getLength(field); // e.g., 42\n * ```\n */\nexport function getLength(node?: Nodes | null | undefined): number {\n if (!node) {\n return 0;\n }\n\n if (\"value\" in node) {\n return node.value.length;\n }\n\n const nameLength = node.type === \"segment\" ? node.name.length : 0;\n\n return (\n nameLength +\n node.children.reduce((total, child) => total + getLength(child), 0)\n );\n}\n","import type { Field, Nodes } from \"@rethinkhealth/hl7v2-ast\";\n\nimport { getLength, isEmptyNode } from \"./utils\";\n\nexport type ValidationErrorCode =\n // Constraints\n | \"MISSING\"\n | \"EMPTY\"\n | \"UNEXPECTED_CONTENT\"\n | \"CARDINALITY_UNDERFLOW\"\n | \"CARDINALITY_OVERFLOW\"\n | \"LENGTH_UNDERFLOW\"\n | \"LENGTH_OVERFLOW\"\n // Value Sets\n | \"VALUE_NOT_IN_TABLE\";\n\nexport interface ValidationError {\n code: ValidationErrorCode;\n message: string;\n expected?: string | number | Array<string | number>;\n actual?: string | number | Array<string | number>;\n}\n\nexport interface ValidationSuccess {\n ok: true;\n}\n\nexport interface ValidationFailure {\n ok: false;\n error: ValidationError;\n}\n\nexport type ValidationResult = ValidationSuccess | ValidationFailure;\n\nexport const OptionalityCode = {\n /**\n * Backward Compatible\n *\n * There are no implementation requirements. The “B” usage indicates that the\n * element is retained for backwards compatibility of the element. Another\n * usage indicator may be assigned in a derived profile.\n */\n BackwardCompatible: \"B\",\n\n /**\n * Undeclared / Conditional.\n *\n * There are no implementation requirements. The “C” usage designation is a\n * placeholder indicating that the usage for this element has not yet been\n * specified.\n */\n Conditional: \"C\",\n\n /**\n * Not Supported.\n *\n * There are no implementation requirements. The application must not value an\n * element with an “X” usage designation.\n */\n NotSupported: \"X\",\n\n /**\n * Optional\n *\n * There are no implementation requirements. The “O” usage designation is a\n * placeholder indicating that the usage for this element has not yet been\n * specified.\n */\n Optional: \"O\",\n\n /**\n * Required\n */\n Required: \"R\",\n\n /**\n * Required, but may be empty.\n *\n * The use of the RE usage code is qualified with the “if data is known”\n * clause. The sender must interpret the clause as “the capability must always\n * be supported, and data must always be sent if known”. To clarify, the\n * sender does not determine whether the data should be sent; to be conformant\n * to the rule, the data must be sent. There is a misconception where the RE\n * usage is interpreted as “the capability must always be supported, and data\n * may or may not be sent even when known based on a condition external to the\n * profile specification”.\n *\n * The receiving application must process in a meaningful way the information\n * conveyed by an element with an “RE” usage designation.\n * The receiving application must process the message if the element is omitted\n * (that is, an exception must not be raised because the element is missing). A\n * receiving application must not raise an exception due to the presence of a\n * required element.\n */\n RequiredOrEmpty: \"RE\",\n\n /**\n * Withdrawn\n *\n * The element has been withdrawn from the standard. There are no\n * implementation requirements. The application must not value an element with\n * a \"W\" usage designation.\n */\n Withdrawn: \"W\",\n} as const;\n\nexport type OptionalityCode =\n (typeof OptionalityCode)[keyof typeof OptionalityCode];\n\n/**\n * Checks if a field satisfies the cardinality constraint.\n */\nexport function checkCardinality(\n node: Field | undefined,\n min: number,\n max: number | \"*\"\n): ValidationResult {\n if (min < 0 || (max !== \"*\" && max < 0)) {\n throw new Error(\"Min and max lengths must be non-negative\");\n }\n\n if (max !== \"*\" && min > max) {\n throw new Error(\"Min length cannot be greater than max length\");\n }\n\n const count = node?.children ? node.children.length : 0;\n\n if (count < min) {\n return {\n error: {\n actual: count,\n code: \"CARDINALITY_UNDERFLOW\",\n expected: min,\n message: `has ${count} repetitions but requires at least ${min}`,\n },\n ok: false,\n };\n }\n\n if (max !== \"*\" && count > max) {\n return {\n error: {\n actual: count,\n code: \"CARDINALITY_OVERFLOW\",\n expected: max,\n message: `has ${count} repetitions but allows at most ${max}`,\n },\n ok: false,\n };\n }\n\n return { ok: true };\n}\n\n/**\n * Checks if a node satisfies the length constraint.\n */\nexport function checkLength(\n node: Nodes | undefined,\n max: number,\n min = 0\n): ValidationResult {\n if (min < 0 || max < 0) {\n throw new Error(\"Min and max lengths must be non-negative\");\n }\n\n if (min > max) {\n throw new Error(\"Min length cannot be greater than max length\");\n }\n\n const length = getLength(node);\n\n if (length < min) {\n return {\n error: {\n actual: length,\n code: \"LENGTH_UNDERFLOW\",\n expected: min,\n message: `has length ${length} but requires at least ${min}`,\n },\n ok: false,\n };\n }\n\n if (length > max) {\n return {\n error: {\n actual: length,\n code: \"LENGTH_OVERFLOW\",\n expected: max,\n message: `has length ${length} but allows at most ${max}`,\n },\n ok: false,\n };\n }\n\n return { ok: true };\n}\n\n/**\n * Checks if a node satisfies the optionality constraint.\n */\nexport function checkOptionality(\n node: Nodes | undefined,\n optionality: OptionalityCode | string\n): ValidationResult {\n const code = optionality.toUpperCase();\n\n switch (code) {\n case OptionalityCode.Required: {\n if (!node) {\n return {\n error: {\n code: \"MISSING\",\n expected: \"R\",\n message: \"is required but missing\",\n },\n ok: false,\n };\n }\n if (isEmptyNode(node)) {\n return {\n error: {\n code: \"EMPTY\",\n expected: \"R\",\n message: \"is required but empty\",\n },\n ok: false,\n };\n }\n return { ok: true };\n }\n\n case OptionalityCode.NotSupported: {\n if (node && !isEmptyNode(node)) {\n return {\n error: {\n code: \"UNEXPECTED_CONTENT\",\n expected: \"X\",\n message: \"is not supported but present\",\n },\n ok: false,\n };\n }\n return { ok: true };\n }\n\n case OptionalityCode.RequiredOrEmpty:\n case OptionalityCode.Optional:\n case OptionalityCode.Conditional:\n case OptionalityCode.BackwardCompatible:\n case OptionalityCode.Withdrawn: {\n return { ok: true };\n }\n\n default: {\n return { ok: true };\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rethinkhealth/hl7v2-utils",
3
- "version": "0.11.0",
3
+ "version": "0.13.1",
4
4
  "description": "hl7v2 utilities",
5
5
  "keywords": [
6
6
  "health",
@@ -32,21 +32,21 @@
32
32
  "@types/node": "^25.5.0",
33
33
  "@types/unist": "^3.0.3",
34
34
  "@vitest/coverage-v8": "4.1.0",
35
- "tsup": "^8.5.1",
35
+ "tsdown": "0.21.7",
36
36
  "typescript": "^5.9.3",
37
37
  "unist-builder": "^4.0.0",
38
38
  "vfile": "^6.0.3",
39
39
  "vitest": "4.1.0",
40
- "@rethinkhealth/tsconfig": "0.0.1",
41
- "@rethinkhealth/hl7v2-ast": "0.11.0",
42
- "@rethinkhealth/testing": "0.0.2"
40
+ "@rethinkhealth/hl7v2-ast": "0.13.1",
41
+ "@rethinkhealth/testing": "0.0.2",
42
+ "@rethinkhealth/tsconfig": "0.0.1"
43
43
  },
44
44
  "engines": {
45
45
  "node": ">=18"
46
46
  },
47
47
  "packageManager": "pnpm@10.14.0",
48
48
  "scripts": {
49
- "build": "tsup && tsc --emitDeclarationOnly",
49
+ "build": "tsdown && tsc --emitDeclarationOnly",
50
50
  "check-types": "tsc --noEmit",
51
51
  "test": "vitest run",
52
52
  "test:coverage": "vitest run --coverage",