@glion/annotate-profile-fields-code-systems 0.14.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Rethink Health
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,37 @@
1
+ import type { Root } from "@glion/ast";
2
+ import type { Plugin } from "unified";
3
+ declare module "@glion/ast" {
4
+ interface FieldData {
5
+ /** Resolved UTG code system identity for this field's table reference. */
6
+ codeSystem?: {
7
+ id: string;
8
+ name: string;
9
+ title: string;
10
+ } | undefined;
11
+ }
12
+ interface FieldRepetitionData {
13
+ /** Resolved code entry for this repetition's primary value. */
14
+ code?: {
15
+ value: string;
16
+ display: string;
17
+ status: string;
18
+ } | undefined;
19
+ }
20
+ }
21
+ /**
22
+ * Unified plugin that annotates coded fields with their resolved UTG
23
+ * code system identity (on the field) and the display/status of each
24
+ * repetition's primary value (on the field-repetition).
25
+ *
26
+ * Per the HL7v2 spec, when a field has a table binding and a composite
27
+ * datatype (CWE/CNE), the table constrains CWE.1 — the first component's
28
+ * first subcomponent. This plugin reads that value from each repetition,
29
+ * resolves it against the UTG code system, and attaches:
30
+ * - `field.data.codeSystem` — code system identity (same for all reps)
31
+ * - `rep.data.code` — resolved value entry (different per rep)
32
+ *
33
+ * Requires the fields annotator to run first (preset guarantees ordering).
34
+ */
35
+ export declare const hl7v2AnnotateProfileFieldsCodeSystems: Plugin<[], Root, Root>;
36
+ export default hl7v2AnnotateProfileFieldsCodeSystems;
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,IAAI,EAAE,MAAM,YAAY,CAAC;AAIrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAYtC,OAAO,QAAQ,YAAY,CAAC;IAC1B,UAAU,SAAS;QACjB,0EAA0E;QAC1E,UAAU,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;KACtE;IACD,UAAU,mBAAmB;QAC3B,+DAA+D;QAC/D,IAAI,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;KACvE;CACF;AAUD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qCAAqC,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CA2EtE,CAAC;AAEJ,eAAe,qCAAqC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,75 @@
1
+ import { profiles } from "@glion/profiles";
2
+ import { SKIP, visit } from "@glion/util-visit";
3
+ //#region src/index.ts
4
+ /** Visit predicate: only visit field nodes that have a table reference. */
5
+ function isCodedField(node) {
6
+ return node.type === "field" && typeof node.data?.table === "string";
7
+ }
8
+ /**
9
+ * Convert a field profile table reference to a UTG code system ID.
10
+ * Field profiles use "HL70001"; UTG code systems use "v2-0001".
11
+ */
12
+ function tableIdToCodeSystemId(tableRef) {
13
+ return `v2-${tableRef.replace(/^HL7/, "")}`;
14
+ }
15
+ /**
16
+ * Unified plugin that annotates coded fields with their resolved UTG
17
+ * code system identity (on the field) and the display/status of each
18
+ * repetition's primary value (on the field-repetition).
19
+ *
20
+ * Per the HL7v2 spec, when a field has a table binding and a composite
21
+ * datatype (CWE/CNE), the table constrains CWE.1 — the first component's
22
+ * first subcomponent. This plugin reads that value from each repetition,
23
+ * resolves it against the UTG code system, and attaches:
24
+ * - `field.data.codeSystem` — code system identity (same for all reps)
25
+ * - `rep.data.code` — resolved value entry (different per rep)
26
+ *
27
+ * Requires the fields annotator to run first (preset guarantees ordering).
28
+ */
29
+ const hl7v2AnnotateProfileFieldsCodeSystems = () => async (tree, file) => {
30
+ const tableRefs = /* @__PURE__ */ new Set();
31
+ visit(tree, isCodedField, (node) => {
32
+ tableRefs.add(node.data.table);
33
+ });
34
+ const codeSystems = /* @__PURE__ */ new Map();
35
+ const entries = [...tableRefs].map((ref) => [ref, tableIdToCodeSystemId(ref)]);
36
+ const results = await Promise.allSettled(entries.map(([, csId]) => profiles.codeSystems.load(csId)));
37
+ for (let i = 0; i < results.length; i++) {
38
+ const result = results[i];
39
+ const [tableRef] = entries[i];
40
+ if (result.status === "fulfilled") codeSystems.set(tableRef, result.value);
41
+ else if (!(result.reason instanceof Error) || !result.reason.message.startsWith("Unknown ")) {
42
+ const msg = file.message(`Failed to load code system for table '${tableRef}'`);
43
+ msg.source = "hl7v2-annotate-profile-fields-code-systems";
44
+ msg.cause = result.reason;
45
+ }
46
+ }
47
+ visit(tree, isCodedField, (node) => {
48
+ const table = node.data.table;
49
+ const csDef = codeSystems.get(table);
50
+ if (!csDef) return SKIP;
51
+ node.data.codeSystem = {
52
+ id: csDef.id,
53
+ name: csDef.name,
54
+ title: csDef.title
55
+ };
56
+ for (const rep of node.children) {
57
+ const primaryValue = rep.children[0]?.children[0]?.value;
58
+ if (!primaryValue) continue;
59
+ const entry = csDef.codes.get(primaryValue);
60
+ if (!entry) continue;
61
+ if (!rep.data) rep.data = {};
62
+ rep.data.code = {
63
+ value: primaryValue,
64
+ display: entry.display,
65
+ status: entry.status
66
+ };
67
+ }
68
+ return SKIP;
69
+ });
70
+ return tree;
71
+ };
72
+ //#endregion
73
+ export { hl7v2AnnotateProfileFieldsCodeSystems as default, hl7v2AnnotateProfileFieldsCodeSystems };
74
+
75
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Field, Nodes, Root } from \"@glion/ast\";\nimport type { CodeSystemDefinition } from \"@glion/profiles\";\nimport { profiles } from \"@glion/profiles\";\nimport { SKIP, visit } from \"@glion/util-visit\";\nimport type { Plugin } from \"unified\";\nimport type { VFile } from \"vfile\";\n\n/** Visit predicate: only visit field nodes that have a table reference. */\nfunction isCodedField(node: Nodes): node is Field {\n return (\n node.type === \"field\" &&\n typeof (node.data as Record<string, unknown> | undefined)?.table ===\n \"string\"\n );\n}\n\ndeclare module \"@glion/ast\" {\n interface FieldData {\n /** Resolved UTG code system identity for this field's table reference. */\n codeSystem?: { id: string; name: string; title: string } | undefined;\n }\n interface FieldRepetitionData {\n /** Resolved code entry for this repetition's primary value. */\n code?: { value: string; display: string; status: string } | undefined;\n }\n}\n\n/**\n * Convert a field profile table reference to a UTG code system ID.\n * Field profiles use \"HL70001\"; UTG code systems use \"v2-0001\".\n */\nfunction tableIdToCodeSystemId(tableRef: string): string {\n return `v2-${tableRef.replace(/^HL7/, \"\")}`;\n}\n\n/**\n * Unified plugin that annotates coded fields with their resolved UTG\n * code system identity (on the field) and the display/status of each\n * repetition's primary value (on the field-repetition).\n *\n * Per the HL7v2 spec, when a field has a table binding and a composite\n * datatype (CWE/CNE), the table constrains CWE.1 — the first component's\n * first subcomponent. This plugin reads that value from each repetition,\n * resolves it against the UTG code system, and attaches:\n * - `field.data.codeSystem` — code system identity (same for all reps)\n * - `rep.data.code` — resolved value entry (different per rep)\n *\n * Requires the fields annotator to run first (preset guarantees ordering).\n */\nexport const hl7v2AnnotateProfileFieldsCodeSystems: Plugin<[], Root, Root> =\n () => async (tree: Root, file: VFile) => {\n // Collect table references from field.data.table (set by fields annotator)\n const tableRefs = new Set<string>();\n visit(tree, isCodedField, (node) => {\n tableRefs.add((node.data as Record<string, unknown>).table as string);\n });\n\n // Resolve UTG code systems in parallel\n const codeSystems = new Map<string, CodeSystemDefinition>();\n const entries = [...tableRefs].map(\n (ref) => [ref, tableIdToCodeSystemId(ref)] as const\n );\n const results = await Promise.allSettled(\n entries.map(([, csId]) => profiles.codeSystems.load(csId))\n );\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i]!;\n const [tableRef] = entries[i]!;\n if (result.status === \"fulfilled\") {\n codeSystems.set(tableRef, result.value);\n } else if (\n !(result.reason instanceof Error) ||\n !result.reason.message.startsWith(\"Unknown \")\n ) {\n const msg = file.message(\n `Failed to load code system for table '${tableRef}'`\n );\n msg.source = \"hl7v2-annotate-profile-fields-code-systems\";\n msg.cause = result.reason;\n }\n }\n\n // Annotate: codeSystem on field, resolved code on each repetition\n visit(tree, isCodedField, (node) => {\n const table = (node.data as Record<string, unknown>).table as string;\n const csDef = codeSystems.get(table);\n if (!csDef) {\n return SKIP;\n }\n\n // Code system identity on the field (same for all repetitions)\n (node.data as Record<string, unknown>).codeSystem = {\n id: csDef.id,\n name: csDef.name,\n title: csDef.title,\n };\n\n // Resolved value on each repetition\n for (const rep of node.children) {\n const primaryValue = rep.children[0]?.children[0]?.value;\n if (!primaryValue) {\n continue;\n }\n\n const entry = csDef.codes.get(primaryValue);\n if (!entry) {\n continue;\n }\n\n if (!rep.data) {\n rep.data = {};\n }\n rep.data.code = {\n value: primaryValue,\n display: entry.display,\n status: entry.status,\n };\n }\n\n return SKIP;\n });\n\n return tree;\n };\n\nexport default hl7v2AnnotateProfileFieldsCodeSystems;\n"],"mappings":";;;;AAQA,SAAS,aAAa,MAA4B;AAChD,QACE,KAAK,SAAS,WACd,OAAQ,KAAK,MAA8C,UACzD;;;;;;AAmBN,SAAS,sBAAsB,UAA0B;AACvD,QAAO,MAAM,SAAS,QAAQ,QAAQ,GAAG;;;;;;;;;;;;;;;;AAiB3C,MAAa,8CACL,OAAO,MAAY,SAAgB;CAEvC,MAAM,4BAAY,IAAI,KAAa;AACnC,OAAM,MAAM,eAAe,SAAS;AAClC,YAAU,IAAK,KAAK,KAAiC,MAAgB;GACrE;CAGF,MAAM,8BAAc,IAAI,KAAmC;CAC3D,MAAM,UAAU,CAAC,GAAG,UAAU,CAAC,KAC5B,QAAQ,CAAC,KAAK,sBAAsB,IAAI,CAAC,CAC3C;CACD,MAAM,UAAU,MAAM,QAAQ,WAC5B,QAAQ,KAAK,GAAG,UAAU,SAAS,YAAY,KAAK,KAAK,CAAC,CAC3D;AAED,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,SAAS,QAAQ;EACvB,MAAM,CAAC,YAAY,QAAQ;AAC3B,MAAI,OAAO,WAAW,YACpB,aAAY,IAAI,UAAU,OAAO,MAAM;WAEvC,EAAE,OAAO,kBAAkB,UAC3B,CAAC,OAAO,OAAO,QAAQ,WAAW,WAAW,EAC7C;GACA,MAAM,MAAM,KAAK,QACf,yCAAyC,SAAS,GACnD;AACD,OAAI,SAAS;AACb,OAAI,QAAQ,OAAO;;;AAKvB,OAAM,MAAM,eAAe,SAAS;EAClC,MAAM,QAAS,KAAK,KAAiC;EACrD,MAAM,QAAQ,YAAY,IAAI,MAAM;AACpC,MAAI,CAAC,MACH,QAAO;AAIR,OAAK,KAAiC,aAAa;GAClD,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,OAAO,MAAM;GACd;AAGD,OAAK,MAAM,OAAO,KAAK,UAAU;GAC/B,MAAM,eAAe,IAAI,SAAS,IAAI,SAAS,IAAI;AACnD,OAAI,CAAC,aACH;GAGF,MAAM,QAAQ,MAAM,MAAM,IAAI,aAAa;AAC3C,OAAI,CAAC,MACH;AAGF,OAAI,CAAC,IAAI,KACP,KAAI,OAAO,EAAE;AAEf,OAAI,KAAK,OAAO;IACd,OAAO;IACP,SAAS,MAAM;IACf,QAAQ,MAAM;IACf;;AAGH,SAAO;GACP;AAEF,QAAO"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@glion/annotate-profile-fields-code-systems",
3
+ "version": "0.14.1",
4
+ "description": "Unified plugin to annotate HL7v2 field-level coded values with UTG code system metadata",
5
+ "keywords": [
6
+ "annotate",
7
+ "code-system",
8
+ "health",
9
+ "healthcare",
10
+ "hl7",
11
+ "hl7v2",
12
+ "nodejs",
13
+ "plugin",
14
+ "profile",
15
+ "typescript",
16
+ "unified",
17
+ "utg"
18
+ ],
19
+ "homepage": "https://glion.dev",
20
+ "license": "MIT",
21
+ "author": {
22
+ "name": "Melek Somai",
23
+ "email": "melek@rethinkhealth.io"
24
+ },
25
+ "repository": "rethinkhealth/glion.git",
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "type": "module",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": "./dist/index.js"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "dependencies": {
38
+ "unified": "11.0.5",
39
+ "vfile": "6.0.3",
40
+ "@glion/ast": "0.14.1",
41
+ "@glion/profiles": "0.14.1",
42
+ "@glion/util-visit": "0.14.1"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^25.5.0",
46
+ "@vitest/coverage-v8": "4.1.2",
47
+ "tsdown": "0.21.7",
48
+ "typescript": "^5.9.3",
49
+ "vitest": "4.1.2",
50
+ "@glion/annotate-profile-fields": "0.14.1",
51
+ "@glion/annotate-profile-context": "0.14.1",
52
+ "@glion/tsconfig": "0.0.1",
53
+ "@glion/testing": "0.0.2",
54
+ "@glion/builder": "0.14.1"
55
+ },
56
+ "engines": {
57
+ "node": ">=18"
58
+ },
59
+ "scripts": {
60
+ "build": "tsdown && tsc --emitDeclarationOnly",
61
+ "check-types": "tsc --noEmit",
62
+ "bench": "vitest bench --run",
63
+ "test": "vitest run",
64
+ "test:coverage": "vitest run --coverage",
65
+ "test:watch": "vitest"
66
+ }
67
+ }