@cosyte/terminology 0.0.1 → 0.0.4
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/CHANGELOG.md +280 -7
- package/LICENSE +83 -0
- package/README.md +96 -25
- package/dist/index.cjs +66 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +348 -188
- package/dist/index.d.ts +348 -188
- package/dist/index.mjs +66 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -6
- package/vendor/ucum/NOTICE.md +48 -0
package/dist/index.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ interface Coding {
|
|
|
38
38
|
/**
|
|
39
39
|
* A concept described by one or more {@link Coding}s plus optional free text — FHIR R4
|
|
40
40
|
* `CodeableConcept`. Included so the value layer is complete for downstream consumers even though
|
|
41
|
-
*
|
|
41
|
+
* {@link ../conceptmap/translate.translate} operates on a single {@link Coding}.
|
|
42
42
|
*
|
|
43
43
|
* @example
|
|
44
44
|
* ```ts
|
|
@@ -102,7 +102,7 @@ declare function codeableConcept(init: CodeableConcept): CodeableConcept;
|
|
|
102
102
|
*
|
|
103
103
|
* **Value-free by construction.** A diagnostic carries a stable code plus, at most, a
|
|
104
104
|
* code + system + version — **never** a surrounding patient identifier or clinical narrative. A
|
|
105
|
-
* code *in patient context* can be PHI
|
|
105
|
+
* code *in patient context* can be PHI, so messages describe *structure* (a resource
|
|
106
106
|
* path, a code system), never echo arbitrary input *values*.
|
|
107
107
|
*
|
|
108
108
|
* @packageDocumentation
|
|
@@ -177,13 +177,13 @@ declare const DIAGNOSTIC_CODES: {
|
|
|
177
177
|
* code system was not supplied, an unresolvable referenced value set, or a `filter` operator the
|
|
178
178
|
* engine does not implement. Surfaced as a typed outcome that marks the expansion **incomplete**;
|
|
179
179
|
* the engine **never** fabricates a member and **never** returns a silently-empty "no members"
|
|
180
|
-
* answer for a part it could not compute (
|
|
180
|
+
* answer for a part it could not compute (a false "not a member" is a clinical error).
|
|
181
181
|
*/
|
|
182
182
|
readonly TERM_VALUESET_CANNOT_EXPAND: "TERM_VALUESET_CANNOT_EXPAND";
|
|
183
183
|
/**
|
|
184
184
|
* A **pre-computed** `ValueSet.expansion` is **incomplete** — its `total` exceeds the number of
|
|
185
|
-
* `contains` entries, or it is flagged too-costly (the VSAC `$expand` >1200-code truncation
|
|
186
|
-
*
|
|
185
|
+
* `contains` entries, or it is flagged too-costly (the VSAC `$expand` >1200-code truncation
|
|
186
|
+
* hazard). The engine **never treats a truncated expansion as complete membership**: a code
|
|
187
187
|
* absent from a truncated expansion is `undetermined`, never a confident "not a member".
|
|
188
188
|
*/
|
|
189
189
|
readonly TERM_VALUESET_EXPANSION_TRUNCATED: "TERM_VALUESET_EXPANSION_TRUNCATED";
|
|
@@ -191,7 +191,7 @@ declare const DIAGNOSTIC_CODES: {
|
|
|
191
191
|
* A UCUM unit expression is **not valid** — it does not parse against the UCUM grammar, or it
|
|
192
192
|
* names an atom absent from the vendored UCUM table. A **first-class typed outcome, never an
|
|
193
193
|
* error and never a guess**: {@link validateUcum} returns `{ valid: false, reason }`, never a
|
|
194
|
-
* coerced or "nearest" unit (the never-fabricate invariant, applied to units
|
|
194
|
+
* coerced or "nearest" unit (the never-fabricate invariant, applied to units). The
|
|
195
195
|
* `reason` is value-free (a grammar fault or an unknown-atom shape), never PHI.
|
|
196
196
|
*/
|
|
197
197
|
readonly TERM_UCUM_INVALID: "TERM_UCUM_INVALID";
|
|
@@ -199,7 +199,7 @@ declare const DIAGNOSTIC_CODES: {
|
|
|
199
199
|
* A crosswalk source code has an **authored No-Map** — the steward declares it has no valid target
|
|
200
200
|
* in the other classification (a GEM `NoDx`/`NoPCS` sentinel, or a SNOMED complex-map `447638001`
|
|
201
201
|
* "cannot be classified" category). A **first-class typed outcome, never an error and never a
|
|
202
|
-
* guess** (the never-fabricate invariant, applied to crosswalks
|
|
202
|
+
* guess** (the never-fabricate invariant, applied to crosswalks). Distinct from
|
|
203
203
|
* {@link TERM_CROSSWALK_UNMAPPED}: the source *is* in the map, and the map says "no target".
|
|
204
204
|
*/
|
|
205
205
|
readonly TERM_CROSSWALK_NO_MAP: "TERM_CROSSWALK_NO_MAP";
|
|
@@ -213,7 +213,7 @@ declare const DIAGNOSTIC_CODES: {
|
|
|
213
213
|
/**
|
|
214
214
|
* A SNOMED→ICD-10-CM complex-map group's decision needs **patient context** (an `IFA` age band or
|
|
215
215
|
* gender) the caller did not supply. The engine surfaces the candidate rules + advice and **refuses
|
|
216
|
-
* to pick a branch** it lacks the data for
|
|
216
|
+
* to pick a branch** it lacks the data for — never a silently-chosen target.
|
|
217
217
|
*/
|
|
218
218
|
readonly TERM_CROSSWALK_CONTEXT_REQUIRED: "TERM_CROSSWALK_CONTEXT_REQUIRED";
|
|
219
219
|
/**
|
|
@@ -235,17 +235,27 @@ declare const DIAGNOSTIC_CODES: {
|
|
|
235
235
|
* **silently** — they are expected, not faults.
|
|
236
236
|
*/
|
|
237
237
|
readonly TERM_RXNORM_MALFORMED_ROW: "TERM_RXNORM_MALFORMED_ROW";
|
|
238
|
+
/**
|
|
239
|
+
* An `RXCUI` appeared in the release's `SAB=RXNORM` atoms but **none of them could establish its
|
|
240
|
+
* term type**, so it is **not** in the graph. Either every atom carried a synonym-class `TTY`
|
|
241
|
+
* (`PSN`/`SY`/`TMSY`, which Appendix 5 defines as a "synonym of another TTY" and which therefore
|
|
242
|
+
* types a *name* rather than a concept) or every atom carried a `TTY` this engine does not model.
|
|
243
|
+
* The concept is skipped rather than typed from a synonym atom: an absent concept is already a
|
|
244
|
+
* first-class typed answer (`TERM_RXNORM_UNKNOWN_RXCUI`), while a concept whose term type reads
|
|
245
|
+
* `TMSY` is a fabricated claim about what a drug *is* that a caller cannot detect.
|
|
246
|
+
*/
|
|
247
|
+
readonly TERM_RXNORM_UNTYPED_CONCEPT: "TERM_RXNORM_UNTYPED_CONCEPT";
|
|
238
248
|
/**
|
|
239
249
|
* A RxNorm graph navigation was asked about an `RXCUI` **absent from the loaded release** — a
|
|
240
250
|
* first-class typed outcome, never a fabricated concept and never an empty "success" (the
|
|
241
|
-
* never-fabricate invariant, applied to the drug graph
|
|
251
|
+
* never-fabricate invariant, applied to the drug graph). Distinct from a *present*
|
|
242
252
|
* concept that simply has no edge of the requested relationship (that is a found result with empty
|
|
243
253
|
* targets).
|
|
244
254
|
*/
|
|
245
255
|
readonly TERM_RXNORM_UNKNOWN_RXCUI: "TERM_RXNORM_UNKNOWN_RXCUI";
|
|
246
256
|
/**
|
|
247
257
|
* An NDC could **not be resolved** to any `RXCUI` in the loaded RxNorm release — a typed, surfaced
|
|
248
|
-
* absence, never a guessed `RXCUI`. NDC↔RXCUI is many:1 and temporal
|
|
258
|
+
* absence, never a guessed `RXCUI`. NDC↔RXCUI is many:1 and temporal, so a resolution
|
|
249
259
|
* is always release-scoped; an NDC not present in the loaded release is this diagnostic.
|
|
250
260
|
*/
|
|
251
261
|
readonly TERM_RXNORM_NDC_UNMAPPED: "TERM_RXNORM_NDC_UNMAPPED";
|
|
@@ -295,7 +305,7 @@ declare const FATAL_CODES: {
|
|
|
295
305
|
/**
|
|
296
306
|
* An **inversion** of a directional crosswalk was requested — a forbidden operation. The GEMs and
|
|
297
307
|
* the SNOMED→ICD-10-CM map are authoritative in **one direction only**; a forward map is not the
|
|
298
|
-
* inverse of the backward map
|
|
308
|
+
* inverse of the backward map. Thrown by {@link ../crosswalk/gems.invertGem} so the
|
|
299
309
|
* never-invert refusal is a first-class, discoverable contract rather than a silent absence.
|
|
300
310
|
*/
|
|
301
311
|
readonly TERM_MAP_NOT_INVERTIBLE: "TERM_MAP_NOT_INVERTIBLE";
|
|
@@ -342,7 +352,7 @@ declare class TerminologyError extends Error {
|
|
|
342
352
|
* is the terminology-engine analogue of a parser's lenient tokenizer — liberal on load.
|
|
343
353
|
*
|
|
344
354
|
* These helpers are **value-free**: they read structure, never log or echo field *values*, so a
|
|
345
|
-
* code-in-context (which can be PHI
|
|
355
|
+
* code-in-context (which can be PHI) never flows into a message.
|
|
346
356
|
*
|
|
347
357
|
* @packageDocumentation
|
|
348
358
|
*/
|
|
@@ -427,9 +437,9 @@ declare function getNumber(obj: unknown, key: string): number | undefined;
|
|
|
427
437
|
* ecosystem uses.
|
|
428
438
|
*
|
|
429
439
|
* A code-system *identity* (the triple of canonical URI, OID, and HL7 v2 mnemonic that all name
|
|
430
|
-
* the same terminology) is a **published
|
|
431
|
-
* cited firsthand.
|
|
432
|
-
*
|
|
440
|
+
* the same terminology) is a **published identifier** for the system, not the system's code list — so
|
|
441
|
+
* it is encoded here, cited firsthand. That is where the line falls: identities are encoded; the code
|
|
442
|
+
* *lists themselves* (SNOMED CT / CPT / LOINC content) are BYO and never bundled.
|
|
433
443
|
*
|
|
434
444
|
* **Every identity below is grounded firsthand against a primary source** (verified 2026-07-21):
|
|
435
445
|
*
|
|
@@ -442,8 +452,8 @@ declare function getNumber(obj: unknown, key: string): number | undefined;
|
|
|
442
452
|
* - HL7 Table 0396 (coding-system mnemonics) — the THO `v2-0396` code system — for the mnemonics
|
|
443
453
|
* (`LN`, `SCT`, `I10C`, `RXNORM`, `UCUM`, `C4`, `NDC`, `CVX`).
|
|
444
454
|
*
|
|
445
|
-
* Identities that could not be pinned to a primary source firsthand
|
|
446
|
-
* guessed
|
|
455
|
+
* Identities that could not be pinned to a primary source firsthand are **omitted**, not
|
|
456
|
+
* guessed — notably ICD-9-CM and ICD-10-PCS, whose OID
|
|
447
457
|
* assignments were ambiguous across sources.
|
|
448
458
|
*
|
|
449
459
|
* @packageDocumentation
|
|
@@ -754,15 +764,14 @@ declare function loadConceptMap(json: unknown): ConceptMap;
|
|
|
754
764
|
*
|
|
755
765
|
* Given a source {@link Coding} and a loaded {@link ConceptMap}, it returns the declared target
|
|
756
766
|
* code(s) with their FHIR relationship and the map's provenance — or, when the source does not map,
|
|
757
|
-
* a **typed {@link TranslateUnmapped}**.
|
|
758
|
-
* inherits:
|
|
767
|
+
* a **typed {@link TranslateUnmapped}**. Two invariants govern it:
|
|
759
768
|
*
|
|
760
769
|
* 1. **Never fabricate.** An unmapped source yields a surfaced `unmapped` result — never a guessed
|
|
761
770
|
* target. Every target returned is drawn verbatim from the map; the engine invents nothing.
|
|
762
771
|
* 2. **Never invert.** Translation reads the map in its authored direction only: a source coding is
|
|
763
772
|
* matched against `group.element.code` (the source side) and **never** against target codes. A
|
|
764
773
|
* directional map therefore cannot be run backwards — reverse translation requires an explicit
|
|
765
|
-
* inverse map
|
|
774
|
+
* inverse map; it is never synthesized here.
|
|
766
775
|
*
|
|
767
776
|
* @packageDocumentation
|
|
768
777
|
*/
|
|
@@ -804,14 +813,14 @@ declare function loadConceptMap(json: unknown): ConceptMap;
|
|
|
804
813
|
declare function translate(sourceCoding: Coding, map: ConceptMap): TranslateResult;
|
|
805
814
|
|
|
806
815
|
/**
|
|
807
|
-
* The types for the **CodeSystem load layer** and the FHIR `$lookup` / `$validate-code`
|
|
808
|
-
*
|
|
816
|
+
* The types for the **CodeSystem load layer** and the FHIR `$lookup` / `$validate-code`
|
|
817
|
+
* operations: the immutable {@link CodeSystem} model, the per-concept {@link ConceptStatus},
|
|
809
818
|
* and the discriminated {@link CodeSystemSource} union the loaders accept.
|
|
810
819
|
*
|
|
811
820
|
* The model is **content-agnostic**: it is fed a code system's *release* (a consumer-supplied RRF,
|
|
812
821
|
* CSV, fixed-width file, or FHIR `CodeSystem` JSON) and answers the two identity questions. It ships
|
|
813
|
-
* **
|
|
814
|
-
*
|
|
822
|
+
* **no code-system release** — every concept comes from the caller's data (the BYO-data posture).
|
|
823
|
+
* The FHIR operation shapes are grounded firsthand on the FHIR R4 Terminology Module
|
|
815
824
|
* (`https://hl7.org/fhir/R4/codesystem-operation-lookup.html`,
|
|
816
825
|
* `https://hl7.org/fhir/R4/codesystem-operation-validate-code.html`).
|
|
817
826
|
*
|
|
@@ -833,7 +842,7 @@ declare function translate(sourceCoding: Coding, map: ConceptMap): TranslateResu
|
|
|
833
842
|
type ConceptActivity = "active" | "deprecated" | "discouraged" | "trial" | "obsolete" | "suppressed" | "header" | "unknown";
|
|
834
843
|
/**
|
|
835
844
|
* The status flags a `$lookup`/`$validate-code` carries on a concept — the safety surface that stops
|
|
836
|
-
* a non-current or non-billable code from being presented as clean
|
|
845
|
+
* a non-current or non-billable code from being presented as clean. Present only when
|
|
837
846
|
* the loaded release supplied status information; the engine never fabricates a status.
|
|
838
847
|
*/
|
|
839
848
|
interface ConceptStatus {
|
|
@@ -1059,8 +1068,8 @@ interface FixedWidthFieldMap {
|
|
|
1059
1068
|
/**
|
|
1060
1069
|
* A **fixed-width** source (slice by column) — e.g. the ICD-10-CM order file. Fully parameterized:
|
|
1061
1070
|
* the consumer supplies the field slices (see {@link ICD10CM_ORDER_FILE_FIELDS} for the documented
|
|
1062
|
-
* ICD-10-CM preset, which they confirm against their release's README
|
|
1063
|
-
*
|
|
1071
|
+
* ICD-10-CM preset, which they confirm against their release's README, since the byte offsets are
|
|
1072
|
+
* not confirmed against an authoritative machine-readable source). BYO.
|
|
1064
1073
|
*/
|
|
1065
1074
|
interface FixedWidthSource {
|
|
1066
1075
|
/** Discriminant. */
|
|
@@ -1079,7 +1088,7 @@ interface FixedWidthSource {
|
|
|
1079
1088
|
readonly statusMap?: StatusMapper;
|
|
1080
1089
|
}
|
|
1081
1090
|
/**
|
|
1082
|
-
* A **FHIR R4 `CodeSystem`** JSON source (native,
|
|
1091
|
+
* A **FHIR R4 `CodeSystem`** JSON source (native, consumer-supplied model). The consumer supplies the
|
|
1083
1092
|
* untrusted resource; nested `concept` hierarchies are flattened, and the standard `inactive` /
|
|
1084
1093
|
* `deprecated` concept properties are read into {@link ConceptStatus}.
|
|
1085
1094
|
*/
|
|
@@ -1096,8 +1105,8 @@ type CodeSystemSource = RrfSource | CsvSource | FixedWidthSource | FhirCodeSyste
|
|
|
1096
1105
|
* {@link loadCodeSystem} — the single entry point that dispatches a {@link CodeSystemSource} to the
|
|
1097
1106
|
* right reader (RRF / CSV / fixed-width / FHIR) and assembles the immutable {@link CodeSystem}.
|
|
1098
1107
|
*
|
|
1099
|
-
* The engine is **content-agnostic
|
|
1100
|
-
*
|
|
1108
|
+
* The engine is **content-agnostic**: it loads a *consumer-supplied* release and ships
|
|
1109
|
+
* **no code-system release** of its own. The loaded model is deep-frozen and keyed by code
|
|
1101
1110
|
* for O(1) {@link lookup}/{@link validateCode}.
|
|
1102
1111
|
*
|
|
1103
1112
|
* @packageDocumentation
|
|
@@ -1148,7 +1157,7 @@ declare function loadCodeSystem(source: CodeSystemSource): CodeSystem;
|
|
|
1148
1157
|
* `property` values (*"additional information about the code, including status"*).
|
|
1149
1158
|
* - `$validate-code` returns `result` (*"True if the concept details supplied are valid"*).
|
|
1150
1159
|
*
|
|
1151
|
-
* Both honor the **never-fabricate invariant
|
|
1160
|
+
* Both honor the **never-fabricate invariant**, applied here to code identity: an
|
|
1152
1161
|
* unknown code yields a typed `unknown` / `valid: false` — **never** a fabricated display and
|
|
1153
1162
|
* **never** a guessed `valid: true`. A found-but-non-current concept (deprecated, or an ICD-10-CM
|
|
1154
1163
|
* header) validates as present **but carries its status flag**, so a caller never treats it as clean.
|
|
@@ -1206,7 +1215,7 @@ declare function validateCode(cs: CodeSystem, code: string): ValidateCodeResult;
|
|
|
1206
1215
|
* UMLS Reference Manual, `https://www.ncbi.nlm.nih.gov/books/NBK9685/`: *"values … are separated by
|
|
1207
1216
|
* vertical bars (|)"* and each row ends with *"a vertical bar and line termination"*).
|
|
1208
1217
|
*
|
|
1209
|
-
* **Liberal on load
|
|
1218
|
+
* **Liberal on load**: a row too short to reach a configured column, or with an empty
|
|
1210
1219
|
* code, is **skipped and surfaced** as a `TERM_RRF_MALFORMED_ROW` warning — never kept as a partial
|
|
1211
1220
|
* concept, never a crash. RRF reserves `|` as the delimiter (fields never contain a literal pipe), so
|
|
1212
1221
|
* a plain split is exact.
|
|
@@ -1223,7 +1232,7 @@ declare function validateCode(cs: CodeSystem, code: string): ValidateCodeResult;
|
|
|
1223
1232
|
* ```ts
|
|
1224
1233
|
* import { parseRrfLine } from "@cosyte/terminology";
|
|
1225
1234
|
*
|
|
1226
|
-
* parseRrfLine("
|
|
1235
|
+
* parseRrfLine("316151|ENG|lisinopril 10 MG|"); // => ["316151", "ENG", "lisinopril 10 MG"]
|
|
1227
1236
|
* ```
|
|
1228
1237
|
*/
|
|
1229
1238
|
declare function parseRrfLine(line: string): readonly string[];
|
|
@@ -1256,8 +1265,8 @@ declare function parseRrf(source: RrfSource): {
|
|
|
1256
1265
|
/**
|
|
1257
1266
|
* The **RFC-4180 CSV** reader — the one release format that needs real quote handling (LOINC's
|
|
1258
1267
|
* `Loinc.csv`). Fields may be quoted with `"`; inside a quoted field a literal quote is escaped as
|
|
1259
|
-
* `""`, and commas and newlines are data. Hand-rolled, zero-dep (
|
|
1260
|
-
*
|
|
1268
|
+
* `""`, and commas and newlines are data. Hand-rolled, zero-dep (the CSV surface is small and
|
|
1269
|
+
* well-specified enough to hand-roll rather than pull a dependency).
|
|
1261
1270
|
*
|
|
1262
1271
|
* **Liberal on load:** a data row with too few fields to reach a configured column is **skipped and
|
|
1263
1272
|
* surfaced** as a `TERM_CSV_MALFORMED` warning; an unterminated final quote is surfaced too — never a
|
|
@@ -1312,9 +1321,8 @@ declare function parseCsvSource(source: CsvSource): {
|
|
|
1312
1321
|
*
|
|
1313
1322
|
* The documented ICD-10-CM preset is {@link ICD10CM_ORDER_FILE_FIELDS} — the position-15 flag
|
|
1314
1323
|
* (0-based char index 14) is `1` for a **billable/valid** code and `0` for a **header** (grounded on
|
|
1315
|
-
* the CMS/CDC order-file layout).
|
|
1316
|
-
*
|
|
1317
|
-
* exactly why the reader takes the slices as a parameter.
|
|
1324
|
+
* the CMS/CDC order-file layout). Confirm the exact offsets against your release's README before
|
|
1325
|
+
* relying on the preset — which is exactly why the reader takes the slices as a parameter.
|
|
1318
1326
|
*
|
|
1319
1327
|
* **Liberal on load:** a line too short to contain the code slice, or with an empty code, is skipped
|
|
1320
1328
|
* and surfaced as a `TERM_FIXED_WIDTH_MALFORMED` warning.
|
|
@@ -1345,8 +1353,9 @@ declare function sliceField(line: string, slice: FieldSlice): string;
|
|
|
1345
1353
|
* - property `shortDescription` — the 60-char short description.
|
|
1346
1354
|
*
|
|
1347
1355
|
* Grounded on the CMS/CDC order-file layout; **verify against your release's README** before relying
|
|
1348
|
-
* on the exact offsets
|
|
1349
|
-
* the layout as a parameter precisely so this preset is a starting point, not a
|
|
1356
|
+
* on the exact offsets, which are not confirmed against an authoritative machine-readable source.
|
|
1357
|
+
* The reader takes the layout as a parameter precisely so this preset is a starting point, not a
|
|
1358
|
+
* hardcoded assumption.
|
|
1350
1359
|
*/
|
|
1351
1360
|
declare const ICD10CM_ORDER_FILE_FIELDS: FixedWidthFieldMap;
|
|
1352
1361
|
/**
|
|
@@ -1372,7 +1381,7 @@ declare function parseFixedWidth(source: FixedWidthSource): {
|
|
|
1372
1381
|
};
|
|
1373
1382
|
|
|
1374
1383
|
/**
|
|
1375
|
-
* The **FHIR R4 `CodeSystem`** JSON loader — the native,
|
|
1384
|
+
* The **FHIR R4 `CodeSystem`** JSON loader — the native, consumer-supplied model. Reads the untrusted
|
|
1376
1385
|
* resource into the engine's {@link Concept} map, flattening nested `concept` hierarchies and mapping
|
|
1377
1386
|
* the standard concept properties to {@link ConceptStatus}.
|
|
1378
1387
|
*
|
|
@@ -1418,11 +1427,11 @@ declare function parseFhirCodeSystem(source: FhirCodeSystemSource): {
|
|
|
1418
1427
|
/**
|
|
1419
1428
|
* Status interpretation shared by the loaders — the {@link defaultStatusMapper} that turns a raw
|
|
1420
1429
|
* steward status token into a normalized {@link ConceptActivity}, and {@link makeStatus} which
|
|
1421
|
-
* assembles the frozen {@link ConceptStatus} (attaching the stable diagnostic code for the
|
|
1422
|
-
*
|
|
1430
|
+
* assembles the frozen {@link ConceptStatus} (attaching the stable diagnostic code for the two
|
|
1431
|
+
* concerns it distinguishes: deprecated and header-not-billable).
|
|
1423
1432
|
*
|
|
1424
1433
|
* The mapper is deliberately **conservative**: it recognizes only the tokens grounded in the format
|
|
1425
|
-
* docs (LOINC `STATUS` lifecycle values
|
|
1434
|
+
* docs (LOINC `STATUS` lifecycle values and RxNorm/UMLS `SUPPRESS` values), and maps
|
|
1426
1435
|
* everything else to `unknown` — a non-active state carrying the raw token, **never** a guessed
|
|
1427
1436
|
* clean-active. Every loader lets the consumer override it for a release with bespoke semantics.
|
|
1428
1437
|
*
|
|
@@ -1450,7 +1459,7 @@ declare const defaultStatusMapper: StatusMapper;
|
|
|
1450
1459
|
/**
|
|
1451
1460
|
* Assemble a frozen {@link ConceptStatus} from a normalized activity, carrying the raw token and (for
|
|
1452
1461
|
* classification systems) the billable flag, and attaching the stable diagnostic code for the two
|
|
1453
|
-
* concerns
|
|
1462
|
+
* concerns it distinguishes — `TERM_CONCEPT_DEPRECATED` and `TERM_CONCEPT_HEADER_NOT_BILLABLE`.
|
|
1454
1463
|
*
|
|
1455
1464
|
* @param activity - The normalized activity.
|
|
1456
1465
|
* @param raw - The verbatim steward token, if any (omitted from the result when empty).
|
|
@@ -1466,14 +1475,14 @@ declare const defaultStatusMapper: StatusMapper;
|
|
|
1466
1475
|
declare function makeStatus(activity: ConceptActivity, raw?: string, billable?: boolean): ConceptStatus;
|
|
1467
1476
|
|
|
1468
1477
|
/**
|
|
1469
|
-
* The types for the **ValueSet binding layer
|
|
1478
|
+
* The types for the **ValueSet binding layer**: the immutable {@link ValueSet}
|
|
1470
1479
|
* model, the `compose` component/filter shapes, the {@link ExpansionContext} that supplies the loaded
|
|
1471
1480
|
* code systems and referenced value sets, and the fail-safe {@link ExpandResult} /
|
|
1472
1481
|
* {@link ValueSetMembership} outcomes.
|
|
1473
1482
|
*
|
|
1474
|
-
* The model is **content-agnostic
|
|
1475
|
-
*
|
|
1476
|
-
*
|
|
1483
|
+
* The model is **content-agnostic**: a `ValueSet` names codes by system URI and is expanded over
|
|
1484
|
+
* **consumer-supplied** {@link CodeSystem} releases — the engine ships **zero** encoded value-set
|
|
1485
|
+
* content (SNOMED CT / CPT / LOINC / UMLS / VSAC value sets are strictly BYO). The FHIR
|
|
1477
1486
|
* operation shapes are grounded firsthand on the FHIR R4 Terminology Module
|
|
1478
1487
|
* (`https://hl7.org/fhir/R4/valueset.html`, `https://hl7.org/fhir/R4/valueset-operation-expand.html`,
|
|
1479
1488
|
* `https://hl7.org/fhir/R4/valueset-operation-validate-code.html`).
|
|
@@ -1545,8 +1554,8 @@ interface ExpansionContains {
|
|
|
1545
1554
|
}
|
|
1546
1555
|
/**
|
|
1547
1556
|
* A **pre-computed** `ValueSet.expansion` — a cached membership snapshot, used as-is (extensional).
|
|
1548
|
-
* The engine never re-derives it; it only checks whether it is **complete** (
|
|
1549
|
-
*
|
|
1557
|
+
* The engine never re-derives it; it only checks whether it is **complete** (a truncated
|
|
1558
|
+
* expansion must never read as full membership).
|
|
1550
1559
|
*/
|
|
1551
1560
|
interface ValueSetExpansion {
|
|
1552
1561
|
/** The server-reported total membership, when present (FHIR `expansion.total`). */
|
|
@@ -1581,9 +1590,10 @@ interface ValueSet {
|
|
|
1581
1590
|
* {@link CodeSystem} releases (for intensional `filter`/`system` includes) and any referenced
|
|
1582
1591
|
* {@link ValueSet}s (for `compose.include.valueSet`), each keyed by its **canonical URL**.
|
|
1583
1592
|
*
|
|
1584
|
-
* The engine makes **no network call** and holds no bundled
|
|
1593
|
+
* The engine makes **no network call** and holds no bundled code-system release: everything
|
|
1594
|
+
* intensional resolves
|
|
1585
1595
|
* through this map, and a system or value set the caller did not supply becomes a typed
|
|
1586
|
-
* {@link DiagnosticCode.TERM_VALUESET_CANNOT_EXPAND}, never a fabricated member
|
|
1596
|
+
* {@link DiagnosticCode.TERM_VALUESET_CANNOT_EXPAND}, never a fabricated member.
|
|
1587
1597
|
*/
|
|
1588
1598
|
interface ExpansionContext {
|
|
1589
1599
|
/** Loaded code-system releases, keyed by canonical URI (e.g. `"http://loinc.org"`). */
|
|
@@ -1631,7 +1641,7 @@ interface ValueSetMemberDecided {
|
|
|
1631
1641
|
* A **fail-safe undetermined** membership — the never-fabricate outcome for a value set that could
|
|
1632
1642
|
* not be fully evaluated (a missing code system, a truncated expansion). The engine refuses to guess:
|
|
1633
1643
|
* it returns neither `true` nor `false`, so a caller can never mistake "we could not check" for "not a
|
|
1634
|
-
* member" (
|
|
1644
|
+
* member" (a false "not a member" is a clinical error).
|
|
1635
1645
|
*/
|
|
1636
1646
|
interface ValueSetMemberUndetermined {
|
|
1637
1647
|
/** Discriminant: membership could not be decided. */
|
|
@@ -1696,7 +1706,7 @@ declare function loadValueSet(json: unknown): ValueSet;
|
|
|
1696
1706
|
* `https://hl7.org/fhir/R4/valueset.html#compose`):
|
|
1697
1707
|
*
|
|
1698
1708
|
* - A **pre-computed** `expansion` is used as-is (extensional), and its completeness is checked — a
|
|
1699
|
-
* truncated snapshot is flagged, never treated as full membership
|
|
1709
|
+
* truncated snapshot is flagged, never treated as full membership.
|
|
1700
1710
|
* - An intensional `compose` is expanded over **consumer-supplied** {@link ../codesystem/types.CodeSystem}
|
|
1701
1711
|
* releases: the union of `include` components minus the union of `exclude` components. Each component
|
|
1702
1712
|
* selects by explicit `concept`, by `filter` (subsumption + property predicates), by the whole
|
|
@@ -1751,8 +1761,8 @@ declare function expand(vs: ValueSet, ctx?: ExpansionContext): ExpandResult;
|
|
|
1751
1761
|
* not removed by any computable `exclude` is a definite member; a code absent from a fully-evaluated
|
|
1752
1762
|
* value set is a definite non-member. When any relevant part cannot be evaluated (a missing code
|
|
1753
1763
|
* system, a truncated pre-computed expansion, an unimplemented `filter`), the answer is a typed
|
|
1754
|
-
* {@link ValueSetMemberUndetermined} — **never** a fabricated `false` (
|
|
1755
|
-
*
|
|
1764
|
+
* {@link ValueSetMemberUndetermined} — **never** a fabricated `false` (a false "not a member" is a
|
|
1765
|
+
* clinical error).
|
|
1756
1766
|
*
|
|
1757
1767
|
* @packageDocumentation
|
|
1758
1768
|
*/
|
|
@@ -1786,9 +1796,9 @@ declare function validateCodeInValueSet(coding: Coding, valueSet: ValueSet, ctx?
|
|
|
1786
1796
|
* **Subsumption** is read from the loaded {@link CodeSystem}'s **`parent`** concept-properties
|
|
1787
1797
|
* (`http://hl7.org/fhir/concept-properties#parent`) — which the FHIR loader synthesizes from a nested
|
|
1788
1798
|
* `concept` hierarchy and carries verbatim from an explicit `parent` property. This is deliberately
|
|
1789
|
-
* the release's **own** hierarchy
|
|
1790
|
-
*
|
|
1791
|
-
*
|
|
1799
|
+
* the release's **own** hierarchy: subsumption across two separate releases is not computed, and a
|
|
1800
|
+
* code system that encodes no parent edges has no descendants beyond identity, which is treated as
|
|
1801
|
+
* complete — not guessed deeper.
|
|
1792
1802
|
*
|
|
1793
1803
|
* **Filter support is explicit.** `is-a` / `descendent-of` / `is-not-a` / `=` / `in` / `not-in` /
|
|
1794
1804
|
* `exists` are implemented; `regex` / `generalizes` / anything unrecognized report `supported: false`
|
|
@@ -1886,15 +1896,16 @@ interface FilterMatch {
|
|
|
1886
1896
|
declare function matchesFilter(concept: Concept, filter: ConceptSetFilter, sub: Subsumption): FilterMatch;
|
|
1887
1897
|
|
|
1888
1898
|
/**
|
|
1889
|
-
* Types for the **UCUM unit layer
|
|
1899
|
+
* Types for the **UCUM unit layer**: the parsed unit AST, the reduced
|
|
1890
1900
|
* (canonical) dimensional form, and the public {@link UcumValidation} result.
|
|
1891
1901
|
*
|
|
1892
1902
|
* The layer is **recognition + validation + representation canonicalization only** — it answers
|
|
1893
1903
|
* "is this a valid UCUM expression" and "are these two expressions the same unit", and it
|
|
1894
1904
|
* canonicalizes a unit's *representation*. It performs **no magnitude conversion** (`mg/dL` →
|
|
1895
|
-
* `mmol/L` needs an analyte's molar mass — a clinical computation the engine refuses
|
|
1896
|
-
*
|
|
1897
|
-
* to an in-memory model at runtime;
|
|
1905
|
+
* `mmol/L` needs an analyte's molar mass — a clinical computation the engine refuses). The tables
|
|
1906
|
+
* are the UCUM `ucum-essence.xml`, **bundled verbatim** in this package (copyright © Regenstrief
|
|
1907
|
+
* Institute, Inc. — see `vendor/ucum/NOTICE.md`) and transformed to an in-memory model at runtime;
|
|
1908
|
+
* the engine ships **no derivative** of the UCUM table.
|
|
1898
1909
|
*
|
|
1899
1910
|
* @packageDocumentation
|
|
1900
1911
|
*/
|
|
@@ -2039,11 +2050,11 @@ type UcumValidation = {
|
|
|
2039
2050
|
};
|
|
2040
2051
|
|
|
2041
2052
|
/**
|
|
2042
|
-
* The public **UCUM** surface
|
|
2053
|
+
* The public **UCUM** surface: {@link validateUcum} (recognition + a canonical
|
|
2043
2054
|
* descriptor) and {@link ucumEqual} (are two expressions the *same unit*).
|
|
2044
2055
|
*
|
|
2045
2056
|
* Both are **recognition / validation / representation-canonicalization only** — never magnitude
|
|
2046
|
-
* conversion
|
|
2057
|
+
* conversion. The never-fabricate posture holds: an unparseable or unknown unit is
|
|
2047
2058
|
* a typed {@link TERM_UCUM_INVALID} outcome carrying a value-free reason, **never** a guessed
|
|
2048
2059
|
* "nearest" unit; and a special (non-linear) unit is never claimed equal to a linear one.
|
|
2049
2060
|
*
|
|
@@ -2094,7 +2105,7 @@ declare function validateUcum(unit: string): UcumValidation;
|
|
|
2094
2105
|
declare function ucumEqual(a: string, b: string): boolean;
|
|
2095
2106
|
|
|
2096
2107
|
/**
|
|
2097
|
-
* The **UCUM grammar parser
|
|
2108
|
+
* The **UCUM grammar parser**: a hand-rolled, zero-dependency recursive-descent
|
|
2098
2109
|
* parser from a unit expression string to a {@link UnitNode} AST, grounded firsthand on the UCUM
|
|
2099
2110
|
* specification's syntax (base units, metric prefixes attached with no delimiter and resolved by
|
|
2100
2111
|
* longest-match, `.` multiply / `/` divide, signed integer exponents, `{…}` inert annotations, and
|
|
@@ -2131,13 +2142,13 @@ interface ParseFailure {
|
|
|
2131
2142
|
declare function parseUcum(unit: string): ParseResult;
|
|
2132
2143
|
|
|
2133
2144
|
/**
|
|
2134
|
-
* **Dimensional reduction** of a parsed UCUM unit
|
|
2145
|
+
* **Dimensional reduction** of a parsed UCUM unit: reduce an expression to its
|
|
2135
2146
|
* canonical base-unit form — a scalar factor times a map of the seven UCUM base dimensions
|
|
2136
2147
|
* (`m s g rad K C cd`), recursively substituting each atom's essence definition down to base units.
|
|
2137
2148
|
*
|
|
2138
2149
|
* This is **representation** canonicalization, not magnitude *conversion*: it answers "are these two
|
|
2139
2150
|
* expressions the same unit" (`N` ≡ `kg.m/s2`, `mmol/L` ≡ `mmol.L-1`), never "what is 5 mg/dL in
|
|
2140
|
-
* mmol/L" (that needs an analyte's molar mass
|
|
2151
|
+
* mmol/L" (that needs an analyte's molar mass, which the engine refuses). **Special** units (`Cel`,
|
|
2141
2152
|
* `B`, `[pH]`) are non-linear and carry no factor/dimension — they reduce to an opaque normalized
|
|
2142
2153
|
* form and are never equated with a linear unit. **Arbitrary** units (`[IU]`, `[arb'U]`) are modeled
|
|
2143
2154
|
* as their own dimension axis, so they cancel with themselves but convert to nothing else.
|
|
@@ -2171,8 +2182,9 @@ declare function reduce(node: UnitNode): Reduction;
|
|
|
2171
2182
|
* Hand-rolled, **zero-dependency** scanning of a known-well-formed document (not a general XML
|
|
2172
2183
|
* parser): the essence file is a flat, regular list of `<prefix>` / `<base-unit>` / `<unit>`
|
|
2173
2184
|
* elements. Parsed **once**, lazily, and cached — the engine reads no file at runtime; the table is
|
|
2174
|
-
* a pure transform of the embedded verbatim content
|
|
2175
|
-
*
|
|
2185
|
+
* a pure in-process transform of the embedded verbatim content, never serialized or distributed. The
|
|
2186
|
+
* UCUM table is copyright © Regenstrief Institute, Inc. and is bundled verbatim — see
|
|
2187
|
+
* `vendor/ucum/NOTICE.md`, which ships with this package.
|
|
2176
2188
|
*
|
|
2177
2189
|
* @packageDocumentation
|
|
2178
2190
|
*/
|
|
@@ -2192,7 +2204,7 @@ declare function reduce(node: UnitNode): Reduction;
|
|
|
2192
2204
|
declare function loadUcumEssence(): UcumEssence;
|
|
2193
2205
|
|
|
2194
2206
|
/**
|
|
2195
|
-
* The types for the **crosswalk resolvers**
|
|
2207
|
+
* The types for the **crosswalk resolvers** — the CMS ICD-9↔ICD-10 **GEMs**
|
|
2196
2208
|
* (General Equivalence Mappings) and the NLM **SNOMED CT → ICD-10-CM complex map**.
|
|
2197
2209
|
*
|
|
2198
2210
|
* Both are the library's highest-risk surface, and their types are built around the stewards' own
|
|
@@ -2206,8 +2218,7 @@ declare function loadUcumEssence(): UcumEssence;
|
|
|
2206
2218
|
* - a 1:many source yields the **whole** ordered candidate set, never one confident pick;
|
|
2207
2219
|
* - a context-dependent rule with no runtime context is a typed {@link ComplexMapContextRequired} —
|
|
2208
2220
|
* the rule + advice ride through, the engine never picks a branch it wasn't given the data for;
|
|
2209
|
-
* - all Map Advice / GEM flags ride through **verbatim** (
|
|
2210
|
-
* roadmap §4.1);
|
|
2221
|
+
* - all Map Advice / GEM flags ride through **verbatim** (advice flags must not be swallowed);
|
|
2211
2222
|
* - a directional map is **never inverted** (see {@link ../crosswalk/gems.invertGem}).
|
|
2212
2223
|
*
|
|
2213
2224
|
* @packageDocumentation
|
|
@@ -2216,7 +2227,7 @@ declare function loadUcumEssence(): UcumEssence;
|
|
|
2216
2227
|
/**
|
|
2217
2228
|
* The **direction** of a loaded GEM file. CMS ships the forward (ICD-9→ICD-10, `…_I9gem.txt`) and
|
|
2218
2229
|
* backward (ICD-10→ICD-9, `…_I10gem.txt`) maps as **separate, non-inverse artifacts** — a forward map
|
|
2219
|
-
* composed with a backward map is *"not a mirror image"
|
|
2230
|
+
* composed with a backward map is *"not a mirror image"*. A `GemMap` therefore records
|
|
2220
2231
|
* which direction it is and is only ever applied in that direction.
|
|
2221
2232
|
*/
|
|
2222
2233
|
type GemDirection = "9-to-10" | "10-to-9";
|
|
@@ -2236,7 +2247,7 @@ interface GemFlags {
|
|
|
2236
2247
|
/**
|
|
2237
2248
|
* Position 2 — **no-map** flag. `true` when the source code has **no valid target** in the other
|
|
2238
2249
|
* classification (the target field is the `NoDx`/`NoPCS` sentinel). A first-class typed outcome —
|
|
2239
|
-
* surfaced as a {@link CrosswalkNoMap}, never a fabricated target
|
|
2250
|
+
* surfaced as a {@link CrosswalkNoMap}, never a fabricated target.
|
|
2240
2251
|
*/
|
|
2241
2252
|
readonly noMap: boolean;
|
|
2242
2253
|
/**
|
|
@@ -2290,7 +2301,7 @@ interface GemMap {
|
|
|
2290
2301
|
}
|
|
2291
2302
|
/**
|
|
2292
2303
|
* A surfaced, non-fatal GEM load warning — a malformed line that was **skipped**, reported with its
|
|
2293
|
-
* line number and a value-free structural reason. Liberal on load (
|
|
2304
|
+
* line number and a value-free structural reason. Liberal on load (the parsers' posture).
|
|
2294
2305
|
*/
|
|
2295
2306
|
interface GemLoadWarning {
|
|
2296
2307
|
/** The stable diagnostic code for a skipped GEM row. */
|
|
@@ -2336,8 +2347,8 @@ interface GemMatched {
|
|
|
2336
2347
|
}
|
|
2337
2348
|
/**
|
|
2338
2349
|
* One row of the SNOMED CT → ICD-10-CM **complex/extended map** refset — the caller-supplied,
|
|
2339
|
-
* SNOMED-licensed content the resolver runs over (**no SNOMED
|
|
2340
|
-
*
|
|
2350
|
+
* SNOMED-licensed content the resolver runs over (**no SNOMED CT refset is bundled**). The field
|
|
2351
|
+
* names paraphrase the SNOMED RF2 extended-map refset columns.
|
|
2341
2352
|
*/
|
|
2342
2353
|
interface ComplexMapEntry {
|
|
2343
2354
|
/** The SNOMED CT source concept id (`referencedComponentId`), verbatim. */
|
|
@@ -2361,7 +2372,7 @@ interface ComplexMapEntry {
|
|
|
2361
2372
|
/**
|
|
2362
2373
|
* The **map advice**, verbatim (pipe-delimited in the source) — steward instructions to a human
|
|
2363
2374
|
* (`CONSIDER LATERALITY`, `EPISODE OF CARE INFORMATION NEEDED`, `THIS IS A MANIFESTATION CODE…`).
|
|
2364
|
-
* Carried through untouched: advice flags must **never** be swallowed
|
|
2375
|
+
* Carried through untouched: advice flags must **never** be swallowed.
|
|
2365
2376
|
*/
|
|
2366
2377
|
readonly advice: string;
|
|
2367
2378
|
/** The ICD-10-CM **map target** code, verbatim — **absent** for a No-Map / empty-target row. */
|
|
@@ -2397,7 +2408,7 @@ interface ComplexMapLoadWarning {
|
|
|
2397
2408
|
/**
|
|
2398
2409
|
* The **caller-supplied patient context** an `IFA` rule is evaluated against. The resolver evaluates
|
|
2399
2410
|
* only against what it is given: a rule needing context absent here surfaces as a
|
|
2400
|
-
* {@link ComplexMapContextRequired}, never a silently-picked branch
|
|
2411
|
+
* {@link ComplexMapContextRequired}, never a silently-picked branch.
|
|
2401
2412
|
*/
|
|
2402
2413
|
interface PatientContext {
|
|
2403
2414
|
/** The patient's age **in years**, when known (for `IFA … Age …` bands). */
|
|
@@ -2445,7 +2456,7 @@ interface ComplexMapGroupNoMap {
|
|
|
2445
2456
|
/**
|
|
2446
2457
|
* A group whose winning path is a **context-dependent** `IFA` rule (or `447639009`/`447640006`
|
|
2447
2458
|
* category) for which the caller supplied **no** matching context. The engine surfaces the rules +
|
|
2448
|
-
* advice and refuses to pick a branch
|
|
2459
|
+
* advice and refuses to pick a branch — the never-fabricate rule for runtime context.
|
|
2449
2460
|
*/
|
|
2450
2461
|
interface ComplexMapContextRequired {
|
|
2451
2462
|
/** Discriminant. */
|
|
@@ -2469,7 +2480,7 @@ interface ComplexMapMatched {
|
|
|
2469
2480
|
/**
|
|
2470
2481
|
* A **No-Map** outcome — the source is present in the map but the steward declares it has no valid
|
|
2471
2482
|
* target ("cannot be classified with available data"). A first-class typed result, **never** a
|
|
2472
|
-
* fabricated target
|
|
2483
|
+
* fabricated target. Distinct from {@link CrosswalkUnmapped} (source absent entirely).
|
|
2473
2484
|
*/
|
|
2474
2485
|
interface CrosswalkNoMap {
|
|
2475
2486
|
/** Discriminant: the source did not map. */
|
|
@@ -2506,7 +2517,7 @@ type GemApplyResult = GemMatched | CrosswalkNoMap | CrosswalkUnmapped;
|
|
|
2506
2517
|
type ComplexMapApplyResult = ComplexMapMatched | CrosswalkUnmapped;
|
|
2507
2518
|
|
|
2508
2519
|
/**
|
|
2509
|
-
* The CMS **ICD-9 ↔ ICD-10 GEMs** (General Equivalence Mappings) loader + applier
|
|
2520
|
+
* The CMS **ICD-9 ↔ ICD-10 GEMs** (General Equivalence Mappings) loader + applier.
|
|
2510
2521
|
*
|
|
2511
2522
|
* The GEMs are **CMS/NCHS public-domain** (US-government work) reference mappings between the ICD-9-CM
|
|
2512
2523
|
* and ICD-10-CM diagnosis classifications. CMS is emphatic about what they are — *"GEMs are not
|
|
@@ -2524,8 +2535,7 @@ type ComplexMapApplyResult = ComplexMapMatched | CrosswalkUnmapped;
|
|
|
2524
2535
|
* - **Directional, never inverted.** The forward (9→10) and backward (10→9) files are **separate,
|
|
2525
2536
|
* non-inverse** artifacts; {@link invertGem} refuses to synthesize one from the other.
|
|
2526
2537
|
*
|
|
2527
|
-
* The engine ships **no GEM content**: the caller supplies the public-domain GEM file (BYO
|
|
2528
|
-
* §2/§5). Bundling the public-domain packs is the separate content-packs phase.
|
|
2538
|
+
* The engine ships **no GEM content**: the caller supplies the public-domain GEM file (BYO).
|
|
2529
2539
|
*
|
|
2530
2540
|
* @packageDocumentation
|
|
2531
2541
|
*/
|
|
@@ -2549,7 +2559,7 @@ interface GemSource {
|
|
|
2549
2559
|
* malformed 5-digit flag) is **skipped and surfaced** as a {@link GemLoadWarning}, never a
|
|
2550
2560
|
* partially-parsed entry. An unusable *source* is not possible here (an all-malformed file loads to an
|
|
2551
2561
|
* empty map with warnings) — there is no fatal for GEM load. Ships **no** GEM content: the entries are
|
|
2552
|
-
* the caller's public-domain file
|
|
2562
|
+
* the caller's public-domain file.
|
|
2553
2563
|
*
|
|
2554
2564
|
* @param source - The {@link GemSource} (raw content + direction + version).
|
|
2555
2565
|
* @returns The immutable {@link GemMap}.
|
|
@@ -2593,7 +2603,7 @@ declare function applyGem(map: GemMap, source: string): GemApplyResult;
|
|
|
2593
2603
|
*
|
|
2594
2604
|
* The never-invert invariant made explicit and discoverable: a forward GEM (9→10) is **not** the
|
|
2595
2605
|
* inverse of the backward GEM (10→9) — CMS ships them as separate artifacts and *"forward and
|
|
2596
|
-
* backward mappings are not simply the reverse"
|
|
2606
|
+
* backward mappings are not simply the reverse"*. To resolve the other direction, load
|
|
2597
2607
|
* the other file with {@link loadGems}; the engine never synthesizes an inverse.
|
|
2598
2608
|
*
|
|
2599
2609
|
* @param map - The map an inversion was (incorrectly) requested for.
|
|
@@ -2610,10 +2620,13 @@ declare function applyGem(map: GemMap, source: string): GemApplyResult;
|
|
|
2610
2620
|
declare function invertGem(map: GemMap): never;
|
|
2611
2621
|
|
|
2612
2622
|
/**
|
|
2613
|
-
* The **SNOMED CT → ICD-10-CM complex-map** resolver
|
|
2614
|
-
* resolver over the caller-supplied complex/extended-map refset. **No SNOMED CT
|
|
2615
|
-
*
|
|
2616
|
-
* SNOMED
|
|
2623
|
+
* The **SNOMED CT → ICD-10-CM complex-map** resolver — a rule-based, **BYO**
|
|
2624
|
+
* resolver over the caller-supplied complex/extended-map refset. **No SNOMED CT refset or release is
|
|
2625
|
+
* bundled**: the engine ships the rule machinery; the caller supplies the map rows from their own
|
|
2626
|
+
* SNOMED CT release. (Individual SNOMED CT concepts this resolver *names* are bundled: the
|
|
2627
|
+
* map-category concepts a row's `mapCategoryId` refers to — see
|
|
2628
|
+
* {@link ../crosswalk/categories.MAP_CATEGORIES} — and the two gender findings a gender `IFA` rule
|
|
2629
|
+
* is written against.)
|
|
2617
2630
|
*
|
|
2618
2631
|
* The map is *"semi-automated"* by the steward's own statement — 1:many, context-dependent, with
|
|
2619
2632
|
* first-class No-Map states. The resolver honours that:
|
|
@@ -2625,7 +2638,7 @@ declare function invertGem(map: GemMap): never;
|
|
|
2625
2638
|
* - **Context it wasn't given, it never guesses.** If deciding a group requires an `IFA` predicate
|
|
2626
2639
|
* (an age band, a gender) the caller left unspecified, the group is a typed
|
|
2627
2640
|
* {@link ComplexMapContextRequired} carrying the candidate rules + advice — never a silently-picked
|
|
2628
|
-
* branch
|
|
2641
|
+
* branch.
|
|
2629
2642
|
* - **No-Map is typed.** A `447638001` "cannot be classified" row (or an empty target) is a typed
|
|
2630
2643
|
* No-Map, never a fabricated code.
|
|
2631
2644
|
* - **Advice rides through verbatim.** `CONSIDER LATERALITY`, `EPISODE OF CARE INFORMATION NEEDED`,
|
|
@@ -2654,8 +2667,8 @@ type ComplexMapInput = {
|
|
|
2654
2667
|
*
|
|
2655
2668
|
* Liberal on load: a structurally unusable RF2 *row* is skipped and surfaced as a warning; only an
|
|
2656
2669
|
* unusable *source* (empty content, header missing required columns) is a fatal
|
|
2657
|
-
* {@link FATAL_CODES.TERM_CROSSWALK_MALFORMED}. Ships **no** SNOMED
|
|
2658
|
-
* caller's, under their own licence
|
|
2670
|
+
* {@link FATAL_CODES.TERM_CROSSWALK_MALFORMED}. Ships **no** SNOMED CT release or refset — the rows
|
|
2671
|
+
* are the caller's, under their own licence.
|
|
2659
2672
|
*
|
|
2660
2673
|
* @param input - Structured `rows`, or a raw RF2 extended-map refset `content`.
|
|
2661
2674
|
* @returns The immutable {@link ComplexMap}.
|
|
@@ -2710,23 +2723,25 @@ declare const COMPLEX_MAP_SOURCE_SYSTEM = "http://snomed.info/sct";
|
|
|
2710
2723
|
/**
|
|
2711
2724
|
* Steward-defined **map category** and **map-relationship** identifiers the crosswalk resolvers carry
|
|
2712
2725
|
* through verbatim — the SNOMED CT complex-map `mapCategoryId` concepts and the map-correlation
|
|
2713
|
-
* concepts. These are
|
|
2714
|
-
*
|
|
2715
|
-
*
|
|
2716
|
-
* refset itself under their own SNOMED licence (
|
|
2726
|
+
* concepts. These are SNOMED CT metadata concepts, and **they are bundled**: the four ids below and
|
|
2727
|
+
* their steward descriptions ship inside this package. SNOMED CT is copyright © International Health
|
|
2728
|
+
* Terminology Standards Development Organisation. **No SNOMED CT refset or release is bundled** — a
|
|
2729
|
+
* caller still supplies the map refset itself under their own SNOMED CT licence (the BYO posture).
|
|
2717
2730
|
*
|
|
2718
2731
|
* The category on a resolved SNOMED→ICD-10-CM map row is the steward telling the caller *how much to
|
|
2719
2732
|
* trust the target*: a `447638001` "cannot be classified" row is a **No-Map**, a `447640006`
|
|
2720
2733
|
* "ambiguous" row must surface its candidates rather than pick one, and a `447639009`
|
|
2721
2734
|
* "context-dependent" row needs runtime patient context. The resolver never collapses these to a
|
|
2722
|
-
* single confident target
|
|
2735
|
+
* single confident target.
|
|
2723
2736
|
*
|
|
2724
2737
|
* @packageDocumentation
|
|
2725
2738
|
*/
|
|
2726
2739
|
/**
|
|
2727
2740
|
* The SNOMED CT complex-map **map category** concept ids — the `mapCategoryId` column of the
|
|
2728
|
-
* SNOMED→ICD-10-CM extended-map refset.
|
|
2729
|
-
*
|
|
2741
|
+
* SNOMED→ICD-10-CM extended-map refset. These four SNOMED CT concepts — id and steward description —
|
|
2742
|
+
* are **bundled** in this package (SNOMED CT is copyright © International Health Terminology
|
|
2743
|
+
* Standards Development Organisation); carried through a resolution verbatim so a caller sees the
|
|
2744
|
+
* steward's own trust signal.
|
|
2730
2745
|
*
|
|
2731
2746
|
* @example
|
|
2732
2747
|
* ```ts
|
|
@@ -2765,22 +2780,24 @@ declare const ICD10CM_SYSTEM = "http://hl7.org/fhir/sid/icd-10-cm";
|
|
|
2765
2780
|
declare const ICD9CM_SYSTEM = "http://hl7.org/fhir/sid/icd-9-cm";
|
|
2766
2781
|
/**
|
|
2767
2782
|
* The canonical code-system URI for **SNOMED CT** — the source system of the SNOMED→ICD-10-CM complex
|
|
2768
|
-
* map. Recognised by URI only; **no SNOMED CT
|
|
2783
|
+
* map. Recognised by URI only; **no SNOMED CT refset or release is bundled**.
|
|
2769
2784
|
*/
|
|
2770
2785
|
declare const SNOMEDCT_SYSTEM = "http://snomed.info/sct";
|
|
2771
2786
|
|
|
2772
2787
|
/**
|
|
2773
|
-
* The types for the **RxNorm drug relationship graph**
|
|
2788
|
+
* The types for the **RxNorm drug relationship graph** — the ingredient / brand /
|
|
2774
2789
|
* clinical-drug / dose-form graph navigated over a **caller-supplied** RxNorm RRF release.
|
|
2775
2790
|
*
|
|
2776
2791
|
* RxNorm is the US NLM's normalized drug nomenclature. Its concepts (`RXCUI`s) are typed by **term
|
|
2777
2792
|
* type** ({@link TermType}: `IN` ingredient, `SCD` semantic clinical drug, `SBD` semantic branded
|
|
2778
2793
|
* drug, `BN` brand name, `DF` dose form, …) and wired together by **directed relationships** carried
|
|
2779
2794
|
* in `RXNREL.RRF` and labeled by a `RELA` (`has_ingredient`, `tradename_of`, `has_dose_form`,
|
|
2780
|
-
* `consists_of`, …). The graph these form is the whole point
|
|
2781
|
-
*
|
|
2795
|
+
* `consists_of`, …). The graph these form is the whole point: resolve a drug to its
|
|
2796
|
+
* components and through them to its ingredient, a branded drug to its generic, a drug to its dose
|
|
2797
|
+
* form. Note that the ingredient edge is authored on the component rather than on the `SCD` itself
|
|
2798
|
+
* (see {@link ../rxnorm/navigate.ingredientsOf}).
|
|
2782
2799
|
*
|
|
2783
|
-
* **The direction convention is a documented medication-safety trap
|
|
2800
|
+
* **The direction convention is a documented medication-safety trap**, and it
|
|
2784
2801
|
* is grounded here firsthand on the NLM RxNorm Technical Documentation (§12.7) and the UMLS Reference
|
|
2785
2802
|
* Manual: *"the direction of REL — the relationship which the SECOND concept or atom (with … RXCUI2
|
|
2786
2803
|
* …) HAS TO the FIRST concept or atom (with … RXCUI1 …)."* So every `RXNREL` row `(RXCUI1, …, RELA,
|
|
@@ -2791,9 +2808,10 @@ declare const SNOMEDCT_SYSTEM = "http://snomed.info/sct";
|
|
|
2791
2808
|
* fabricates** an `RXCUI` or a relationship absent from the loaded data — an absent concept is a typed
|
|
2792
2809
|
* {@link RxNormUnknown}, an unresolvable NDC a typed {@link NdcUnmapped}, never a guess.
|
|
2793
2810
|
*
|
|
2794
|
-
* **No RxNorm
|
|
2795
|
-
*
|
|
2796
|
-
*
|
|
2811
|
+
* **No RxNorm release is bundled**: the engine ships the graph *machinery*, and RxNorm's
|
|
2812
|
+
* relationship and term-type *names* (`RELA`, `TERM_TYPES`); the caller
|
|
2813
|
+
* supplies the RRF release (the public-domain Current Prescribable Content, or the full BYO
|
|
2814
|
+
* release).
|
|
2797
2815
|
*
|
|
2798
2816
|
* @packageDocumentation
|
|
2799
2817
|
*/
|
|
@@ -2802,8 +2820,13 @@ declare const SNOMEDCT_SYSTEM = "http://snomed.info/sct";
|
|
|
2802
2820
|
* `RXNCONSO.RRF` `TTY` values relevant to the drug graph, grounded on the NLM RxNorm Technical
|
|
2803
2821
|
* Documentation (Appendix 5). Carried verbatim on a {@link RxNormConcept}; the engine classifies but
|
|
2804
2822
|
* never re-labels a concept.
|
|
2823
|
+
*
|
|
2824
|
+
* `PSN` / `SY` / `TMSY` are Appendix 5's **synonym** term types: each labels an alternate *name* on
|
|
2825
|
+
* some other concept rather than a concept of its own, so they are part of this vocabulary but can
|
|
2826
|
+
* never appear as a loaded {@link RxNormConcept.tty}. See
|
|
2827
|
+
* {@link ../rxnorm/tty.isSynonymTermType}.
|
|
2805
2828
|
*/
|
|
2806
|
-
type TermType = "IN" | "PIN" | "MIN" | "BN" | "SCDC" | "SBDC" | "SCD" | "SBD" | "SCDG" | "SBDG" | "GPCK" | "BPCK" | "DF" | "DFG" | "PSN" | "SY" | "TMSY" | "ET";
|
|
2829
|
+
type TermType = "IN" | "PIN" | "MIN" | "BN" | "SCDC" | "SBDC" | "SCDF" | "SBDF" | "SCDFP" | "SBDFP" | "SCD" | "SBD" | "SCDG" | "SBDG" | "SCDGP" | "GPCK" | "BPCK" | "DF" | "DFG" | "PSN" | "SY" | "TMSY" | "ET";
|
|
2807
2830
|
/**
|
|
2808
2831
|
* One RxNorm concept (`RXCUI`) as loaded from `RXNCONSO.RRF` — its normalized name and term type.
|
|
2809
2832
|
* Built from the concept's `SAB=RXNORM` atom (the normalized form); the verbatim `RXCUI`, `TTY`, and
|
|
@@ -2812,7 +2835,10 @@ type TermType = "IN" | "PIN" | "MIN" | "BN" | "SCDC" | "SBDC" | "SCD" | "SBD" |
|
|
|
2812
2835
|
interface RxNormConcept {
|
|
2813
2836
|
/** The RxNorm concept unique identifier (`RXCUI`), verbatim. */
|
|
2814
2837
|
readonly rxcui: string;
|
|
2815
|
-
/**
|
|
2838
|
+
/**
|
|
2839
|
+
* The concept's term type ({@link TermType}), verbatim from the `RXNCONSO.TTY` of a **defining**
|
|
2840
|
+
* atom. Never a synonym-class `TTY` (`PSN`/`SY`/`TMSY`), which types a name rather than a concept.
|
|
2841
|
+
*/
|
|
2816
2842
|
readonly tty: TermType;
|
|
2817
2843
|
/** The concept's normalized name (`RXNCONSO.STR`), verbatim. */
|
|
2818
2844
|
readonly name: string;
|
|
@@ -2835,7 +2861,7 @@ interface RxNormEdge {
|
|
|
2835
2861
|
/**
|
|
2836
2862
|
* A resolved **NDC → RXCUI** mapping (from an `RXNSAT.RRF` `ATN=NDC` attribute), carrying the
|
|
2837
2863
|
* temporal {@link NdcStatus} and the **as-of release** it is valid for. NDC↔RXCUI is many:1 and
|
|
2838
|
-
* changes across releases
|
|
2864
|
+
* changes across releases, so a resolution is never timeless — the release rides
|
|
2839
2865
|
* through on {@link asOf}.
|
|
2840
2866
|
*/
|
|
2841
2867
|
interface NdcResolution {
|
|
@@ -2855,7 +2881,7 @@ interface NdcResolution {
|
|
|
2855
2881
|
* / `UNKNOWN`). An NDC found in the loaded release's `RXNSAT` attributes is `active` **as of that
|
|
2856
2882
|
* release**; `obsolete` / `alien` come from the RxNav NDC-history data (a differential / BYO source,
|
|
2857
2883
|
* not the base RRF concept files) and are surfaced only when the caller supplies them — the engine
|
|
2858
|
-
* **never fabricates** a non-current status
|
|
2884
|
+
* **never fabricates** a non-current status.
|
|
2859
2885
|
*/
|
|
2860
2886
|
type NdcStatus = "active" | "obsolete" | "alien" | "unknown";
|
|
2861
2887
|
/** An NDC that could not be resolved to any `RXCUI` in the loaded release — a typed absence. */
|
|
@@ -2886,8 +2912,8 @@ interface RxNormRelated {
|
|
|
2886
2912
|
}
|
|
2887
2913
|
/**
|
|
2888
2914
|
* A typed **unknown** navigation result — the queried `RXCUI` is **absent from the loaded graph**. A
|
|
2889
|
-
* first-class outcome, never a fabricated concept or an empty success (the never-fabricate
|
|
2890
|
-
* applied to the drug graph
|
|
2915
|
+
* first-class outcome, never a fabricated concept or an empty success (the never-fabricate
|
|
2916
|
+
* invariant, applied to the drug graph). Distinct from a {@link RxNormRelated} with empty
|
|
2891
2917
|
* `targets`, which means "present, but no such relationship".
|
|
2892
2918
|
*/
|
|
2893
2919
|
interface RxNormUnknown {
|
|
@@ -2901,7 +2927,7 @@ interface RxNormUnknown {
|
|
|
2901
2927
|
/** The result of a graph-navigation query: a match (possibly empty) or a typed unknown source. */
|
|
2902
2928
|
type RxNormNavResult = RxNormRelated | RxNormUnknown;
|
|
2903
2929
|
/**
|
|
2904
|
-
* One **approximate**-match candidate (the opt-in, never-default path
|
|
2930
|
+
* One **approximate**-match candidate (the opt-in, never-default path). Every field is
|
|
2905
2931
|
* marked so a caller can never mistake it for an exact identity: {@link approximate} is always `true`
|
|
2906
2932
|
* and {@link score} is the labeled, derived similarity. The concept itself is drawn verbatim from the
|
|
2907
2933
|
* loaded release.
|
|
@@ -2915,13 +2941,17 @@ interface RxNormApproximateMatch {
|
|
|
2915
2941
|
readonly score: number;
|
|
2916
2942
|
}
|
|
2917
2943
|
/**
|
|
2918
|
-
* A surfaced, non-fatal RxNorm load warning
|
|
2919
|
-
* was **skipped**, reported with its line number and
|
|
2920
|
-
*
|
|
2944
|
+
* A surfaced, non-fatal RxNorm load warning: an `RXNCONSO` / `RXNREL` / `RXNSAT` row (or, for
|
|
2945
|
+
* `TERM_RXNORM_UNTYPED_CONCEPT`, an `RXCUI`) that was **skipped**, reported with its line number and
|
|
2946
|
+
* a value-free structural reason (liberal on load). Never echoes a field value.
|
|
2921
2947
|
*/
|
|
2922
2948
|
interface RxNormLoadWarning {
|
|
2923
|
-
/**
|
|
2924
|
-
|
|
2949
|
+
/**
|
|
2950
|
+
* The stable diagnostic code for the skip. `TERM_RXNORM_MALFORMED_ROW` is a structurally unusable
|
|
2951
|
+
* row; `TERM_RXNORM_UNTYPED_CONCEPT` is an `RXCUI` no defining atom could type. Both are in the
|
|
2952
|
+
* package-wide {@link ../common/diagnostics.DIAGNOSTIC_CODES} registry, which documents each.
|
|
2953
|
+
*/
|
|
2954
|
+
readonly code: "TERM_RXNORM_MALFORMED_ROW" | "TERM_RXNORM_UNTYPED_CONCEPT";
|
|
2925
2955
|
/** Which source file the fault was in. */
|
|
2926
2956
|
readonly file: "RXNCONSO" | "RXNREL" | "RXNSAT";
|
|
2927
2957
|
/** The 1-based source line the fault was found on. */
|
|
@@ -2954,7 +2984,7 @@ interface RxNormGraph {
|
|
|
2954
2984
|
}
|
|
2955
2985
|
|
|
2956
2986
|
/**
|
|
2957
|
-
* The **RxNorm drug graph loader**
|
|
2987
|
+
* The **RxNorm drug graph loader** — build an immutable {@link RxNormGraph} from a
|
|
2958
2988
|
* **caller-supplied** RxNorm RRF release (`RXNCONSO.RRF` + `RXNREL.RRF`, and optionally `RXNSAT.RRF`
|
|
2959
2989
|
* for NDC attributes). Reuses the shared, zero-dep {@link ../codesystem/rrf.parseRrfLine} (pipe split,
|
|
2960
2990
|
* reserved trailing pipe) — the same RRF reader the CodeSystem layer uses.
|
|
@@ -2963,8 +2993,8 @@ interface RxNormGraph {
|
|
|
2963
2993
|
* descriptions):
|
|
2964
2994
|
* - `RXNCONSO.RRF` (18 cols): `RXCUI`(0) `LAT`(1) `TS`(2) `LUI`(3) `STT`(4) `SUI`(5) `ISPREF`(6)
|
|
2965
2995
|
* `RXAUI`(7) `SAUI`(8) `SCUI`(9) `SDUI`(10) `SAB`(11) `TTY`(12) `CODE`(13) `STR`(14) `SRL`(15)
|
|
2966
|
-
* `SUPPRESS`(16) `CVF`(17). Only the **normalized** atoms (`SAB=RXNORM`)
|
|
2967
|
-
*
|
|
2996
|
+
* `SUPPRESS`(16) `CVF`(17). Only the **normalized** atoms (`SAB=RXNORM`) become graph concepts, and
|
|
2997
|
+
* only through a **defining** `TTY` (see "Typing a concept" below).
|
|
2968
2998
|
* - `RXNREL.RRF` (16 cols): `RXCUI1`(0) `RXAUI1`(1) `STYPE1`(2) `REL`(3) `RXCUI2`(4) `RXAUI2`(5)
|
|
2969
2999
|
* `STYPE2`(6) `RELA`(7) `RUI`(8) `SRUI`(9) `SAB`(10) `SL`(11) `RG`(12) `DIR`(13) `SUPPRESS`(14)
|
|
2970
3000
|
* `CVF`(15). Read `subject = RXCUI2`, `predicate = RELA`, `object = RXCUI1` (the direction
|
|
@@ -2973,18 +3003,30 @@ interface RxNormGraph {
|
|
|
2973
3003
|
* - `RXNSAT.RRF` (13 cols): `RXCUI`(0) … `ATN`(8) `SAB`(9) `ATV`(10) `SUPPRESS`(11) `CVF`(12). Rows
|
|
2974
3004
|
* with `ATN=NDC` index `ATV`(the NDC) → `RXCUI`, marked `active` **as of** the loaded release.
|
|
2975
3005
|
*
|
|
2976
|
-
* **
|
|
3006
|
+
* **Typing a concept (`RXNCONSO`).** An `RXCUI` carries one **defining** atom (its normalized
|
|
3007
|
+
* name, a `TTY` from Appendix 5's "Normalized Names" table) plus any number of **synonym** atoms, whose
|
|
3008
|
+
* `TTY` (`PSN`/`SY`/`TMSY`) Appendix 5 defines as a *"synonym of another TTY"*: it types a **name**,
|
|
3009
|
+
* not a concept. RxNorm documents no ordering between an `RXCUI`'s atoms, so the loader takes the
|
|
3010
|
+
* **defining** atom wherever it sits in the file (first-wins among defining atoms) and **never** falls
|
|
3011
|
+
* back to a synonym atom. An `RXCUI` that no defining atom could type, because every atom is
|
|
3012
|
+
* synonym-class or carries a `TTY` this engine does not model, is **skipped and surfaced** as a
|
|
3013
|
+
* `TERM_RXNORM_UNTYPED_CONCEPT` warning naming the line. Skipping is the deliberate choice: an absent
|
|
3014
|
+
* concept is already a first-class typed outcome (`TERM_RXNORM_UNKNOWN_RXCUI`), whereas a concept
|
|
3015
|
+
* whose `tty` reads `"TMSY"` is a fabricated claim about what the drug *is*, indistinguishable from a
|
|
3016
|
+
* real one.
|
|
3017
|
+
*
|
|
3018
|
+
* **Liberal on load**: a structurally unusable *row* (too few columns, missing a required
|
|
2977
3019
|
* value) is **skipped and surfaced** as a `TERM_RXNORM_MALFORMED_ROW` warning, never a partial
|
|
2978
3020
|
* concept/edge, never a crash. Rows that are simply *not of interest* (a non-`RXNORM` atom, an
|
|
2979
3021
|
* atom-level relationship, a non-`NDC` attribute) are skipped **silently** — they are expected, not
|
|
2980
|
-
* faults. Ships **no** RxNorm
|
|
3022
|
+
* faults. Ships **no** RxNorm release: every concept/edge is the caller's.
|
|
2981
3023
|
*
|
|
2982
3024
|
* @packageDocumentation
|
|
2983
3025
|
*/
|
|
2984
3026
|
|
|
2985
3027
|
/**
|
|
2986
3028
|
* A raw RxNorm RRF release, BYO. The caller supplies the public-domain Current Prescribable Content
|
|
2987
|
-
* subset or the full (licensed) release; the engine bundles **no** RxNorm
|
|
3029
|
+
* subset or the full (licensed) release; the engine bundles **no** RxNorm release.
|
|
2988
3030
|
*/
|
|
2989
3031
|
interface RxNormGraphSource {
|
|
2990
3032
|
/** The raw `RXNCONSO.RRF` content (pipe-delimited concept/atom names). */
|
|
@@ -3001,8 +3043,12 @@ interface RxNormGraphSource {
|
|
|
3001
3043
|
*
|
|
3002
3044
|
* Parses `RXNCONSO` (concepts), `RXNREL` (directed edges, normalized to the documented direction), and
|
|
3003
3045
|
* — when supplied — `RXNSAT` (NDC attributes). Liberal on load: a structurally unusable row is a
|
|
3004
|
-
* skipped, surfaced {@link RxNormLoadWarning}, never partial. Ships **no** RxNorm
|
|
3005
|
-
* is entirely the caller's release
|
|
3046
|
+
* skipped, surfaced {@link RxNormLoadWarning}, never partial. Ships **no** RxNorm release — the graph
|
|
3047
|
+
* is entirely the caller's release.
|
|
3048
|
+
*
|
|
3049
|
+
* A concept is typed only by a **defining** atom, never by a synonym-class one and never by file
|
|
3050
|
+
* order; an `RXCUI` no defining atom could type is skipped and surfaced as
|
|
3051
|
+
* `TERM_RXNORM_UNTYPED_CONCEPT`. See the module documentation.
|
|
3006
3052
|
*
|
|
3007
3053
|
* @param source - The {@link RxNormGraphSource} (RRF file contents + optional version).
|
|
3008
3054
|
* @returns The immutable {@link RxNormGraph}.
|
|
@@ -3010,10 +3056,10 @@ interface RxNormGraphSource {
|
|
|
3010
3056
|
* ```ts
|
|
3011
3057
|
* import { loadRxNormGraph } from "@cosyte/terminology";
|
|
3012
3058
|
*
|
|
3013
|
-
* // Synthetic rows in the RxNorm RRF wire format (no
|
|
3059
|
+
* // Synthetic rows in the RxNorm RRF wire format (no RxNorm release is bundled).
|
|
3014
3060
|
* const graph = loadRxNormGraph({
|
|
3015
|
-
* conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|
|
|
3016
|
-
* // "
|
|
3061
|
+
* conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|SCDC||lisinopril 10 MG||N||",
|
|
3062
|
+
* // "SCDC(2) has_ingredient IN(1)": subject=RXCUI2=2, object=RXCUI1=1.
|
|
3017
3063
|
* rel: "1|||RN|2|||has_ingredient|||RXNORM||||||",
|
|
3018
3064
|
* });
|
|
3019
3065
|
* graph.conceptCount; // => 2
|
|
@@ -3022,9 +3068,9 @@ interface RxNormGraphSource {
|
|
|
3022
3068
|
declare function loadRxNormGraph(source: RxNormGraphSource): RxNormGraph;
|
|
3023
3069
|
|
|
3024
3070
|
/**
|
|
3025
|
-
* **RxNorm drug-graph navigation
|
|
3026
|
-
* drug to its generic, a drug to its dose form, and an NDC to its `RXCUI`, over
|
|
3027
|
-
* {@link RxNormGraph}. Every query is **fail-safe and never-fabricate
|
|
3071
|
+
* **RxNorm drug-graph navigation**: resolve a drug to its components and its
|
|
3072
|
+
* ingredient, a branded drug to its generic, a drug to its dose form, and an NDC to its `RXCUI`, over
|
|
3073
|
+
* a loaded {@link RxNormGraph}. Every query is **fail-safe and never-fabricate**:
|
|
3028
3074
|
*
|
|
3029
3075
|
* - a queried `RXCUI` absent from the graph is a typed {@link RxNormUnknown}, never a guessed concept;
|
|
3030
3076
|
* - a present concept with no such relationship is a {@link RxNormRelated} with **empty** `targets` —
|
|
@@ -3067,9 +3113,9 @@ declare function getConcept(graph: RxNormGraph, rxcui: string): RxNormConcept |
|
|
|
3067
3113
|
* ```ts
|
|
3068
3114
|
* import { loadRxNormGraph, relatedByRela, RELA } from "@cosyte/terminology";
|
|
3069
3115
|
*
|
|
3070
|
-
* // "
|
|
3116
|
+
* // "SCDC(2) has_ingredient IN(1)": subject=RXCUI2=2, object=RXCUI1=1.
|
|
3071
3117
|
* const g = loadRxNormGraph({
|
|
3072
|
-
* conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|
|
|
3118
|
+
* conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|SCDC||lisinopril 10 MG||N||",
|
|
3073
3119
|
* rel: "1|||RN|2|||has_ingredient|||RXNORM||||||",
|
|
3074
3120
|
* });
|
|
3075
3121
|
* const r = relatedByRela(g, "2", RELA.HAS_INGREDIENT);
|
|
@@ -3081,12 +3127,35 @@ declare function relatedByRela(graph: RxNormGraph, rxcui: string, predicate: str
|
|
|
3081
3127
|
* The **ingredients** of a concept — the concepts it links to by a **direct** `has_ingredient` /
|
|
3082
3128
|
* `has_precise_ingredient` edge in the loaded release.
|
|
3083
3129
|
*
|
|
3084
|
-
* This follows the *authored, direct* edge only (never-fabricate, never a synthesized path)
|
|
3085
|
-
*
|
|
3086
|
-
*
|
|
3087
|
-
*
|
|
3088
|
-
*
|
|
3089
|
-
*
|
|
3130
|
+
* This follows the *authored, direct* edge only (never-fabricate, never a synthesized path), and
|
|
3131
|
+
* **RxNorm's ingredient topology is not the obvious one**. Always read the `TTY` of what comes back:
|
|
3132
|
+
*
|
|
3133
|
+
* - concepts on the **clinical** side (`SCDC`, `SCDF`, `SCDG`) link to the ingredient itself, an
|
|
3134
|
+
* `IN`;
|
|
3135
|
+
* - concepts on the **branded** side (`SBD`, `SBDC`, `SBDF`, `SBDG`) link to their **brand name**, a
|
|
3136
|
+
* `BN`. That is what the release says and what is echoed back, term type included. It is *not* the
|
|
3137
|
+
* active ingredient. (`has_precise_ingredient`, which this function also follows, likewise reaches
|
|
3138
|
+
* a `PIN`.)
|
|
3139
|
+
* - a **clinical drug** (`SCD`) carries **no** `has_ingredient` edge at all. RxNorm authors none, in
|
|
3140
|
+
* any release, so this honestly returns found-with-empty-targets rather than walking a path on the
|
|
3141
|
+
* caller's behalf.
|
|
3142
|
+
* - the **precise** forms (`SCDFP`, `SBDFP`, `SCDGP`) carry **neither** edge, so this returns
|
|
3143
|
+
* found-with-empty-targets for them too. They do **not** behave like their non-precise siblings:
|
|
3144
|
+
* an `SCDFP` reaches its basis-of-strength substance(s) by `has_boss`, a one-to-many relation with
|
|
3145
|
+
* a different meaning whose targets can be a `PIN` or a plain `IN`, and which this function
|
|
3146
|
+
* deliberately does not follow; an `SBDFP` and an
|
|
3147
|
+
* `SCDGP` author no ingredient-bearing edge at all and are reached instead through `form_of` /
|
|
3148
|
+
* `tradename_of` / `isa`.
|
|
3149
|
+
*
|
|
3150
|
+
* Those pairings are the ones RxNorm authors, not a closed set a caller may rely on: check the
|
|
3151
|
+
* returned `TTY` rather than assuming it from the one you queried.
|
|
3152
|
+
*
|
|
3153
|
+
* **To reach an active ingredient, walk to the CLINICAL component and take its edge.** From an `SCD`
|
|
3154
|
+
* that is `SCD ⟶consists_of⟶ SCDC ⟶has_ingredient⟶ IN`, i.e. {@link consistsOf} then
|
|
3155
|
+
* `ingredientsOf`. From an `SBD` it needs one more decision, because `consists_of` returns **both**
|
|
3156
|
+
* its branded component (`SBDC`, whose own ingredient edge is the `BN` again) and the clinical
|
|
3157
|
+
* `SCDC`: it is the `SCDC` that leads to the `IN`. The engine never invents the transitive edge and
|
|
3158
|
+
* never picks that branch for you.
|
|
3090
3159
|
*
|
|
3091
3160
|
* @param graph - A loaded {@link RxNormGraph}.
|
|
3092
3161
|
* @param rxcui - The concept (a drug or a clinical/branded component).
|
|
@@ -3095,8 +3164,9 @@ declare function relatedByRela(graph: RxNormGraph, rxcui: string, predicate: str
|
|
|
3095
3164
|
* ```ts
|
|
3096
3165
|
* import { loadRxNormGraph, ingredientsOf } from "@cosyte/terminology";
|
|
3097
3166
|
*
|
|
3167
|
+
* // The ingredient edge is authored on the COMPONENT, not on the clinical drug.
|
|
3098
3168
|
* const g = loadRxNormGraph({
|
|
3099
|
-
* conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|
|
|
3169
|
+
* conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|SCDC||lisinopril 10 MG||N||",
|
|
3100
3170
|
* rel: "1|||RN|2|||has_ingredient|||RXNORM||||||",
|
|
3101
3171
|
* });
|
|
3102
3172
|
* ingredientsOf(g, "2").found; // => true
|
|
@@ -3116,7 +3186,7 @@ declare function ingredientsOf(graph: RxNormGraph, rxcui: string): RxNormNavResu
|
|
|
3116
3186
|
*
|
|
3117
3187
|
* // "SBD(2) tradename_of SCD(1)": subject=RXCUI2=2, object=RXCUI1=1.
|
|
3118
3188
|
* const g = loadRxNormGraph({
|
|
3119
|
-
* conso: "1|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||\n2|ENG||||||||||RXNORM|SBD||
|
|
3189
|
+
* conso: "1|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||\n2|ENG||||||||||RXNORM|SBD||lisinopril 10 MG Oral Tablet [Zestril]||N||",
|
|
3120
3190
|
* rel: "1|||RN|2|||tradename_of|||RXNORM||||||",
|
|
3121
3191
|
* });
|
|
3122
3192
|
* genericFor(g, "2").found; // => true
|
|
@@ -3135,7 +3205,7 @@ declare function genericFor(graph: RxNormGraph, rxcui: string): RxNormNavResult;
|
|
|
3135
3205
|
* import { loadRxNormGraph, brandsFor } from "@cosyte/terminology";
|
|
3136
3206
|
*
|
|
3137
3207
|
* const g = loadRxNormGraph({
|
|
3138
|
-
* conso: "1|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||\n2|ENG||||||||||RXNORM|SBD||
|
|
3208
|
+
* conso: "1|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||\n2|ENG||||||||||RXNORM|SBD||lisinopril 10 MG Oral Tablet [Zestril]||N||",
|
|
3139
3209
|
* rel: "2|||RN|1|||has_tradename|||RXNORM||||||",
|
|
3140
3210
|
* });
|
|
3141
3211
|
* brandsFor(g, "1").found; // => true
|
|
@@ -3180,7 +3250,7 @@ declare function doseFormsOf(graph: RxNormGraph, rxcui: string): RxNormNavResult
|
|
|
3180
3250
|
declare function consistsOf(graph: RxNormGraph, rxcui: string): RxNormNavResult;
|
|
3181
3251
|
/**
|
|
3182
3252
|
* Resolve an **NDC** (National Drug Code) to its `RXCUI` in the loaded release, carrying the temporal
|
|
3183
|
-
* status and the as-of release. NDC↔RXCUI is many:1 and changes across releases
|
|
3253
|
+
* status and the as-of release. NDC↔RXCUI is many:1 and changes across releases, so an
|
|
3184
3254
|
* NDC present in the release is `active` **as of that release**; an absent NDC is a typed
|
|
3185
3255
|
* {@link NdcUnmapped}, never a guessed `RXCUI`.
|
|
3186
3256
|
*
|
|
@@ -3210,12 +3280,12 @@ interface ApproximateMatchOptions {
|
|
|
3210
3280
|
readonly limit?: number;
|
|
3211
3281
|
}
|
|
3212
3282
|
/**
|
|
3213
|
-
* **Opt-in, explicitly labeled** approximate name matching
|
|
3283
|
+
* **Opt-in, explicitly labeled** approximate name matching — find loaded concepts whose
|
|
3214
3284
|
* names are token-similar to `query`. This is **never** the default resolution path and its results
|
|
3215
3285
|
* are **never** an exact code assertion: every candidate is marked `approximate: true` with a derived
|
|
3216
3286
|
* {@link RxNormApproximateMatch.score}. A caller opts in by calling this function explicitly.
|
|
3217
3287
|
*
|
|
3218
|
-
* Coverage is not correctness
|
|
3288
|
+
* Coverage is not correctness: a "no match" is an **empty** array (typed, honest),
|
|
3219
3289
|
* distinct from a fabricated nearest guess. The engine never promotes an approximate hit to an exact
|
|
3220
3290
|
* one.
|
|
3221
3291
|
*
|
|
@@ -3240,10 +3310,10 @@ declare function approximateMatch(graph: RxNormGraph, query: string, options?: A
|
|
|
3240
3310
|
* The RxNorm **relationship (`RELA`) vocabulary** and the **direction convention** the drug graph is
|
|
3241
3311
|
* built on — encoded here as published identity facts (like the code-system OID↔URI facts in
|
|
3242
3312
|
* {@link ../systems/registry}), grounded firsthand on the NLM RxNorm Technical Documentation and the
|
|
3243
|
-
* UMLS Reference Manual. **No RxNorm
|
|
3244
|
-
* *rule* for reading a row's direction
|
|
3313
|
+
* UMLS Reference Manual. **No RxNorm release is bundled** — what ships is the relationship *names*
|
|
3314
|
+
* and the *rule* for reading a row's direction.
|
|
3245
3315
|
*
|
|
3246
|
-
* **The direction rule (
|
|
3316
|
+
* **The direction rule (a documented medication-safety trap).** From the
|
|
3247
3317
|
* RxNorm Technical Documentation (§12.7) and the UMLS Reference Manual, verbatim: *"the direction of
|
|
3248
3318
|
* REL — the relationship which the SECOND concept or atom (with … RXCUI2 …) HAS TO the FIRST concept
|
|
3249
3319
|
* or atom (with … RXCUI1 …)."* The doc's worked example — a row with `RXCUI1=1155862`, `RELA=isa`,
|
|
@@ -3251,10 +3321,21 @@ declare function approximateMatch(graph: RxNormGraph, query: string, options?: A
|
|
|
3251
3321
|
*
|
|
3252
3322
|
* So an `RXNREL.RRF` row is read **`RXCUI2 ⟶RELA⟶ RXCUI1`**, and {@link ../rxnorm/load.loadRxNormGraph}
|
|
3253
3323
|
* normalizes every row to `subject = RXCUI2`, `predicate = RELA`, `object = RXCUI1`. Concretely, a
|
|
3254
|
-
* `has_ingredient` row places the **
|
|
3255
|
-
*
|
|
3256
|
-
*
|
|
3257
|
-
*
|
|
3324
|
+
* `has_ingredient` row places the **having** concept in `RXCUI2` and what it *has* in `RXCUI1`; a
|
|
3325
|
+
* `tradename_of` row places the **branded** concept in `RXCUI2` and the **generic** in `RXCUI1` (the
|
|
3326
|
+
* brand *is a tradename of* the generic). Getting this backwards is a wrong-medication bug, so the
|
|
3327
|
+
* fixtures pin it against the doc's convention.
|
|
3328
|
+
*
|
|
3329
|
+
* **Direction is not topology, and the topology is not the obvious one.** Knowing how to read a row
|
|
3330
|
+
* does not tell you which rows exist. RxNorm authors `has_ingredient` from the **clinical** side
|
|
3331
|
+
* (`SCDC`/`SCDF`/`SCDG`) to an `IN`, and from the **branded** side (`SBD`/`SBDC`/`SBDF`/`SBDG`) to a
|
|
3332
|
+
* `BN` rather than to the active ingredient; it authors **no** `SCD ⟶ IN` ingredient edge at all, so
|
|
3333
|
+
* a clinical drug reaches its ingredient only through `consists_of`. The **precise** forms
|
|
3334
|
+
* (`SCDFP`/`SBDFP`/`SCDGP`) carry no `has_ingredient` row either: an `SCDFP` instead reaches its
|
|
3335
|
+
* basis-of-strength substances by `has_boss` (one-to-many, and its targets can be a `PIN` or a plain
|
|
3336
|
+
* `IN`), and the other two author no ingredient-bearing edge at all. Treat those pairings as the
|
|
3337
|
+
* ones RxNorm authors, not as a closed set, and read the `TTY` of what a traversal returns. See
|
|
3338
|
+
* {@link ../rxnorm/navigate.ingredientsOf}.
|
|
3258
3339
|
*
|
|
3259
3340
|
* @packageDocumentation
|
|
3260
3341
|
*/
|
|
@@ -3272,9 +3353,17 @@ declare function approximateMatch(graph: RxNormGraph, query: string, options?: A
|
|
|
3272
3353
|
* ```
|
|
3273
3354
|
*/
|
|
3274
3355
|
declare const RELA: {
|
|
3275
|
-
/**
|
|
3356
|
+
/**
|
|
3357
|
+
* `has_ingredient`: subject *has ingredient* object. Authored from the clinical side
|
|
3358
|
+
* (`SCDC`/`SCDF`/`SCDG`) to an `IN` and from the branded side (`SBD`/`SBDC`/`SBDF`/`SBDG`) to a
|
|
3359
|
+
* `BN`; RxNorm authors no `SCD ⟶ IN` row.
|
|
3360
|
+
*/
|
|
3276
3361
|
readonly HAS_INGREDIENT: "has_ingredient";
|
|
3277
|
-
/**
|
|
3362
|
+
/**
|
|
3363
|
+
* `ingredient_of`: subject *is an ingredient of* object. The authored inverse, so an `IN` reaches
|
|
3364
|
+
* clinical components and dose forms and a `BN` reaches branded concepts (the `SBD` included).
|
|
3365
|
+
* Neither reaches an `SCD`.
|
|
3366
|
+
*/
|
|
3278
3367
|
readonly INGREDIENT_OF: "ingredient_of";
|
|
3279
3368
|
/** `has_precise_ingredient` — subject *has precise ingredient* object (a `PIN`). */
|
|
3280
3369
|
readonly HAS_PRECISE_INGREDIENT: "has_precise_ingredient";
|
|
@@ -3331,33 +3420,47 @@ declare const RXNORM_SYSTEM = "http://www.nlm.nih.gov/research/umls/rxnorm";
|
|
|
3331
3420
|
/**
|
|
3332
3421
|
* The RxNorm **term-type (`TTY`) vocabulary** relevant to the drug graph — the normal-form ladder and
|
|
3333
3422
|
* the cross-link kinds — encoded as published identity facts (grounded firsthand on the NLM RxNorm
|
|
3334
|
-
* Technical Documentation, Appendix 5). **No RxNorm
|
|
3423
|
+
* Technical Documentation, Appendix 5). **No RxNorm release is bundled**: what ships is these
|
|
3335
3424
|
* *labels*, not the drug list.
|
|
3336
3425
|
*
|
|
3337
3426
|
* The RxNorm normal-form graph runs `IN → SCDC → SCD → SBD` (ingredient → clinical-drug component →
|
|
3338
3427
|
* semantic clinical drug → semantic branded drug), with `BN` (brand name) and `DF` (dose form) as
|
|
3339
|
-
* cross-links
|
|
3428
|
+
* cross-links.
|
|
3429
|
+
*
|
|
3430
|
+
* **Appendix 5 splits these into two kinds, and the split is load-bearing.** A **defining** term type
|
|
3431
|
+
* (its "Normalized Names" table, `IN` … `DFG`) says what an `RXCUI` *is*. A **synonym** term type
|
|
3432
|
+
* (its "Synonyms" table, `PSN` / `SY` / `TMSY`) is Appendix 5's own word for an atom that is a
|
|
3433
|
+
* *"synonym of another TTY"*: it types a **name**, not a concept, so it can never be a concept's term
|
|
3434
|
+
* type. `ET` is in neither table; the appendix describes it only in prose, as "a small number of
|
|
3435
|
+
* concepts with TTY=ET, a term type reserved for entry terms for dose forms". Those are concepts in
|
|
3436
|
+
* their own right rather than synonyms carried on another, so `ET` counts as defining here. See
|
|
3437
|
+
* {@link isSynonymTermType} and {@link ../rxnorm/load.loadRxNormGraph}.
|
|
3340
3438
|
*
|
|
3341
3439
|
* @packageDocumentation
|
|
3342
3440
|
*/
|
|
3343
3441
|
|
|
3344
3442
|
/**
|
|
3345
|
-
* The drug-graph term types (`RXNCONSO.TTY`), each mapped to its
|
|
3346
|
-
*
|
|
3347
|
-
*
|
|
3443
|
+
* The drug-graph term types (`RXNCONSO.TTY`), each mapped to its **verbatim Appendix 5 name** (`ET`
|
|
3444
|
+
* excepted: the appendix publishes no Name for it, so the UMLS expansion "Entry Term" is used).
|
|
3445
|
+
* Encoded as an identity fact; a concept's `TTY` is carried verbatim on its
|
|
3446
|
+
* {@link ../rxnorm/types.RxNormConcept}, never re-labeled.
|
|
3447
|
+
*
|
|
3448
|
+
* The keys are the full Appendix 5 vocabulary, defining and synonym alike. Only the **defining** ones
|
|
3449
|
+
* can appear on a loaded concept (see {@link isSynonymTermType}).
|
|
3348
3450
|
*
|
|
3349
3451
|
* @example
|
|
3350
3452
|
* ```ts
|
|
3351
3453
|
* import { TERM_TYPES } from "@cosyte/terminology";
|
|
3352
3454
|
*
|
|
3353
3455
|
* TERM_TYPES.SCD; // => "Semantic Clinical Drug"
|
|
3456
|
+
* TERM_TYPES.SCDF; // => "Semantic Clinical Drug Form"
|
|
3354
3457
|
* ```
|
|
3355
3458
|
*/
|
|
3356
3459
|
declare const TERM_TYPES: Readonly<Record<TermType, string>>;
|
|
3357
3460
|
/**
|
|
3358
3461
|
* Narrow a raw `RXNCONSO.TTY` string to a known {@link TermType}, or `undefined` when it is not a
|
|
3359
|
-
* drug-graph term type this engine models (the
|
|
3360
|
-
*
|
|
3462
|
+
* drug-graph term type this engine models (the atom is then skipped at load, liberal-on-load, never
|
|
3463
|
+
* coerced to a wrong type).
|
|
3361
3464
|
*
|
|
3362
3465
|
* @param tty - The raw `TTY` value from an `RXNCONSO` row.
|
|
3363
3466
|
* @returns The narrowed {@link TermType}, or `undefined` when unrecognized.
|
|
@@ -3370,6 +3473,25 @@ declare const TERM_TYPES: Readonly<Record<TermType, string>>;
|
|
|
3370
3473
|
* ```
|
|
3371
3474
|
*/
|
|
3372
3475
|
declare function asTermType(tty: string): TermType | undefined;
|
|
3476
|
+
/**
|
|
3477
|
+
* Is this term type a **synonym-class** one (`PSN` / `SY` / `TMSY`)?
|
|
3478
|
+
*
|
|
3479
|
+
* Appendix 5 defines each as a *"synonym of another TTY"*: it labels an alternate **name** for a
|
|
3480
|
+
* concept, never the concept's own kind. So a synonym atom can never establish an `RXCUI`'s term
|
|
3481
|
+
* type, and {@link ../rxnorm/load.loadRxNormGraph} will not let one: an `RXCUI` whose release
|
|
3482
|
+
* supplies only synonym atoms is skipped and surfaced, never typed `"TMSY"`.
|
|
3483
|
+
*
|
|
3484
|
+
* @param tty - A {@link TermType}.
|
|
3485
|
+
* @returns `true` for `PSN` / `SY` / `TMSY`; `false` for every defining term type.
|
|
3486
|
+
* @example
|
|
3487
|
+
* ```ts
|
|
3488
|
+
* import { isSynonymTermType } from "@cosyte/terminology";
|
|
3489
|
+
*
|
|
3490
|
+
* isSynonymTermType("TMSY"); // => true
|
|
3491
|
+
* isSynonymTermType("SCDF"); // => false
|
|
3492
|
+
* ```
|
|
3493
|
+
*/
|
|
3494
|
+
declare function isSynonymTermType(tty: TermType): boolean;
|
|
3373
3495
|
|
|
3374
3496
|
/**
|
|
3375
3497
|
* Public entry point for **`@cosyte/terminology`** — a zero-dependency, developer-focused
|
|
@@ -3377,28 +3499,30 @@ declare function asTermType(tty: string): TermType | undefined;
|
|
|
3377
3499
|
*
|
|
3378
3500
|
* Unlike its sibling `@cosyte/*` packages, this is **not a wire-format parser**: it mirrors the
|
|
3379
3501
|
* **FHIR Terminology Module** (`$translate`, `$lookup`, `$validate-code`, `$expand`, …), operating
|
|
3380
|
-
* over **consumer-supplied** FHIR resources. It ships the *engine
|
|
3381
|
-
*
|
|
3382
|
-
*
|
|
3502
|
+
* over **consumer-supplied** FHIR resources. It ships the *engine* and **no code-system release**
|
|
3503
|
+
* (SNOMED CT / CPT / LOINC / UMLS / RxNorm are strictly BYO). It is not content-free: see
|
|
3504
|
+
* **What is bundled** at the end of this note, which includes the UCUM unit table, the code-system
|
|
3505
|
+
* *identities* (OID ↔ URI), the SNOMED CT concepts the crosswalk resolver names and RxNorm's
|
|
3506
|
+
* relationship and term-type names, each with its copyright.
|
|
3383
3507
|
*
|
|
3384
|
-
* **
|
|
3508
|
+
* **Code-system identity and ConceptMap translation:**
|
|
3385
3509
|
*
|
|
3386
3510
|
* - {@link resolveSystem} — the code-system identity / canonical-URI resolver (mnemonic | OID → URI).
|
|
3387
3511
|
* - {@link loadConceptMap} + {@link translate} — the ConceptMap `$translate` engine, with the
|
|
3388
3512
|
* **never-fabricate / never-invert** invariants: an unmapped source is a typed
|
|
3389
3513
|
* {@link TranslateUnmapped}, never a guessed target; a directional map is never run backwards.
|
|
3390
3514
|
*
|
|
3391
|
-
* **
|
|
3515
|
+
* **The CodeSystem load layer**, with the FHIR `$lookup` / `$validate-code` operations:
|
|
3392
3516
|
*
|
|
3393
3517
|
* - {@link loadCodeSystem} — load a **consumer-supplied** release (RRF / CSV / fixed-width / FHIR
|
|
3394
|
-
* `CodeSystem` JSON) into an immutable model. Ships the
|
|
3518
|
+
* `CodeSystem` JSON) into an immutable model. Ships the loader; **no code-system release**.
|
|
3395
3519
|
* - {@link lookup} — code → display + properties, carrying status (deprecated / header-not-billable).
|
|
3396
3520
|
* - {@link validateCode} — is a code a valid member of the system, with its status flags.
|
|
3397
3521
|
*
|
|
3398
3522
|
* The never-fabricate invariant holds here too: an unknown code is a typed `unknown` / `valid: false`,
|
|
3399
3523
|
* never a fabricated display or a guessed `valid: true`.
|
|
3400
3524
|
*
|
|
3401
|
-
* **
|
|
3525
|
+
* **The ValueSet binding layer** — FHIR `$expand` / `$validate-code` over a `compose`:
|
|
3402
3526
|
*
|
|
3403
3527
|
* - {@link loadValueSet} — load a **consumer-supplied** FHIR `ValueSet` (intensional `compose` and/or
|
|
3404
3528
|
* a pre-computed `expansion`) into an immutable model.
|
|
@@ -3408,8 +3532,8 @@ declare function asTermType(tty: string): TermType | undefined;
|
|
|
3408
3532
|
* - {@link validateCodeInValueSet} — binding membership, returning a **decided** `result` only when
|
|
3409
3533
|
* proven and a typed `undetermined` otherwise (a truncated expansion never reads as complete).
|
|
3410
3534
|
*
|
|
3411
|
-
* **
|
|
3412
|
-
*
|
|
3535
|
+
* **The UCUM unit layer** — a hand-rolled UCUM grammar parser + validation + representation
|
|
3536
|
+
* canonicalization (recognition only, **no** magnitude conversion):
|
|
3413
3537
|
*
|
|
3414
3538
|
* - {@link validateUcum} — is a string a valid UCUM unit; if so, its canonical descriptor. An
|
|
3415
3539
|
* invalid unit is a typed `TERM_UCUM_INVALID`, never a guessed "nearest" unit.
|
|
@@ -3418,25 +3542,25 @@ declare function asTermType(tty: string): TermType | undefined;
|
|
|
3418
3542
|
* - {@link parseUcum} / {@link reduce} / {@link loadUcumEssence} — the underlying grammar parser,
|
|
3419
3543
|
* dimensional reducer, and the in-memory model of the vendored, verbatim UCUM table.
|
|
3420
3544
|
*
|
|
3421
|
-
* **
|
|
3422
|
-
*
|
|
3545
|
+
* **The crosswalk resolvers** — the never-fabricate/never-invert invariant applied to the
|
|
3546
|
+
* published, directional reference maps:
|
|
3423
3547
|
*
|
|
3424
3548
|
* - {@link loadGems} + {@link applyGem} — the CMS **ICD-9↔ICD-10 GEMs** (public-domain reference
|
|
3425
3549
|
* mappings), honoring the steward's Approximate / No-Map / Combination (scenario→choice-list) flags.
|
|
3426
3550
|
* A No-Map source is a typed {@link CrosswalkNoMap}; a 1:many source returns the full candidate set.
|
|
3427
3551
|
* - {@link loadComplexMap} + {@link applyComplexMap} — the NLM **SNOMED CT → ICD-10-CM complex map**
|
|
3428
|
-
* (BYO
|
|
3552
|
+
* (BYO — **no SNOMED CT refset bundled**), evaluating Map Group / Priority / `IFA` Rule /
|
|
3429
3553
|
* Advice / Category against caller-supplied {@link PatientContext}; a rule needing context the
|
|
3430
3554
|
* caller lacks is a typed {@link ComplexMapContextRequired}, never a guessed branch.
|
|
3431
3555
|
* - {@link invertGem} — the never-invert refusal made a first-class, thrown contract
|
|
3432
3556
|
* ({@link FATAL_CODES.TERM_MAP_NOT_INVERTIBLE}).
|
|
3433
3557
|
*
|
|
3434
|
-
* **
|
|
3435
|
-
*
|
|
3558
|
+
* **The RxNorm drug relationship graph** — ingredient / brand / clinical-drug / dose-form
|
|
3559
|
+
* navigation over a **caller-supplied** RxNorm RRF release:
|
|
3436
3560
|
*
|
|
3437
3561
|
* - {@link loadRxNormGraph} — load `RXNCONSO` (concepts, typed by `TTY`), `RXNREL` (directed `RELA`
|
|
3438
3562
|
* edges, normalized to the documented `RXCUI2 ⟶RELA⟶ RXCUI1` direction), and optionally `RXNSAT`
|
|
3439
|
-
* (NDC attributes) into an immutable graph. Ships **no** RxNorm
|
|
3563
|
+
* (NDC attributes) into an immutable graph. Ships **no** RxNorm release — BYO.
|
|
3440
3564
|
* - {@link ingredientsOf} / {@link genericFor} / {@link brandsFor} / {@link doseFormsOf} /
|
|
3441
3565
|
* {@link consistsOf} / {@link relatedByRela} — graph navigation following **authored** edges only
|
|
3442
3566
|
* (the engine never synthesizes an inverse). An absent `RXCUI` is a typed {@link RxNormUnknown}.
|
|
@@ -3445,15 +3569,51 @@ declare function asTermType(tty: string): TermType | undefined;
|
|
|
3445
3569
|
* - {@link approximateMatch} — the **opt-in, explicitly labeled** similarity path (never the default,
|
|
3446
3570
|
* never an exact code assertion).
|
|
3447
3571
|
*
|
|
3448
|
-
*
|
|
3449
|
-
*
|
|
3450
|
-
*
|
|
3451
|
-
*
|
|
3572
|
+
* **What is bundled.** No code-system release is. What is bundled includes the following, named with
|
|
3573
|
+
* its copyright:
|
|
3574
|
+
*
|
|
3575
|
+
* - the **UCUM unit table** (`ucum-essence.xml`, version 2.2, revision-date 2024-06-17) — copyright
|
|
3576
|
+
* ©1999–2024 Regenstrief Institute, Inc., all rights reserved, reproduced **verbatim** under the
|
|
3577
|
+
* UCUM Copyright Notice and License (https://ucum.org/license), embedded byte-for-byte in the
|
|
3578
|
+
* published build and parsed at runtime; no modified or derivative copy is distributed. The UCUM
|
|
3579
|
+
* Specification is provided "as is" **without warranty of any kind** — see the License for the
|
|
3580
|
+
* full disclaimer. The complete notice ships with this package at `vendor/ucum/NOTICE.md`.
|
|
3581
|
+
* - the **code-system identity facts** ({@link SYSTEM_IDENTITIES}) — OID ↔ canonical-URI pairings,
|
|
3582
|
+
* which identify the systems rather than listing any system's codes.
|
|
3583
|
+
* - the **SNOMED CT concepts the crosswalk resolver names**, each with its description: the four
|
|
3584
|
+
* map-category concepts ({@link MAP_CATEGORIES}) a complex-map row's `mapCategoryId` refers to, and
|
|
3585
|
+
* the two gender findings (`248152002` Female, `248153007` Male) a gender `IFA` rule is written
|
|
3586
|
+
* against. Further SNOMED CT identifiers, and ICD-10-CM codes, appear in the API documentation
|
|
3587
|
+
* examples, which are distributed in the compiled declaration files and in the build's
|
|
3588
|
+
* sourcemaps. SNOMED CT is copyright © International Health Terminology Standards
|
|
3589
|
+
* Development Organisation.
|
|
3590
|
+
* - the **RxNorm relationship and term-type names** the drug-graph API is written against: the
|
|
3591
|
+
* relationship names in {@link RELA} / {@link RELA_INVERSE} (`has_ingredient`, `tradename_of`, …),
|
|
3592
|
+
* and the term-type codes in {@link TERM_TYPES}, each with its name as published by the U.S.
|
|
3593
|
+
* National Library of Medicine (`SCD` reads "Semantic Clinical Drug"). Individual RxNorm
|
|
3594
|
+
* identifiers also appear in the API documentation examples, with their RxNorm names and term
|
|
3595
|
+
* types (for instance `RXCUI` `316151`, "lisinopril 10 MG"), and in `README.md` as well as the
|
|
3596
|
+
* places named above. RxNorm is produced by the National Library of Medicine; no RxNorm release
|
|
3597
|
+
* is bundled.
|
|
3598
|
+
*
|
|
3599
|
+
* The `LICENSE` file that ships with this package carries the MIT text for the package's own code
|
|
3600
|
+
* and a third-party notices section naming each of the above.
|
|
3601
|
+
*
|
|
3602
|
+
* The content packs that would change this (the CMS GEM files, the RxNorm Current Prescribable
|
|
3603
|
+
* subset) are not bundled; a caller supplies them, as they do a SNOMED CT, CPT, LOINC, UMLS or VSAC
|
|
3604
|
+
* release, under whatever terms its steward sets. This states what is distributed and under whose
|
|
3605
|
+
* copyright; it is not legal advice, and makes no claim about whether a particular use is permitted
|
|
3606
|
+
* to you.
|
|
3452
3607
|
*
|
|
3453
3608
|
* @packageDocumentation
|
|
3454
3609
|
*/
|
|
3455
3610
|
/**
|
|
3456
|
-
* Library version string,
|
|
3611
|
+
* Library version string, kept in lockstep with `package.json#version`.
|
|
3612
|
+
*
|
|
3613
|
+
* Changesets owns the bump and rewrites `package.json` only, so the release `version` script runs
|
|
3614
|
+
* `scripts/sync-version.mjs` to rewrite this declaration in the same commit, and
|
|
3615
|
+
* `test/sanity.test.ts` compares the two so a skipped sync goes red instead of shipping a version
|
|
3616
|
+
* string that lies. That is not hypothetical: `0.0.1` went to the registry exporting `"0.0.0"`.
|
|
3457
3617
|
*
|
|
3458
3618
|
* @example
|
|
3459
3619
|
* ```ts
|
|
@@ -3461,6 +3621,6 @@ declare function asTermType(tty: string): TermType | undefined;
|
|
|
3461
3621
|
* typeof VERSION; // => "string"
|
|
3462
3622
|
* ```
|
|
3463
3623
|
*/
|
|
3464
|
-
declare const VERSION
|
|
3624
|
+
declare const VERSION: string;
|
|
3465
3625
|
|
|
3466
|
-
export { type AnnotationNode, type ApproximateMatchOptions, type BillableFlag, COMPLEX_MAP_SOURCE_SYSTEM, type CodeSystem, type CodeSystemSource, type CodeableConcept, type Coding, type ComplexMap, type ComplexMapApplyResult, type ComplexMapContextRequired, type ComplexMapEntry, type ComplexMapGroupNoMap, type ComplexMapGroupResolved, type ComplexMapGroupResult, type ComplexMapInput, type ComplexMapLoadWarning, type ComplexMapMatched, type ComponentNode, type Concept, type ConceptActivity, type ConceptMap, type ConceptMapElement, type ConceptMapGroup, type ConceptMapTarget, type ConceptMapUnmapped, type ConceptRef, type ConceptSetComponent, type ConceptSetFilter, type ConceptStatus, type CrosswalkNoMap, type CrosswalkUnmapped, type CsvColumnMap, type CsvSource, DIAGNOSTIC_CODES, type DiagnosticCode, type ExpandResult, type ExpansionContains, type ExpansionContext, type ExpansionDiagnostic, FATAL_CODES, type FactorNode, type FatalCode, type FhirCodeSystemSource, type FieldSlice, type FilterMatch, type FilterOperator, type FixedWidthFieldMap, type FixedWidthPropertyField, type FixedWidthSource, type GemApplyResult, type GemChoiceList, type GemDirection, type GemEntry, type GemFlags, type GemLoadWarning, type GemMap, type GemMatched, type GemScenario, type GemSource, type GroupNode, HL7_V2_OID_ROOT, HL7_V2_URL_PREFIX, ICD10CM_ORDER_FILE_FIELDS, ICD10CM_SYSTEM, ICD9CM_SYSTEM, type LinearReduction, type LoadWarning, type LookupOutcome, type LookupResult, type LookupUnknown, MAP_CATEGORIES, type MapCategoryId, type MapProvenance, NO_MAP_CATEGORIES, type NdcResolution, type NdcResult, type NdcStatus, type NdcUnmapped, type ParseFailure, type ParseResult, type PatientContext, type Property, type R4Equivalence, RELA, RELA_INVERSE, RXNORM_SYSTEM, type Reduction, type RelaName, type Relationship, type ResolveSystemResult, type RrfColumnMap, type RrfPropertyColumn, type RrfSource, type RxNormApproximateMatch, type RxNormConcept, type RxNormEdge, type RxNormGraph, type RxNormGraphSource, type RxNormLoadWarning, type RxNormNavResult, type RxNormRelated, type RxNormUnknown, SNOMEDCT_SYSTEM, SYSTEM_IDENTITIES, type SimpleUnitNode, type SpecialReduction, type StatusMapper, type Subsumption, type SystemIdentity, TERM_TYPES, type TermType, TerminologyError, type TranslateMatch, type TranslateMatched, type TranslateResult, type TranslateUnmapped, type UcumAtom, type UcumEssence, type UcumPrefix, type UcumValidation, type UnitNode, type UnknownSystem, type UnmappedMode, VERSION, type ValidateCodeResult, type ValueSet, type ValueSetCompose, type ValueSetExpansion, type ValueSetMemberDecided, type ValueSetMemberUndetermined, type ValueSetMembership, applyComplexMap, applyGem, approximateMatch, asTermType, brandsFor, buildSubsumption, codeableConcept, coding, consistsOf, defaultStatusMapper, doseFormsOf, expand, genericFor, getArray, getBoolean, getConcept, getNumber, getString, ingredientsOf, invertGem, isA, isJsonObject, isUnknownSystem, loadCodeSystem, loadComplexMap, loadConceptMap, loadGems, loadRxNormGraph, loadUcumEssence, loadValueSet, lookup, makeStatus, matchesFilter, parseCsv, parseCsvSource, parseFhirCodeSystem, parseFixedWidth, parseRrf, parseRrfLine, parseUcum, reduce, relatedByRela, resolveNdc, resolveSystem, sliceField, translate, ucumEqual, unsupportedOps, validateCode, validateCodeInValueSet, validateUcum };
|
|
3626
|
+
export { type AnnotationNode, type ApproximateMatchOptions, type BillableFlag, COMPLEX_MAP_SOURCE_SYSTEM, type CodeSystem, type CodeSystemSource, type CodeableConcept, type Coding, type ComplexMap, type ComplexMapApplyResult, type ComplexMapContextRequired, type ComplexMapEntry, type ComplexMapGroupNoMap, type ComplexMapGroupResolved, type ComplexMapGroupResult, type ComplexMapInput, type ComplexMapLoadWarning, type ComplexMapMatched, type ComponentNode, type Concept, type ConceptActivity, type ConceptMap, type ConceptMapElement, type ConceptMapGroup, type ConceptMapTarget, type ConceptMapUnmapped, type ConceptRef, type ConceptSetComponent, type ConceptSetFilter, type ConceptStatus, type CrosswalkNoMap, type CrosswalkUnmapped, type CsvColumnMap, type CsvSource, DIAGNOSTIC_CODES, type DiagnosticCode, type ExpandResult, type ExpansionContains, type ExpansionContext, type ExpansionDiagnostic, FATAL_CODES, type FactorNode, type FatalCode, type FhirCodeSystemSource, type FieldSlice, type FilterMatch, type FilterOperator, type FixedWidthFieldMap, type FixedWidthPropertyField, type FixedWidthSource, type GemApplyResult, type GemChoiceList, type GemDirection, type GemEntry, type GemFlags, type GemLoadWarning, type GemMap, type GemMatched, type GemScenario, type GemSource, type GroupNode, HL7_V2_OID_ROOT, HL7_V2_URL_PREFIX, ICD10CM_ORDER_FILE_FIELDS, ICD10CM_SYSTEM, ICD9CM_SYSTEM, type LinearReduction, type LoadWarning, type LookupOutcome, type LookupResult, type LookupUnknown, MAP_CATEGORIES, type MapCategoryId, type MapProvenance, NO_MAP_CATEGORIES, type NdcResolution, type NdcResult, type NdcStatus, type NdcUnmapped, type ParseFailure, type ParseResult, type PatientContext, type Property, type R4Equivalence, RELA, RELA_INVERSE, RXNORM_SYSTEM, type Reduction, type RelaName, type Relationship, type ResolveSystemResult, type RrfColumnMap, type RrfPropertyColumn, type RrfSource, type RxNormApproximateMatch, type RxNormConcept, type RxNormEdge, type RxNormGraph, type RxNormGraphSource, type RxNormLoadWarning, type RxNormNavResult, type RxNormRelated, type RxNormUnknown, SNOMEDCT_SYSTEM, SYSTEM_IDENTITIES, type SimpleUnitNode, type SpecialReduction, type StatusMapper, type Subsumption, type SystemIdentity, TERM_TYPES, type TermType, TerminologyError, type TranslateMatch, type TranslateMatched, type TranslateResult, type TranslateUnmapped, type UcumAtom, type UcumEssence, type UcumPrefix, type UcumValidation, type UnitNode, type UnknownSystem, type UnmappedMode, VERSION, type ValidateCodeResult, type ValueSet, type ValueSetCompose, type ValueSetExpansion, type ValueSetMemberDecided, type ValueSetMemberUndetermined, type ValueSetMembership, applyComplexMap, applyGem, approximateMatch, asTermType, brandsFor, buildSubsumption, codeableConcept, coding, consistsOf, defaultStatusMapper, doseFormsOf, expand, genericFor, getArray, getBoolean, getConcept, getNumber, getString, ingredientsOf, invertGem, isA, isJsonObject, isSynonymTermType, isUnknownSystem, loadCodeSystem, loadComplexMap, loadConceptMap, loadGems, loadRxNormGraph, loadUcumEssence, loadValueSet, lookup, makeStatus, matchesFilter, parseCsv, parseCsvSource, parseFhirCodeSystem, parseFixedWidth, parseRrf, parseRrfLine, parseUcum, reduce, relatedByRela, resolveNdc, resolveSystem, sliceField, translate, ucumEqual, unsupportedOps, validateCode, validateCodeInValueSet, validateUcum };
|