fhirsmith 0.10.0 → 0.10.1
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 +12 -1
- package/package.json +1 -1
- package/tx/library/renderer.js +8 -8
- package/tx/provider.js +3 -3
- package/tx/vs/vs-database.js +41 -8
- package/tx/vs/vs-package.js +3 -0
- package/tx/vs/vs-vsac.js +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,17 @@ 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
8
|
|
|
9
|
+
## [v0.10.1] - 2026-06-27
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Terminology: the version-less value set lookup now resolves to the latest version when several versions of the same value set are present (e.g. VSAC date versions), instead of an arbitrary one determined by database row order
|
|
14
|
+
- Rendering: fixed value set links in `renderLinkComma` (read the resolver's `description`/`link` fields and fall back to the raw URI)
|
|
15
|
+
|
|
16
|
+
### Tx Conformance Statement
|
|
17
|
+
|
|
18
|
+
FHIRsmith passed all 2503 HL7 terminology service tests (modes tx.fhir.org+omop+general+snomed, tests v1.9.1, runner v6.9.11)
|
|
19
|
+
|
|
9
20
|
## [v0.10.0] - 2026-06-27
|
|
10
21
|
|
|
11
22
|
### Added
|
|
@@ -35,7 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
35
46
|
|
|
36
47
|
### Tx Conformance Statement
|
|
37
48
|
|
|
38
|
-
FHIRsmith passed all 2503 HL7 terminology service tests (modes tx.fhir.org+omop+general+snomed, tests v1.9.1, runner v6.9.11
|
|
49
|
+
FHIRsmith passed all 2503 HL7 terminology service tests (modes tx.fhir.org+omop+general+snomed, tests v1.9.1, runner v6.9.11)
|
|
39
50
|
|
|
40
51
|
## [v0.9.7] - 2026-06-12
|
|
41
52
|
|
package/package.json
CHANGED
package/tx/library/renderer.js
CHANGED
|
@@ -340,12 +340,12 @@ class Renderer {
|
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
renderLinkComma(x, uri) {
|
|
344
|
-
let {
|
|
345
|
-
if (
|
|
346
|
-
x.commaItem(
|
|
343
|
+
async renderLinkComma(x, uri) {
|
|
344
|
+
let {description, link} = await (this.linkResolver ? this.linkResolver.resolveURL(this.opContext, uri) : null) || {};
|
|
345
|
+
if (link) {
|
|
346
|
+
x.commaItem(description, link);
|
|
347
347
|
} else {
|
|
348
|
-
x.commaItem(
|
|
348
|
+
x.commaItem(link);
|
|
349
349
|
}
|
|
350
350
|
}
|
|
351
351
|
|
|
@@ -673,7 +673,7 @@ class Renderer {
|
|
|
673
673
|
p.tx(" ");
|
|
674
674
|
p.startCommaList("and");
|
|
675
675
|
for (let ext of supplements) {
|
|
676
|
-
this.renderLinkComma(p, getValuePrimitive(ext));
|
|
676
|
+
await this.renderLinkComma(p, getValuePrimitive(ext));
|
|
677
677
|
}
|
|
678
678
|
p.stopCommaList();
|
|
679
679
|
p.tx(".");
|
|
@@ -762,10 +762,10 @@ class Renderer {
|
|
|
762
762
|
li.stopCommaList();
|
|
763
763
|
}
|
|
764
764
|
} else if (inc.valueSet && inc.valueSet.length > 0) {
|
|
765
|
-
li.tx(this.translatePlural(inc.valueSet.length, '
|
|
765
|
+
li.tx(this.translatePlural(inc.valueSet.length, 'VALUE_SET_IMPORT')+" ");
|
|
766
766
|
li.startCommaList("and");
|
|
767
767
|
for (let vs of inc.valueSet) {
|
|
768
|
-
this.renderLinkComma(li, vs);
|
|
768
|
+
await this.renderLinkComma(li, vs);
|
|
769
769
|
}
|
|
770
770
|
li.stopCommaList();
|
|
771
771
|
} else {
|
package/tx/provider.js
CHANGED
|
@@ -231,8 +231,8 @@ class Provider {
|
|
|
231
231
|
return vs;
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
|
-
let
|
|
235
|
-
return
|
|
234
|
+
let vs1 = await this.findKnownValueSet(url, version);
|
|
235
|
+
return vs1;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
async getConceptMapById(opContext, id) {
|
|
@@ -381,7 +381,7 @@ class Provider {
|
|
|
381
381
|
if (vs) {
|
|
382
382
|
return {
|
|
383
383
|
link: this.path+"/ValueSet/"+vs.id,
|
|
384
|
-
description: (vs.title ? vs.title : vs.name)+(version ? " v"+version : "")
|
|
384
|
+
description: (vs.title ? vs.title : vs.name)+(version ? " v"+version : vs.version ? " v"+vs.version : "")
|
|
385
385
|
};
|
|
386
386
|
}
|
|
387
387
|
let cm = await this.findConceptMap(opContext, system, version);
|
package/tx/vs/vs-database.js
CHANGED
|
@@ -7,6 +7,30 @@ const ValueSet = require("../library/valueset");
|
|
|
7
7
|
// Columns that can be returned directly without parsing JSON
|
|
8
8
|
const INDEXED_COLUMNS = ['id', 'url', 'version', 'date', 'description', 'name', 'publisher', 'status', 'title'];
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Is `candidate` a newer version than `current`? Used to keep the version-less
|
|
12
|
+
* (bare-url) and url|major.minor map keys pointing at the latest version when several
|
|
13
|
+
* versions of the same value set are present. Handles both semver (IG/package value
|
|
14
|
+
* sets) and VSAC-style YYYYMMDD date versions (not semver, but fixed-width so they
|
|
15
|
+
* order correctly numerically).
|
|
16
|
+
* @param {string|null|undefined} candidate
|
|
17
|
+
* @param {string|null|undefined} current
|
|
18
|
+
* @returns {boolean}
|
|
19
|
+
*/
|
|
20
|
+
function isNewerVersion(candidate, current) {
|
|
21
|
+
if (current == null) return true;
|
|
22
|
+
if (candidate == null) return false;
|
|
23
|
+
if (candidate === current) return false;
|
|
24
|
+
if (VersionUtilities.isSemVer(candidate) && VersionUtilities.isSemVer(current)) {
|
|
25
|
+
return VersionUtilities.isThisOrLater(current, candidate); // candidate >= current (semver-aware)
|
|
26
|
+
}
|
|
27
|
+
if (/^\d+$/.test(candidate) && /^\d+$/.test(current)) {
|
|
28
|
+
// e.g. VSAC YYYYMMDD - compare numerically (handles differing widths too)
|
|
29
|
+
return Number(candidate) > Number(current);
|
|
30
|
+
}
|
|
31
|
+
return candidate > current; // best-effort lexical fallback
|
|
32
|
+
}
|
|
33
|
+
|
|
10
34
|
/**
|
|
11
35
|
* Shared database layer for ValueSet providers
|
|
12
36
|
* Handles SQLite operations for indexing and searching ValueSets
|
|
@@ -737,21 +761,22 @@ class ValueSetDatabase {
|
|
|
737
761
|
}
|
|
738
762
|
|
|
739
763
|
addToMap(valueSetMap, id, url, version, valueSet) {
|
|
740
|
-
|
|
741
|
-
|
|
764
|
+
// The bare-url key must resolve to the *latest* version, but rows arrive in no
|
|
765
|
+
// particular order (and several versions of the same url coexist - e.g. VSAC, where
|
|
766
|
+
// each date-version is its own row). So only overwrite it when this version is newer.
|
|
767
|
+
this._setIfNewer(valueSetMap, url, version, valueSet);
|
|
768
|
+
valueSetMap.set(id, valueSet); // id is unique per version
|
|
742
769
|
|
|
743
770
|
if (version) {
|
|
744
|
-
// Store by url|version
|
|
745
|
-
|
|
746
|
-
valueSetMap.set(versionKey, valueSet);
|
|
771
|
+
// Store by url|version (exact - unique per version, always set)
|
|
772
|
+
valueSetMap.set(`${url}|${version}`, valueSet);
|
|
747
773
|
|
|
748
|
-
// If version is semver, also store by url|major.minor
|
|
774
|
+
// If version is semver, also store by url|major.minor, keeping the latest patch
|
|
749
775
|
try {
|
|
750
776
|
if (VersionUtilities.isSemVer(version)) {
|
|
751
777
|
const majorMinor = VersionUtilities.getMajMin(version);
|
|
752
778
|
if (majorMinor) {
|
|
753
|
-
|
|
754
|
-
valueSetMap.set(majorMinorKey, valueSet);
|
|
779
|
+
this._setIfNewer(valueSetMap, `${url}|${majorMinor}`, version, valueSet);
|
|
755
780
|
}
|
|
756
781
|
}
|
|
757
782
|
} catch (error) {
|
|
@@ -760,6 +785,14 @@ class ValueSetDatabase {
|
|
|
760
785
|
}
|
|
761
786
|
}
|
|
762
787
|
|
|
788
|
+
// Set map[key] = valueSet only if `version` is newer than the version already there.
|
|
789
|
+
_setIfNewer(valueSetMap, key, version, valueSet) {
|
|
790
|
+
const existing = valueSetMap.get(key);
|
|
791
|
+
if (!existing || isNewerVersion(version, existing.version)) {
|
|
792
|
+
valueSetMap.set(key, valueSet);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
763
796
|
/**
|
|
764
797
|
* Search for ValueSets based on criteria
|
|
765
798
|
* @param {Array<{name: string, value: string}>} searchParams - Search criteria
|
package/tx/vs/vs-package.js
CHANGED