@cosyte/terminology 0.1.5 → 0.1.6
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 +10 -0
- package/README.md +3 -0
- package/dist/index.cjs +58 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -36
- package/dist/index.d.ts +54 -36
- package/dist/index.mjs +58 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -210,7 +210,7 @@ var FATAL_CODES = {
|
|
|
210
210
|
/**
|
|
211
211
|
* An **inversion** of a directional crosswalk was requested: a forbidden operation. The GEMs and
|
|
212
212
|
* the SNOMED→ICD-10-CM map are authoritative in **one direction only**; a forward map is not the
|
|
213
|
-
* inverse of the backward map. Thrown by {@link
|
|
213
|
+
* inverse of the backward map. Thrown by {@link invertGem} so the
|
|
214
214
|
* never-invert refusal is a first-class, discoverable contract rather than a silent absence.
|
|
215
215
|
*/
|
|
216
216
|
TERM_MAP_NOT_INVERTIBLE: "TERM_MAP_NOT_INVERTIBLE"
|
|
@@ -762,10 +762,10 @@ function parseCsvSource(source) {
|
|
|
762
762
|
const codeIdx = requireHeader(header, source.columns.code, "code");
|
|
763
763
|
const displayIdx = requireHeader(header, source.columns.display, "display");
|
|
764
764
|
const statusIdx = source.columns.status !== void 0 ? requireHeader(header, source.columns.status, "status") : void 0;
|
|
765
|
-
const propIdx =
|
|
766
|
-
|
|
767
|
-
index: requireHeader(header, n, "property")
|
|
768
|
-
}
|
|
765
|
+
const propIdx = [];
|
|
766
|
+
for (const n of source.columns.properties ?? []) {
|
|
767
|
+
propIdx.push({ name: n, index: requireHeader(header, n, "property") });
|
|
768
|
+
}
|
|
769
769
|
const needCols = Math.max(codeIdx, displayIdx, statusIdx ?? 0, ...propIdx.map((p) => p.index)) + 1;
|
|
770
770
|
const concepts = /* @__PURE__ */ new Map();
|
|
771
771
|
for (let r = 1; r < rows.length; r++) {
|
|
@@ -854,9 +854,10 @@ function collectConcepts(rawConcepts, into, warnings, parentCode) {
|
|
|
854
854
|
if (code !== void 0 && code !== "" && !into.has(code)) {
|
|
855
855
|
const props = [];
|
|
856
856
|
for (const p of getArray(raw, "property") ?? []) {
|
|
857
|
+
if (!isJsonObject(p)) continue;
|
|
857
858
|
const pcode = getString(p, "code");
|
|
858
859
|
if (pcode === void 0) continue;
|
|
859
|
-
const value =
|
|
860
|
+
const value = readPropertyValue(p);
|
|
860
861
|
if (value !== void 0) props.push(Object.freeze({ code: pcode, value }));
|
|
861
862
|
}
|
|
862
863
|
if (parentCode !== void 0 && !props.some((p) => p.code === "parent" && p.value === parentCode)) {
|
|
@@ -919,9 +920,21 @@ var ICD10CM_ORDER_FILE_FIELDS = Object.freeze({
|
|
|
919
920
|
Object.freeze({ name: "shortDescription", slice: Object.freeze({ start: 16, end: 76 }) })
|
|
920
921
|
])
|
|
921
922
|
});
|
|
923
|
+
function requirePropertyFields(fields) {
|
|
924
|
+
for (const p of fields.properties ?? []) {
|
|
925
|
+
const entry = p;
|
|
926
|
+
if (typeof entry !== "object" || entry === null) {
|
|
927
|
+
throw new TerminologyError(
|
|
928
|
+
FATAL_CODES.TERM_CODESYSTEM_MALFORMED,
|
|
929
|
+
"fixed-width source: a configured property field is not an object"
|
|
930
|
+
);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
922
934
|
function parseFixedWidth(source) {
|
|
923
935
|
const statusMap = source.statusMap ?? defaultStatusMapper;
|
|
924
936
|
const fields = source.fields;
|
|
937
|
+
requirePropertyFields(fields);
|
|
925
938
|
const concepts = /* @__PURE__ */ new Map();
|
|
926
939
|
const warnings = [];
|
|
927
940
|
const lines = source.content.split(/\r?\n/);
|
|
@@ -983,7 +996,16 @@ function parseRrfLine(line) {
|
|
|
983
996
|
function maxColumn(source) {
|
|
984
997
|
const { code, display, status, properties } = source.columns;
|
|
985
998
|
let max = Math.max(code, display, status ?? 0);
|
|
986
|
-
for (const p of properties ?? [])
|
|
999
|
+
for (const p of properties ?? []) {
|
|
1000
|
+
const entry = p;
|
|
1001
|
+
if (typeof entry !== "object" || entry === null) {
|
|
1002
|
+
throw new TerminologyError(
|
|
1003
|
+
FATAL_CODES.TERM_CODESYSTEM_MALFORMED,
|
|
1004
|
+
"RRF source: a configured property column is not an object"
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1007
|
+
max = Math.max(max, p.column);
|
|
1008
|
+
}
|
|
987
1009
|
return max;
|
|
988
1010
|
}
|
|
989
1011
|
function cell(cells, index) {
|
|
@@ -1390,8 +1412,7 @@ function makeCoding(system, code, display, version) {
|
|
|
1390
1412
|
return coding(init);
|
|
1391
1413
|
}
|
|
1392
1414
|
function cannotExpand(detail, path) {
|
|
1393
|
-
const d = { code: "TERM_VALUESET_CANNOT_EXPAND", detail };
|
|
1394
|
-
if (path !== void 0) d.path = path;
|
|
1415
|
+
const d = { code: "TERM_VALUESET_CANNOT_EXPAND", detail, path };
|
|
1395
1416
|
return Object.freeze(d);
|
|
1396
1417
|
}
|
|
1397
1418
|
function truncated(detail, path) {
|
|
@@ -1405,9 +1426,9 @@ function truncated(detail, path) {
|
|
|
1405
1426
|
function enumeratedUndefined(detail, path) {
|
|
1406
1427
|
const d = {
|
|
1407
1428
|
code: "TERM_VALUESET_ENUMERATED_CODE_UNDEFINED",
|
|
1408
|
-
detail
|
|
1429
|
+
detail,
|
|
1430
|
+
path
|
|
1409
1431
|
};
|
|
1410
|
-
if (path !== void 0) d.path = path;
|
|
1411
1432
|
return Object.freeze(d);
|
|
1412
1433
|
}
|
|
1413
1434
|
function expansionIncompleteDetail(unclosed) {
|
|
@@ -1441,7 +1462,8 @@ function screenActive(members, component, ctx) {
|
|
|
1441
1462
|
}
|
|
1442
1463
|
function underPath(d, prefix) {
|
|
1443
1464
|
const out = { code: d.code, detail: d.detail };
|
|
1444
|
-
|
|
1465
|
+
if (d.path === void 0) out.path = prefix;
|
|
1466
|
+
else out.path = `${prefix}/${d.path}`;
|
|
1445
1467
|
return Object.freeze(out);
|
|
1446
1468
|
}
|
|
1447
1469
|
function intersectInto(into, other) {
|
|
@@ -1637,8 +1659,7 @@ function expand(vs, ctx = {}) {
|
|
|
1637
1659
|
|
|
1638
1660
|
// src/valueset/validate.ts
|
|
1639
1661
|
function cannotExpand2(detail, path) {
|
|
1640
|
-
const d = { code: "TERM_VALUESET_CANNOT_EXPAND", detail };
|
|
1641
|
-
if (path !== void 0) d.path = path;
|
|
1662
|
+
const d = { code: "TERM_VALUESET_CANNOT_EXPAND", detail, path };
|
|
1642
1663
|
return Object.freeze(d);
|
|
1643
1664
|
}
|
|
1644
1665
|
function expansionIncompleteDetail2(unclosed) {
|
|
@@ -1656,7 +1677,8 @@ function usableRelease2(component, system, ctx) {
|
|
|
1656
1677
|
}
|
|
1657
1678
|
function underPath2(d, prefix) {
|
|
1658
1679
|
const out = { code: d.code, detail: d.detail };
|
|
1659
|
-
|
|
1680
|
+
if (d.path === void 0) out.path = prefix;
|
|
1681
|
+
else out.path = `${prefix}/${d.path}`;
|
|
1660
1682
|
return Object.freeze(out);
|
|
1661
1683
|
}
|
|
1662
1684
|
function matchComponent(target, component, ctx, visited, path, activeOnly = false) {
|
|
@@ -1716,10 +1738,13 @@ function matchComponent(target, component, ctx, visited, path, activeOnly = fals
|
|
|
1716
1738
|
}
|
|
1717
1739
|
}
|
|
1718
1740
|
if (system !== void 0 && target.system === void 0 && baseComplete) baseMatched = false;
|
|
1741
|
+
if (baseMatched === null && !hasVs) return { matched: false, complete: true, diagnostics };
|
|
1719
1742
|
let refDefiniteFalse = false;
|
|
1720
1743
|
let refUndetermined = false;
|
|
1721
1744
|
if (hasVs) {
|
|
1745
|
+
let refsRead = 0;
|
|
1722
1746
|
for (const [i, url] of valueSet2.entries()) {
|
|
1747
|
+
refsRead++;
|
|
1723
1748
|
const refPath = `${path}.valueSet[${String(i)}]`;
|
|
1724
1749
|
if (visited.has(url)) {
|
|
1725
1750
|
diagnostics.push(cannotExpand2("cyclic value set reference", refPath));
|
|
@@ -1740,6 +1765,7 @@ function matchComponent(target, component, ctx, visited, path, activeOnly = fals
|
|
|
1740
1765
|
refDefiniteFalse = true;
|
|
1741
1766
|
}
|
|
1742
1767
|
}
|
|
1768
|
+
if (refsRead === 0) refDefiniteFalse = true;
|
|
1743
1769
|
}
|
|
1744
1770
|
const baseDefiniteFalse = baseMatched === false && baseComplete;
|
|
1745
1771
|
const baseDefiniteTrue = baseMatched === null || baseMatched === true && baseComplete;
|
|
@@ -3991,6 +4017,9 @@ function atBoundary(s, pos) {
|
|
|
3991
4017
|
const c = s[pos];
|
|
3992
4018
|
return c === "." || c === "/" || c === ")";
|
|
3993
4019
|
}
|
|
4020
|
+
function prefixRank(m) {
|
|
4021
|
+
return m.prefix ? 1 : 0;
|
|
4022
|
+
}
|
|
3994
4023
|
function simpleMatches(essence, s, pos) {
|
|
3995
4024
|
const out = [];
|
|
3996
4025
|
for (const atom of essence.atoms) {
|
|
@@ -4005,7 +4034,7 @@ function simpleMatches(essence, s, pos) {
|
|
|
4005
4034
|
}
|
|
4006
4035
|
}
|
|
4007
4036
|
}
|
|
4008
|
-
out.sort((a, b) => b.len - a.len || (a
|
|
4037
|
+
out.sort((a, b) => b.len - a.len || prefixRank(a) - prefixRank(b));
|
|
4009
4038
|
return out;
|
|
4010
4039
|
}
|
|
4011
4040
|
var MAX_PAREN_DEPTH = 100;
|
|
@@ -4410,7 +4439,7 @@ var MAP_CATEGORIES = {
|
|
|
4410
4439
|
NO_MAP: "447638001",
|
|
4411
4440
|
/** `447639009`: "Map of source concept is context dependent" (needs runtime patient context). */
|
|
4412
4441
|
CONTEXT_DEPENDENT: "447639009",
|
|
4413
|
-
/** `447640006`: "Source concept is ambiguous" (
|
|
4442
|
+
/** `447640006`: "Source concept is ambiguous" (carried through on the result; the rule decides). */
|
|
4414
4443
|
AMBIGUOUS: "447640006"
|
|
4415
4444
|
};
|
|
4416
4445
|
var NO_MAP_CATEGORIES = /* @__PURE__ */ new Set([MAP_CATEGORIES.NO_MAP]);
|
|
@@ -4543,8 +4572,15 @@ function evaluateConjunct(clause, context) {
|
|
|
4543
4572
|
const bound = Number(ageMatch[2]);
|
|
4544
4573
|
if (context.ageYears === void 0 || !Number.isFinite(bound)) return "unknown";
|
|
4545
4574
|
const age = context.ageYears;
|
|
4546
|
-
|
|
4547
|
-
if (
|
|
4575
|
+
let ok;
|
|
4576
|
+
if (op === "<=") ok = age <= bound;
|
|
4577
|
+
else if (op === ">=") ok = age >= bound;
|
|
4578
|
+
else if (op === "<") ok = age < bound;
|
|
4579
|
+
else if (op === ">") ok = age > bound;
|
|
4580
|
+
else {
|
|
4581
|
+
if (op === "=") ok = age === bound;
|
|
4582
|
+
else return "unknown";
|
|
4583
|
+
}
|
|
4548
4584
|
return ok ? "match" : "no-match";
|
|
4549
4585
|
}
|
|
4550
4586
|
return "unknown";
|
|
@@ -4963,7 +4999,8 @@ function jaccard(a, b) {
|
|
|
4963
4999
|
let inter = 0;
|
|
4964
5000
|
for (const t of a) if (b.has(t)) inter++;
|
|
4965
5001
|
const union = a.size + b.size - inter;
|
|
4966
|
-
|
|
5002
|
+
if (union === 0) return 0;
|
|
5003
|
+
return inter / union;
|
|
4967
5004
|
}
|
|
4968
5005
|
function approximateMatch(graph, query, options = {}) {
|
|
4969
5006
|
const minScore = options.minScore ?? 0.34;
|
|
@@ -4980,7 +5017,7 @@ function approximateMatch(graph, query, options = {}) {
|
|
|
4980
5017
|
}
|
|
4981
5018
|
|
|
4982
5019
|
// src/index.ts
|
|
4983
|
-
var VERSION = "0.1.
|
|
5020
|
+
var VERSION = "0.1.6";
|
|
4984
5021
|
|
|
4985
5022
|
export { COMPLEX_MAP_SOURCE_SYSTEM, DIAGNOSTIC_CODES, FATAL_CODES, HL7_V2_OID_ROOT, HL7_V2_URL_PREFIX, ICD10CM_ORDER_FILE_FIELDS, ICD10CM_SYSTEM, ICD9CM_SYSTEM, MAP_CATEGORIES, NO_MAP_CATEGORIES, RELA, RELA_INVERSE, RXNORM_SYSTEM, SNOMEDCT_SYSTEM, SYSTEM_IDENTITIES, TERM_TYPES, TerminologyError, VERSION, 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 };
|
|
4986
5023
|
//# sourceMappingURL=index.mjs.map
|