fhirsmith 0.5.6 → 0.7.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/CHANGELOG.md +38 -0
- package/README.md +2 -0
- package/configurations/projector.json +21 -0
- package/configurations/readme.md +5 -0
- package/library/html-server.js +2 -1
- package/library/package-manager.js +37 -34
- package/library/utilities.js +10 -1
- package/library/version-utilities.js +85 -0
- package/package.json +1 -1
- package/packages/package-crawler.js +144 -52
- package/packages/packages.js +15 -7
- package/publisher/publisher.js +15 -3
- package/registry/api.js +173 -191
- package/registry/crawler.js +100 -65
- package/registry/model.js +14 -8
- package/registry/registry.js +5 -0
- package/root-template.html +1 -0
- package/server.js +113 -45
- package/tx/README.md +4 -4
- package/tx/cs/cs-api.js +18 -1
- package/tx/cs/cs-base.js +1 -0
- package/tx/cs/cs-loinc.js +5 -2
- package/tx/cs/cs-provider-api.js +25 -1
- package/tx/cs/cs-provider-list.js +2 -2
- package/tx/cs/cs-rxnorm.js +9 -2
- package/tx/cs/cs-snomed.js +17 -2
- package/tx/html/codesystem-operations.liquid +17 -24
- package/tx/html/valueset-operations.liquid +46 -52
- package/tx/library/canonical-resource.js +6 -1
- package/tx/library/codesystem.js +6 -1
- package/tx/library/renderer.js +81 -7
- package/tx/library.js +145 -13
- package/tx/ocl/README.md +236 -0
- package/tx/ocl/cache/cache-paths.cjs +32 -0
- package/tx/ocl/cache/cache-paths.js +2 -0
- package/tx/ocl/cache/cache-utils.cjs +43 -0
- package/tx/ocl/cache/cache-utils.js +2 -0
- package/tx/ocl/cm-ocl.cjs +531 -0
- package/tx/ocl/cm-ocl.js +1 -105
- package/tx/ocl/cs-ocl.cjs +1779 -0
- package/tx/ocl/cs-ocl.js +1 -38
- package/tx/ocl/fingerprint/fingerprint.cjs +67 -0
- package/tx/ocl/fingerprint/fingerprint.js +2 -0
- package/tx/ocl/http/client.cjs +31 -0
- package/tx/ocl/http/client.js +2 -0
- package/tx/ocl/http/pagination.cjs +98 -0
- package/tx/ocl/http/pagination.js +2 -0
- package/tx/ocl/jobs/background-queue.cjs +200 -0
- package/tx/ocl/jobs/background-queue.js +2 -0
- package/tx/ocl/mappers/concept-mapper.cjs +66 -0
- package/tx/ocl/mappers/concept-mapper.js +2 -0
- package/tx/ocl/model/concept-filter-context.cjs +51 -0
- package/tx/ocl/model/concept-filter-context.js +2 -0
- package/tx/ocl/shared/constants.cjs +15 -0
- package/tx/ocl/shared/constants.js +2 -0
- package/tx/ocl/shared/patches.cjs +224 -0
- package/tx/ocl/shared/patches.js +2 -0
- package/tx/ocl/vs-ocl.cjs +1848 -0
- package/tx/ocl/vs-ocl.js +1 -104
- package/tx/operation-context.js +8 -1
- package/tx/params.js +24 -3
- package/tx/provider.js +51 -2
- package/tx/sct/expressions.js +20 -9
- package/tx/tx-html.js +144 -51
- package/tx/tx.js +10 -2
- package/tx/vs/vs-vsac.js +4 -3
- package/tx/workers/batch-validate.js +3 -2
- package/tx/workers/batch.js +3 -2
- package/tx/workers/expand.js +125 -18
- package/tx/workers/lookup.js +5 -4
- package/tx/workers/read.js +2 -1
- package/tx/workers/related.js +3 -2
- package/tx/workers/search.js +6 -8
- package/tx/workers/subsumes.js +3 -2
- package/tx/workers/translate.js +4 -3
- package/tx/workers/validate.js +132 -40
- package/tx/workers/worker.js +1 -7
- package/tx/xversion/xv-terminologyCapabilities.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,44 @@ All notable changes to the Health Intersections Node Server will be documented i
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [v0.7.0] - 2026-03-13
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Add support for serving for OCL TX content (h/t Italo Macêdo from the OCL team)
|
|
12
|
+
- Add default configurations (wip)
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Make web-crawlers more robust after tx.fhir.org crash
|
|
16
|
+
- Don't accept NPM packages that have .js code or install scripts
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- Fix many bugs in expansion and validation for value sets that include two different versions of the same code system
|
|
20
|
+
- Fix CodeSystem search on system parameter to reduce user confusion
|
|
21
|
+
- Fix CodeSystem search such that default search is without any specified source
|
|
22
|
+
- Fix headers sent multiple times error
|
|
23
|
+
|
|
24
|
+
### Tx Conformance Statement
|
|
25
|
+
|
|
26
|
+
FHIRsmith passed all 1452 HL7 terminology service tests (modes tx.fhir.org+omop+general+snomed, tests v1.9.1-SNAPSHOT, runner v6.8.2)
|
|
27
|
+
|
|
28
|
+
## [v0.6.0] - 2026-03-06
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- Add support to packages server for scoped packages
|
|
32
|
+
- Add support for exclusions and content tracking in tx-registry
|
|
33
|
+
- Add support for serving a host
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
- fix error in SCT expression validation
|
|
37
|
+
- fix null error in search
|
|
38
|
+
- fix search for code systems with uppercase letters in their name
|
|
39
|
+
- rework html interface for CodeSystem and ValueSet
|
|
40
|
+
- further work on publisehr
|
|
41
|
+
|
|
42
|
+
### Tx Conformance Statement
|
|
43
|
+
|
|
44
|
+
FHIRsmith passed all 1382 HL7 terminology service tests (modes tx.fhir.org,omop,general,snomed, tests v1.9.0, runner v6.8.2)
|
|
45
|
+
|
|
8
46
|
## [v0.5.6] - 2026-02-26
|
|
9
47
|
|
|
10
48
|
### Changed
|
package/README.md
CHANGED
|
@@ -229,6 +229,8 @@ GitHub Actions will automatically:
|
|
|
229
229
|
- Change description
|
|
230
230
|
### Fixed
|
|
231
231
|
- Bug fix description
|
|
232
|
+
### Tx Conformance Statement
|
|
233
|
+
{copy content from text-cases-summary.txt}
|
|
232
234
|
```
|
|
233
235
|
2. Update `package.json` to have the same release version
|
|
234
236
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hostName" : "NPM Publisher",
|
|
3
|
+
"server": {
|
|
4
|
+
"port": 3001,
|
|
5
|
+
"cors": {
|
|
6
|
+
"origin": true,
|
|
7
|
+
"credentials": true
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"modules": {
|
|
11
|
+
"npmprojector": {
|
|
12
|
+
"enabled": false,
|
|
13
|
+
"fhirVersion": "r4",
|
|
14
|
+
"basePath": "/us-core",
|
|
15
|
+
"npm": "hl7.fhir.us.core#7.0.1",
|
|
16
|
+
"resourceFolders": ["data"],
|
|
17
|
+
"searchParametersFolder": "data",
|
|
18
|
+
"debounceMs": 500
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
package/library/html-server.js
CHANGED
|
@@ -72,7 +72,8 @@ class HtmlServer {
|
|
|
72
72
|
.replace(/\[%total-packages%\]/g, escape(renderOptions.totalPackages.toLocaleString()))
|
|
73
73
|
.replace(/\[%endpoint-path%\]/g, escape(renderOptions.endpointpath))
|
|
74
74
|
.replace(/\[%fhir-version%\]/g, escape(renderOptions.fhirversion))
|
|
75
|
-
.replace(/\[%ms%\]/g, escape(renderOptions.processingTime.toString()))
|
|
75
|
+
.replace(/\[%ms%\]/g, escape(renderOptions.processingTime.toString()))
|
|
76
|
+
.replace(/\[%about%\]/g, renderOptions.about || '');
|
|
76
77
|
|
|
77
78
|
// Handle any custom template variables
|
|
78
79
|
if (options.templateVars) {
|
|
@@ -380,7 +380,6 @@ class PackageManager {
|
|
|
380
380
|
return cachedPath;
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
-
console.log("Fetch Package "+packageId+"#"+version);
|
|
384
383
|
// Not in cache, fetch from servers
|
|
385
384
|
const packageData = await this.fetchFromServers(packageId, resolvedVersion);
|
|
386
385
|
|
|
@@ -593,42 +592,46 @@ class PackageManager {
|
|
|
593
592
|
* @returns {Promise<string>} Path to extracted package folder
|
|
594
593
|
*/
|
|
595
594
|
async fetchUrl(url) {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
595
|
+
try {
|
|
596
|
+
const client = new CIBuildClient();
|
|
597
|
+
const packageData = await client.fetchFromUrlSpecific(url);
|
|
598
|
+
|
|
599
|
+
// Extract to a temp location to read package.json for name and version
|
|
600
|
+
const tempKey = `_url_temp_${Date.now()}`;
|
|
601
|
+
const tempPath = await this.extractToCache(tempKey, 'url', packageData);
|
|
602
|
+
const tempFullPath = path.join(this.cacheFolder, tempPath);
|
|
603
|
+
|
|
604
|
+
// Read package name and version from the extracted package
|
|
605
|
+
const pkgJsonPath = path.join(tempFullPath, 'package', 'package.json');
|
|
606
|
+
const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf8'));
|
|
607
|
+
const packageId = pkgJson.name;
|
|
608
|
+
const version = pkgJson.version;
|
|
609
|
+
|
|
610
|
+
if (!packageId || !version) {
|
|
611
|
+
throw new Error(`Package at ${url} has no name or version in package.json`);
|
|
612
|
+
}
|
|
614
613
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
614
|
+
// Use the same cache key format as npm packages
|
|
615
|
+
const finalName = `${packageId}#${version}`;
|
|
616
|
+
const finalPath = path.join(this.cacheFolder, finalName);
|
|
618
617
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
618
|
+
// If it already exists, the same package is already loaded - that's a config error
|
|
619
|
+
try {
|
|
620
|
+
await fs.access(finalPath);
|
|
621
|
+
await fs.rm(tempFullPath, { recursive: true, force: true });
|
|
622
|
+
throw new Error(`Package ${finalName} already exists in cache. Check library config for duplicates (url: ${url})`);
|
|
623
|
+
} catch (e) {
|
|
624
|
+
if (e.message.includes('already exists')) throw e;
|
|
625
|
+
// Doesn't exist yet, rename temp to final
|
|
626
|
+
await fs.rename(tempFullPath, finalPath);
|
|
627
|
+
}
|
|
629
628
|
|
|
630
|
-
|
|
631
|
-
|
|
629
|
+
this.totalDownloaded = this.totalDownloaded + packageData.length;
|
|
630
|
+
return finalName;
|
|
631
|
+
} catch (error) {
|
|
632
|
+
console.error(`Error fetching package from URL ${url}: ${error.message}`);
|
|
633
|
+
throw error;
|
|
634
|
+
}
|
|
632
635
|
}
|
|
633
636
|
|
|
634
637
|
/**
|
package/library/utilities.js
CHANGED
|
@@ -274,4 +274,13 @@ class ArrayMatcher {
|
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
-
|
|
277
|
+
const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
|
278
|
+
|
|
279
|
+
function formatDateMMDDYYYY(s) {
|
|
280
|
+
const mm = parseInt(s.substring(0, 2), 10);
|
|
281
|
+
const dd = s.substring(2, 4);
|
|
282
|
+
const yyyy = s.substring(4, 8);
|
|
283
|
+
return dd + '-' + months[mm - 1] + ' ' + yyyy;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
module.exports = { Utilities, ArrayMatcher, validateParameter, validateOptionalParameter, validateArrayParameter, validateResource, strToBool, getValuePrimitive, getValueDT, getValueName, isAbsoluteUrl, formatDateMMDDYYYY };
|
|
@@ -1051,6 +1051,91 @@ class VersionUtilities {
|
|
|
1051
1051
|
return url;
|
|
1052
1052
|
}
|
|
1053
1053
|
}
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
static isAnInteger(version) {
|
|
1057
|
+
return /^\d+$/.test(version);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
static appearsToBeDate(version) {
|
|
1061
|
+
if (!version || typeof version !== 'string') return false;
|
|
1062
|
+
// Strip optional time portion (T...) before checking
|
|
1063
|
+
const datePart = version.split('T')[0];
|
|
1064
|
+
return /^\d{4}-?\d{2}(-?\d{2})?$/.test(datePart);
|
|
1065
|
+
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
static guessVersionAlgorithmFromVersion(version) {
|
|
1069
|
+
if (VersionUtilities.isSemVerWithWildcards(version)) {
|
|
1070
|
+
return 'semver';
|
|
1071
|
+
}
|
|
1072
|
+
if (this.appearsToBeDate(version)) {
|
|
1073
|
+
return 'date';
|
|
1074
|
+
}
|
|
1075
|
+
if (this.isAnInteger(version)) {
|
|
1076
|
+
return 'integer';
|
|
1077
|
+
}
|
|
1078
|
+
return 'alpha';
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
static dateIsMoreRecent(date, date2) {
|
|
1082
|
+
return VersionUtilities.normaliseDateString(date) > VersionUtilities.normaliseDateString(date2);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
static normaliseDateString(date) {
|
|
1086
|
+
// Strip time portion, then remove dashes so all formats compare uniformly as YYYYMMDD or YYYYMM
|
|
1087
|
+
return date.split('T')[0].replace(/-/g, '');
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
/**
|
|
1092
|
+
* guesses the correct format, then compares accordingly
|
|
1093
|
+
*/
|
|
1094
|
+
static compareVersionsGeneral(version1, version2) {
|
|
1095
|
+
if (version1 && version2) {
|
|
1096
|
+
if (version1 == version2) {
|
|
1097
|
+
return 0;
|
|
1098
|
+
}
|
|
1099
|
+
const fmt1 = VersionUtilities.guessVersionAlgorithmFromVersion(version1);
|
|
1100
|
+
const fmt2 = VersionUtilities.guessVersionAlgorithmFromVersion(version2);
|
|
1101
|
+
if (fmt1 != fmt2) {
|
|
1102
|
+
return version1.localeCompare(version2);
|
|
1103
|
+
}
|
|
1104
|
+
switch (fmt1) {
|
|
1105
|
+
case 'semver': {
|
|
1106
|
+
let b1 = VersionUtilities.isThisOrLater(version1, version2, VersionPrecision.PATCH);
|
|
1107
|
+
let b2 = VersionUtilities.isThisOrLater(version2, version1, VersionPrecision.PATCH);
|
|
1108
|
+
if (b1 && b2) {
|
|
1109
|
+
return 0;
|
|
1110
|
+
} else if (b2) {
|
|
1111
|
+
return 1;
|
|
1112
|
+
} else {
|
|
1113
|
+
return -1;
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
case 'date':
|
|
1117
|
+
if (VersionUtilities.dateIsMoreRecent(version1, version2)) {
|
|
1118
|
+
return 1;
|
|
1119
|
+
} else if (VersionUtilities.dateIsMoreRecent(version2, version1)) {
|
|
1120
|
+
return -1;
|
|
1121
|
+
} else {
|
|
1122
|
+
return 0;
|
|
1123
|
+
}
|
|
1124
|
+
case 'integer':
|
|
1125
|
+
return parseInt(version1, 10) - parseInt(version2, 10);
|
|
1126
|
+
case 'alpha':
|
|
1127
|
+
return version1.localeCompare(version2);
|
|
1128
|
+
default:
|
|
1129
|
+
return version1.localeCompare(version2);
|
|
1130
|
+
}
|
|
1131
|
+
} else if (version1) {
|
|
1132
|
+
return 1;
|
|
1133
|
+
} else if (version2) {
|
|
1134
|
+
return -1;
|
|
1135
|
+
} else {
|
|
1136
|
+
return 0;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1054
1139
|
}
|
|
1055
1140
|
|
|
1056
1141
|
module.exports = { VersionUtilities, VersionPrecision, SemverParser };
|