fhir-terminology-runtime 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/index.cjs +160 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.mjs +160 -145
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -398,7 +398,7 @@ Consider a large ValueSet `VS` and a code lookup `inValueSet('C10', VS)`:
|
|
|
398
398
|
#### Priming is not ValueSet expansion caching
|
|
399
399
|
|
|
400
400
|
FTR has two separate caching concepts:
|
|
401
|
-
- **Expansion caching**: stores the expanded ValueSet JSON on disk under `.ftr/` alongside
|
|
401
|
+
- **Expansion caching**: stores the expanded ValueSet JSON on disk under `.ftr.expansions/` alongside package contents.
|
|
402
402
|
- **Membership caching**: accelerates `inValueSet` lookups (in-memory LRUs + optional external cache).
|
|
403
403
|
|
|
404
404
|
“Priming” only refers to the **external membership cache** behavior.
|
|
@@ -422,7 +422,7 @@ When expanding ValueSets the runtime resolves referenced CodeSystems by canonica
|
|
|
422
422
|
|
|
423
423
|
### Expansion Caching
|
|
424
424
|
|
|
425
|
-
Expanded (or fallback) ValueSets are cached in a dedicated `.ftr
|
|
425
|
+
Expanded (or fallback) ValueSets are cached in a dedicated `.ftr.expansions/` directory inside package folders in the FHIR package cache folder. Repeated calls reuse the cached expansion unless `cacheMode` is `none`.
|
|
426
426
|
|
|
427
427
|
## Context
|
|
428
428
|
You must provide an array of FHIR packages in `context`. Any package or its dependencies missing in the local FHIR package cache will be downloaded and installed (by [`fhir-package-installer`](https://github.com/Outburn-IL/fhir-package-installer)).
|
|
@@ -447,7 +447,7 @@ Supports `<id>#<version>`, `<id>@<version>`, `<id>` (latest version) or a packag
|
|
|
447
447
|
Cached artifacts are stored under:
|
|
448
448
|
|
|
449
449
|
```
|
|
450
|
-
<cachePath>/<packageId>#<packageVersion>/.ftr/<FTR version>/
|
|
450
|
+
<cachePath>/<packageId>#<packageVersion>/.ftr.expansions/<FTR version>/
|
|
451
451
|
```
|
|
452
452
|
- Filenames mirror originals in `<cachePath>/<packageId>#<packageVersion>/package`.
|
|
453
453
|
- FTR Version directory uses major.minor.x (e.g. `0.1.x`).
|
package/dist/index.cjs
CHANGED
|
@@ -958,36 +958,13 @@ var ImplicitCodeSystemRegistry = class {
|
|
|
958
958
|
}
|
|
959
959
|
};
|
|
960
960
|
|
|
961
|
-
// src/utils/logger.ts
|
|
962
|
-
var defaultLogger = {
|
|
963
|
-
info: (msg) => console.log(msg),
|
|
964
|
-
warn: (msg) => console.warn(msg),
|
|
965
|
-
error: (msg) => console.error(msg)
|
|
966
|
-
};
|
|
967
|
-
var defaultPrethrow = (msg) => {
|
|
968
|
-
if (msg instanceof Error) {
|
|
969
|
-
return msg;
|
|
970
|
-
}
|
|
971
|
-
const error = new Error(msg);
|
|
972
|
-
return error;
|
|
973
|
-
};
|
|
974
|
-
var customPrethrower = (logger) => {
|
|
975
|
-
return (msg) => {
|
|
976
|
-
if (msg instanceof Error) {
|
|
977
|
-
logger.error(msg);
|
|
978
|
-
return msg;
|
|
979
|
-
}
|
|
980
|
-
const error = new Error(msg);
|
|
981
|
-
logger.error(error);
|
|
982
|
-
return error;
|
|
983
|
-
};
|
|
984
|
-
};
|
|
985
|
-
|
|
986
961
|
// package.json
|
|
987
|
-
var version = "
|
|
962
|
+
var version = "1.0.0";
|
|
988
963
|
|
|
989
964
|
// src/index.ts
|
|
990
965
|
var versionedCacheDir = `v${version.split(".").slice(0, 2).join(".")}.x`;
|
|
966
|
+
var FTR_VERSION_EXTENSION_URL = "http://fhir.fume.health/StructureDefinition/ftr-version";
|
|
967
|
+
var FTR_EXPANSION_FAILED_EXTENSION_URL = "http://fhir.fume.health/StructureDefinition/ftr-expansion-failed";
|
|
991
968
|
var FTR_DEFAULT_LIMITS = {
|
|
992
969
|
valueSet: {
|
|
993
970
|
smallThresholdUniqueCodes: 50,
|
|
@@ -1033,13 +1010,16 @@ var FhirTerminologyRuntime = class _FhirTerminologyRuntime {
|
|
|
1033
1010
|
// Cache for resolving server ConceptMap identifiers (url/id/name) -> deterministic server key.
|
|
1034
1011
|
// Keyed by baseUrl + identifier.
|
|
1035
1012
|
this.serverConceptMapIdentifierKeyCache = /* @__PURE__ */ new Map();
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1013
|
+
this.logger = logger || {
|
|
1014
|
+
debug: () => {
|
|
1015
|
+
},
|
|
1016
|
+
info: () => {
|
|
1017
|
+
},
|
|
1018
|
+
warn: () => {
|
|
1019
|
+
},
|
|
1020
|
+
error: () => {
|
|
1021
|
+
}
|
|
1022
|
+
};
|
|
1043
1023
|
this.cacheMode = cacheMode;
|
|
1044
1024
|
this.fhirVersion = fhirVersion;
|
|
1045
1025
|
this.fpe = fpe;
|
|
@@ -1058,55 +1038,49 @@ var FhirTerminologyRuntime = class _FhirTerminologyRuntime {
|
|
|
1058
1038
|
* @returns - A promise that resolves to a new instance of the FhirTerminologyRuntime class
|
|
1059
1039
|
*/
|
|
1060
1040
|
static async create(config) {
|
|
1061
|
-
const
|
|
1062
|
-
const
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
for (const expansionCacheDir of packageList) {
|
|
1081
|
-
if (await fs__default.default.exists(expansionCacheDir)) {
|
|
1082
|
-
fs__default.default.removeSync(expansionCacheDir);
|
|
1083
|
-
}
|
|
1041
|
+
const cacheMode = config.cacheMode || "lazy";
|
|
1042
|
+
const fhirVersion = config.fhirVersion || "4.0.1";
|
|
1043
|
+
const fpe = config.fpe;
|
|
1044
|
+
const ftr = new _FhirTerminologyRuntime(
|
|
1045
|
+
fpe,
|
|
1046
|
+
cacheMode,
|
|
1047
|
+
fhirVersion,
|
|
1048
|
+
config.logger,
|
|
1049
|
+
config.membershipCache,
|
|
1050
|
+
config.conceptMapCache,
|
|
1051
|
+
config.fhirClient
|
|
1052
|
+
);
|
|
1053
|
+
let precache = false;
|
|
1054
|
+
if (cacheMode === "rebuild") {
|
|
1055
|
+
precache = true;
|
|
1056
|
+
const packageList = fpe.getContextPackages().map((pkg) => path__default.default.join(fpe.getCachePath(), `${pkg.id}#${pkg.version}`, ".ftr.expansions", versionedCacheDir));
|
|
1057
|
+
for (const expansionCacheDir of packageList) {
|
|
1058
|
+
if (await fs__default.default.exists(expansionCacheDir)) {
|
|
1059
|
+
fs__default.default.removeSync(expansionCacheDir);
|
|
1084
1060
|
}
|
|
1085
1061
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
}
|
|
1062
|
+
}
|
|
1063
|
+
if (cacheMode === "ensure") precache = true;
|
|
1064
|
+
if (precache) {
|
|
1065
|
+
ftr.getLogger().info(`Pre-caching ValueSet expansions in '${cacheMode}' mode...`);
|
|
1066
|
+
const vsErrors = [];
|
|
1067
|
+
const allVs = await fpe.lookupMeta({ resourceType: "ValueSet" });
|
|
1068
|
+
for (const vs of allVs) {
|
|
1069
|
+
const { filename, __packageId: packageId, __packageVersion: packageVersion, url } = vs;
|
|
1070
|
+
try {
|
|
1071
|
+
await ftr.ensureExpansionCached(filename, packageId, packageVersion);
|
|
1072
|
+
} catch (e) {
|
|
1073
|
+
vsErrors.push(`Failed to ${cacheMode} expansion for '${url || filename}' in package '${packageId}@${packageVersion}': ${e instanceof Error ? e.message : String(e)}`);
|
|
1098
1074
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1075
|
+
}
|
|
1076
|
+
if (vsErrors.length > 0) {
|
|
1077
|
+
ftr.getLogger().warn(`Errors during pre-caching ValueSet expansions (${vsErrors.length} total):
|
|
1101
1078
|
${vsErrors.join("\n")}`);
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
}
|
|
1079
|
+
} else {
|
|
1080
|
+
ftr.getLogger().info(`Pre-caching ValueSet expansions in '${cacheMode}' mode completed successfully.`);
|
|
1105
1081
|
}
|
|
1106
|
-
return ftr;
|
|
1107
|
-
} catch (e) {
|
|
1108
|
-
throw prethrow(e);
|
|
1109
1082
|
}
|
|
1083
|
+
return ftr;
|
|
1110
1084
|
}
|
|
1111
1085
|
getLogger() {
|
|
1112
1086
|
return this.logger;
|
|
@@ -1130,6 +1104,33 @@ ${vsErrors.join("\n")}`);
|
|
|
1130
1104
|
async getValueSetByFileName(filename, packageId, packageVersion) {
|
|
1131
1105
|
return await this.fpe.resolve({ filename, package: { id: packageId, version: packageVersion } });
|
|
1132
1106
|
}
|
|
1107
|
+
withFtrVersionExtensionInExpansion(resource) {
|
|
1108
|
+
const expansion = resource?.expansion;
|
|
1109
|
+
if (!expansion || typeof expansion !== "object") return resource;
|
|
1110
|
+
const existing = Array.isArray(expansion.extension) ? expansion.extension : [];
|
|
1111
|
+
const alreadyPresent = existing.some((e) => e?.url === FTR_VERSION_EXTENSION_URL);
|
|
1112
|
+
if (alreadyPresent) return resource;
|
|
1113
|
+
const nextExpansion = {
|
|
1114
|
+
...expansion,
|
|
1115
|
+
extension: existing.concat([{ url: FTR_VERSION_EXTENSION_URL, valueCode: version }])
|
|
1116
|
+
};
|
|
1117
|
+
return { ...resource, expansion: nextExpansion };
|
|
1118
|
+
}
|
|
1119
|
+
getExtensionValue(expansion, url) {
|
|
1120
|
+
const ext = Array.isArray(expansion?.extension) ? expansion.extension : [];
|
|
1121
|
+
return ext.find((e) => e?.url === url);
|
|
1122
|
+
}
|
|
1123
|
+
getFtrVersionFromExpansion(resource) {
|
|
1124
|
+
const exp = resource?.expansion;
|
|
1125
|
+
const ext = this.getExtensionValue(exp, FTR_VERSION_EXTENSION_URL);
|
|
1126
|
+
return typeof ext?.valueCode === "string" && ext.valueCode.length > 0 ? ext.valueCode : void 0;
|
|
1127
|
+
}
|
|
1128
|
+
isExpansionMarkedFailed(resource) {
|
|
1129
|
+
if (resource?.expansion?.__failure === true) return true;
|
|
1130
|
+
const exp = resource?.expansion;
|
|
1131
|
+
const ext = this.getExtensionValue(exp, FTR_EXPANSION_FAILED_EXTENSION_URL);
|
|
1132
|
+
return ext?.valueBoolean === true;
|
|
1133
|
+
}
|
|
1133
1134
|
stableStringify(value) {
|
|
1134
1135
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
1135
1136
|
const normalize = (v) => {
|
|
@@ -1497,10 +1498,14 @@ ${vsErrors.join("\n")}`);
|
|
|
1497
1498
|
const { filename, __packageId: packageId, __packageVersion: packageVersion } = metadata;
|
|
1498
1499
|
const cached = this.cacheMode !== "none" ? await this.getExpansionFromCache(filename, packageId, packageVersion) : void 0;
|
|
1499
1500
|
if (cached) {
|
|
1500
|
-
if (cached
|
|
1501
|
-
|
|
1501
|
+
if (this.isExpansionMarkedFailed(cached)) {
|
|
1502
|
+
const cachedVersion = this.getFtrVersionFromExpansion(cached);
|
|
1503
|
+
if (cachedVersion === version) {
|
|
1504
|
+
throw new Error(`Previous expansion attempt failed for ValueSet '${cached.url || cached.id || filename}' (cached).`);
|
|
1505
|
+
}
|
|
1506
|
+
} else {
|
|
1507
|
+
return this.withFtrVersionExtensionInExpansion(cached);
|
|
1502
1508
|
}
|
|
1503
|
-
return cached;
|
|
1504
1509
|
}
|
|
1505
1510
|
const vs = await this.getValueSetByFileName(filename, packageId, packageVersion);
|
|
1506
1511
|
if (!vs || vs.resourceType !== "ValueSet") throw new Error(`File '${filename}' not found as a ValueSet in package '${packageId}@${packageVersion}'.`);
|
|
@@ -1520,7 +1525,15 @@ ${vsErrors.join("\n")}`);
|
|
|
1520
1525
|
}
|
|
1521
1526
|
this.subtractSystemMaps(includeMap, excludeMap);
|
|
1522
1527
|
const { contains, total } = this.buildExpansionFromSystemMap(includeMap);
|
|
1523
|
-
const expanded = {
|
|
1528
|
+
const expanded = {
|
|
1529
|
+
...vs,
|
|
1530
|
+
expansion: {
|
|
1531
|
+
extension: [{ url: FTR_VERSION_EXTENSION_URL, valueCode: version }],
|
|
1532
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1533
|
+
total,
|
|
1534
|
+
contains
|
|
1535
|
+
}
|
|
1536
|
+
};
|
|
1524
1537
|
if (this.cacheMode !== "none") {
|
|
1525
1538
|
await this.saveExpansionToCache(filename, packageId, packageVersion, expanded);
|
|
1526
1539
|
}
|
|
@@ -1528,13 +1541,23 @@ ${vsErrors.join("\n")}`);
|
|
|
1528
1541
|
} catch (e) {
|
|
1529
1542
|
this.logger.warn(`Failed to expand ValueSet '${vs?.url || vs?.id || filename}': ${e instanceof Error ? e.message : String(e)}. Falling back to original expansion if present.`);
|
|
1530
1543
|
if (vs?.expansion?.contains && Array.isArray(vs.expansion.contains)) {
|
|
1544
|
+
const normalized = this.withFtrVersionExtensionInExpansion(vs);
|
|
1531
1545
|
if (this.cacheMode !== "none") {
|
|
1532
|
-
await this.saveExpansionToCache(filename, packageId, packageVersion,
|
|
1546
|
+
await this.saveExpansionToCache(filename, packageId, packageVersion, normalized);
|
|
1533
1547
|
}
|
|
1534
|
-
return
|
|
1548
|
+
return normalized;
|
|
1535
1549
|
}
|
|
1536
1550
|
if (this.cacheMode !== "none") {
|
|
1537
|
-
const failureStub = {
|
|
1551
|
+
const failureStub = {
|
|
1552
|
+
...vs,
|
|
1553
|
+
expansion: {
|
|
1554
|
+
extension: [
|
|
1555
|
+
{ url: FTR_VERSION_EXTENSION_URL, valueCode: version },
|
|
1556
|
+
{ url: FTR_EXPANSION_FAILED_EXTENSION_URL, valueBoolean: true }
|
|
1557
|
+
],
|
|
1558
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1559
|
+
}
|
|
1560
|
+
};
|
|
1538
1561
|
try {
|
|
1539
1562
|
await this.saveExpansionToCache(filename, packageId, packageVersion, failureStub);
|
|
1540
1563
|
} catch {
|
|
@@ -1561,25 +1584,21 @@ ${vsErrors.join("\n")}`);
|
|
|
1561
1584
|
* Get ValueSet expansion by any FSH style identifier (id, url or name), or by a metadata object.
|
|
1562
1585
|
*/
|
|
1563
1586
|
async expandValueSet(identifier, packageFilter) {
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
throw new Error(`ValueSet with metadata:
|
|
1587
|
+
let metadata;
|
|
1588
|
+
if (typeof identifier === "string") {
|
|
1589
|
+
metadata = await this.getValueSetMetadata(identifier, packageFilter);
|
|
1590
|
+
if (!metadata) {
|
|
1591
|
+
throw new Error(`ValueSet '${identifier}' not found in context. Could not get or generate an expansion.`);
|
|
1592
|
+
}
|
|
1593
|
+
} else {
|
|
1594
|
+
metadata = identifier;
|
|
1595
|
+
if (!metadata) {
|
|
1596
|
+
throw new Error(`ValueSet with metadata:
|
|
1575
1597
|
${JSON.stringify(identifier, null, 2)}
|
|
1576
1598
|
not found in context. Could not get or generate an expansion.`);
|
|
1577
|
-
}
|
|
1578
1599
|
}
|
|
1579
|
-
return await this.expandValueSetByMeta(metadata);
|
|
1580
|
-
} catch (e) {
|
|
1581
|
-
throw this.prethrow(e);
|
|
1582
1600
|
}
|
|
1601
|
+
return await this.expandValueSetByMeta(metadata);
|
|
1583
1602
|
}
|
|
1584
1603
|
/**
|
|
1585
1604
|
* Get the count of concepts in the expansion of a ValueSet.
|
|
@@ -1633,55 +1652,51 @@ not found in context. Could not get or generate an expansion.`);
|
|
|
1633
1652
|
* @returns The full CodeSystem resource (content=complete).
|
|
1634
1653
|
*/
|
|
1635
1654
|
async resolveCompleteCodeSystem(url, sourcePackage) {
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
throw new Error(`Implicit CodeSystem '${url}' provider returned no concepts.`);
|
|
1644
|
-
}
|
|
1645
|
-
return {
|
|
1646
|
-
resourceType: "CodeSystem",
|
|
1647
|
-
url,
|
|
1648
|
-
status: "active",
|
|
1649
|
-
content: "complete",
|
|
1650
|
-
concept: Array.from(concepts.entries()).map(([code, display]) => ({
|
|
1651
|
-
code,
|
|
1652
|
-
display
|
|
1653
|
-
}))
|
|
1654
|
-
};
|
|
1655
|
+
if (!url) {
|
|
1656
|
+
throw new Error("CodeSystem canonical URL missing.");
|
|
1657
|
+
}
|
|
1658
|
+
if (ImplicitCodeSystemRegistry.isImplicitCodeSystem(url)) {
|
|
1659
|
+
const concepts = ImplicitCodeSystemRegistry.getConcepts(url);
|
|
1660
|
+
if (!concepts) {
|
|
1661
|
+
throw new Error(`Implicit CodeSystem '${url}' provider returned no concepts.`);
|
|
1655
1662
|
}
|
|
1656
|
-
|
|
1663
|
+
return {
|
|
1664
|
+
resourceType: "CodeSystem",
|
|
1665
|
+
url,
|
|
1666
|
+
status: "active",
|
|
1667
|
+
content: "complete",
|
|
1668
|
+
concept: Array.from(concepts.entries()).map(([code, display]) => ({
|
|
1669
|
+
code,
|
|
1670
|
+
display
|
|
1671
|
+
}))
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
let meta;
|
|
1675
|
+
try {
|
|
1676
|
+
meta = await this.resolveMetaCached({ resourceType: "CodeSystem", url, package: sourcePackage });
|
|
1677
|
+
} catch {
|
|
1678
|
+
}
|
|
1679
|
+
if (!meta) {
|
|
1657
1680
|
try {
|
|
1658
|
-
meta = await this.resolveMetaCached({ resourceType: "CodeSystem", url
|
|
1681
|
+
meta = await this.resolveMetaCached({ resourceType: "CodeSystem", url });
|
|
1659
1682
|
} catch {
|
|
1683
|
+
throw new Error(`CodeSystem '${url}' not found (searched in package '${sourcePackage.id}@${sourcePackage.version}' then globally).`);
|
|
1660
1684
|
}
|
|
1661
|
-
if (!meta) {
|
|
1662
|
-
try {
|
|
1663
|
-
meta = await this.resolveMetaCached({ resourceType: "CodeSystem", url });
|
|
1664
|
-
} catch {
|
|
1665
|
-
throw new Error(`CodeSystem '${url}' not found (searched in package '${sourcePackage.id}@${sourcePackage.version}' then globally).`);
|
|
1666
|
-
}
|
|
1667
|
-
}
|
|
1668
|
-
if (!meta?.content || typeof meta?.content === "string" && meta.content !== "complete") {
|
|
1669
|
-
throw new Error(`CodeSystem '${url}' has content='${meta.content}' and cannot be expanded (only 'complete' supported).`);
|
|
1670
|
-
}
|
|
1671
|
-
const cs = await this.fpe.resolve({ filename: meta.filename, package: { id: meta.__packageId, version: meta.__packageVersion } });
|
|
1672
|
-
if (!cs) {
|
|
1673
|
-
throw new Error(`Failed to load CodeSystem '${url}' from package '${meta.__packageId}@${meta.__packageVersion}'.`);
|
|
1674
|
-
}
|
|
1675
|
-
if (cs.resourceType !== "CodeSystem") {
|
|
1676
|
-
throw new Error(`Resolved resource for '${url}' is not a CodeSystem (got '${cs.resourceType || "unknown"}').`);
|
|
1677
|
-
}
|
|
1678
|
-
if (cs.content !== "complete") {
|
|
1679
|
-
throw new Error(`CodeSystem '${url}' has content='${cs.content || "undefined"}' and cannot be expanded (only 'complete' supported).`);
|
|
1680
|
-
}
|
|
1681
|
-
return cs;
|
|
1682
|
-
} catch (e) {
|
|
1683
|
-
throw this.prethrow(e);
|
|
1684
1685
|
}
|
|
1686
|
+
if (!meta?.content || typeof meta?.content === "string" && meta.content !== "complete") {
|
|
1687
|
+
throw new Error(`CodeSystem '${url}' has content='${meta.content}' and cannot be expanded (only 'complete' supported).`);
|
|
1688
|
+
}
|
|
1689
|
+
const cs = await this.fpe.resolve({ filename: meta.filename, package: { id: meta.__packageId, version: meta.__packageVersion } });
|
|
1690
|
+
if (!cs) {
|
|
1691
|
+
throw new Error(`Failed to load CodeSystem '${url}' from package '${meta.__packageId}@${meta.__packageVersion}'.`);
|
|
1692
|
+
}
|
|
1693
|
+
if (cs.resourceType !== "CodeSystem") {
|
|
1694
|
+
throw new Error(`Resolved resource for '${url}' is not a CodeSystem (got '${cs.resourceType || "unknown"}').`);
|
|
1695
|
+
}
|
|
1696
|
+
if (cs.content !== "complete") {
|
|
1697
|
+
throw new Error(`CodeSystem '${url}' has content='${cs.content || "undefined"}' and cannot be expanded (only 'complete' supported).`);
|
|
1698
|
+
}
|
|
1699
|
+
return cs;
|
|
1685
1700
|
}
|
|
1686
1701
|
/**
|
|
1687
1702
|
* Check whether a code (string) or Coding-like object is a member of a ValueSet.
|
|
@@ -1883,7 +1898,7 @@ not found in context. Could not get or generate an expansion.`);
|
|
|
1883
1898
|
if (!cmKey) {
|
|
1884
1899
|
const err = new Error(`ConceptMap '${typeof conceptMap === "string" ? conceptMap : conceptMap?.filename || "unknown"}' could not be resolved.`);
|
|
1885
1900
|
err.errors = errors;
|
|
1886
|
-
throw
|
|
1901
|
+
throw err;
|
|
1887
1902
|
}
|
|
1888
1903
|
const cmKeyStr = this.toConceptMapKeyString(cmKey);
|
|
1889
1904
|
const smallIndex = this.smallConceptMapIndexLru.get(cmKeyStr);
|
|
@@ -1917,12 +1932,12 @@ not found in context. Could not get or generate an expansion.`);
|
|
|
1917
1932
|
} catch (e) {
|
|
1918
1933
|
const err = new Error(`Failed to load ConceptMap for key '${cmKeyStr}'.`);
|
|
1919
1934
|
err.errors = errors.concat([e]);
|
|
1920
|
-
throw
|
|
1935
|
+
throw err;
|
|
1921
1936
|
}
|
|
1922
1937
|
if (!cm || cm.resourceType !== "ConceptMap") {
|
|
1923
1938
|
const err = new Error(`Resolved ConceptMap '${cmKeyStr}' is not a ConceptMap.`);
|
|
1924
1939
|
err.errors = errors;
|
|
1925
|
-
throw
|
|
1940
|
+
throw err;
|
|
1926
1941
|
}
|
|
1927
1942
|
const flatIndex = buildIndexFromConceptMap(cm);
|
|
1928
1943
|
if (flatIndex.uniqueSourceCodeCount <= FTR_DEFAULT_LIMITS.conceptMap.smallThresholdUniqueSourceCodes) {
|