fhirsmith 0.5.4 → 0.5.5
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 +11 -1
- package/package.json +1 -1
- package/tx/library/canonical-resource.js +63 -0
- package/tx/library.js +7 -2
- package/tx/provider.js +7 -2
- package/tx/workers/search.js +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,9 +5,19 @@ 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.5.5] - 2026-02-26
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Fix loading problem for multiple versions of the same code system
|
|
12
|
+
- Fix url matching in search to be precise
|
|
13
|
+
|
|
14
|
+
### Tx Conformance Statement
|
|
15
|
+
|
|
16
|
+
FHIRsmith 0.5.5 passed all 1382 HL7 terminology service tests (modes tx.fhir.org,omop,general,snomed, tests v1.9.0, runner v6.8.1)
|
|
17
|
+
|
|
8
18
|
## [v0.5.4] - 2026-02-25
|
|
9
19
|
|
|
10
|
-
This version requires that you delete all package content from the terminology-cache directly
|
|
20
|
+
This version requires that you delete all package content from the terminology-cache directly
|
|
11
21
|
by hand before running this version.
|
|
12
22
|
|
|
13
23
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const {VersionUtilities, VersionPrecision} = require("../../library/version-utilities");
|
|
1
2
|
|
|
2
3
|
/**
|
|
3
4
|
* Base class for metadata resources to provide common interface
|
|
@@ -83,6 +84,68 @@ class CanonicalResource {
|
|
|
83
84
|
}
|
|
84
85
|
return this.jsonObj.versionAlgorithmString;
|
|
85
86
|
}
|
|
87
|
+
|
|
88
|
+
guessVersionAlgorithmFromVersion(version) {
|
|
89
|
+
if (VersionUtilities.isSemVerWithWildcards(version)) {
|
|
90
|
+
return 'semver';
|
|
91
|
+
}
|
|
92
|
+
if (this.appearsToBeDate(version)) {
|
|
93
|
+
return 'date';
|
|
94
|
+
}
|
|
95
|
+
if (this.isAnInteger(version)) {
|
|
96
|
+
return 'integer';
|
|
97
|
+
}
|
|
98
|
+
return 'alpha';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* returns true if this is more recent than other.
|
|
103
|
+
*
|
|
104
|
+
* Uses version if possible, otherwise uses date
|
|
105
|
+
*
|
|
106
|
+
* @param other
|
|
107
|
+
* @returns {boolean}
|
|
108
|
+
*/
|
|
109
|
+
isMoreRecent(other) {
|
|
110
|
+
if (this.version && other.version && this.version != other.version) {
|
|
111
|
+
const fmt = this.versionAlgorithm() || other.versionAlgorithm() || this.guessVersionAlgorithmFromVersion(this.version);
|
|
112
|
+
switch (fmt) {
|
|
113
|
+
case 'semver':
|
|
114
|
+
return VersionUtilities.isThisOrLater(other.version, this.version, VersionPrecision.PATCH);
|
|
115
|
+
case 'date':
|
|
116
|
+
return this.dateIsMoreRecent(this.version, other.version);
|
|
117
|
+
case 'integer':
|
|
118
|
+
return parseInt(this.version, 10) > parseInt(other.version, 10);
|
|
119
|
+
case 'alpha': return this.version.localeCompare(other.version) > 0;
|
|
120
|
+
default: return this.version.localeCompare(other.version);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (this.date && other.date && this.date != other.date) {
|
|
124
|
+
return this.dateIsMoreRecent(this.date, other.date);
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
appearsToBeDate(version) {
|
|
130
|
+
if (!version || typeof version !== 'string') return false;
|
|
131
|
+
// Strip optional time portion (T...) before checking
|
|
132
|
+
const datePart = version.split('T')[0];
|
|
133
|
+
return /^\d{4}-?\d{2}(-?\d{2})?$/.test(datePart);
|
|
134
|
+
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
dateIsMoreRecent(date, date2) {
|
|
138
|
+
return this.normaliseDateString(date) > this.normaliseDateString(date2);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
normaliseDateString(date) {
|
|
142
|
+
// Strip time portion, then remove dashes so all formats compare uniformly as YYYYMMDD or YYYYMM
|
|
143
|
+
return date.split('T')[0].replace(/-/g, '');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
isAnInteger(version) {
|
|
147
|
+
return /^\d+$/.test(version);
|
|
148
|
+
}
|
|
86
149
|
}
|
|
87
150
|
|
|
88
151
|
module.exports = { CanonicalResource };
|
package/tx/library.js
CHANGED
|
@@ -449,8 +449,13 @@ class Library {
|
|
|
449
449
|
for (const resource of resources) {
|
|
450
450
|
const cs = new CodeSystem(await contentLoader.loadFile(resource, contentLoader.fhirVersion()));
|
|
451
451
|
cs.sourcePackage = contentLoader.pid();
|
|
452
|
-
cp.codeSystems.
|
|
453
|
-
|
|
452
|
+
const existing = cp.codeSystems.get(cs.url);
|
|
453
|
+
if (!existing || cs.isMoreRecent(existing)) {
|
|
454
|
+
cp.codeSystems.set(cs.url, cs);
|
|
455
|
+
}
|
|
456
|
+
if (cs.version) {
|
|
457
|
+
cp.codeSystems.set(cs.vurl, cs);
|
|
458
|
+
}
|
|
454
459
|
csc++;
|
|
455
460
|
}
|
|
456
461
|
this.codeSystemProviders.push(cp);
|
package/tx/provider.js
CHANGED
|
@@ -136,8 +136,13 @@ class Provider {
|
|
|
136
136
|
for (const resource of resources) {
|
|
137
137
|
const cs = new CodeSystem(await contentLoader.loadFile(resource, contentLoader.fhirVersion()));
|
|
138
138
|
cs.sourcePackage = contentLoader.pid();
|
|
139
|
-
this.codeSystems.
|
|
140
|
-
|
|
139
|
+
const existing = this.codeSystems.get(cs.url);
|
|
140
|
+
if (!existing || cs.isMoreRecent(existing)) {
|
|
141
|
+
this.codeSystems.set(cs.url, cs);
|
|
142
|
+
}
|
|
143
|
+
if (cs.version) {
|
|
144
|
+
this.codeSystems.set(cs.vurl, cs);
|
|
145
|
+
}
|
|
141
146
|
}
|
|
142
147
|
const vs = new PackageValueSetProvider(contentLoader);
|
|
143
148
|
await vs.initialize();
|
package/tx/workers/search.js
CHANGED
|
@@ -177,6 +177,12 @@ class SearchWorker extends TerminologyWorker {
|
|
|
177
177
|
isMatch = false;
|
|
178
178
|
break;
|
|
179
179
|
}
|
|
180
|
+
} else if (param === 'url') { // exact match
|
|
181
|
+
const propValue = json.url;
|
|
182
|
+
if (propValue != searchValue) {
|
|
183
|
+
isMatch = false;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
180
186
|
} else {
|
|
181
187
|
// Standard partial text match
|
|
182
188
|
const propValue = json[jsonProp];
|