fhirsmith 0.8.6 → 0.9.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.
@@ -1511,3 +1511,4 @@ CONFORMANCE_STATEMENT_WORD = The html source contains the word ''{0}'' but it is
1511
1511
  VALUESET_CODE_CONCEPT_HINT = {3}. Note that the display in the ValueSet does not have to match; this check exists to help check that it''s not accidentally the wrong code
1512
1512
  VALUESET_CODE_CONCEPT_HINT_VER ={3}. Note that the display in the ValueSet does not have to match; this check exists to help check that it''s not accidentally the wrong code
1513
1513
  TERMINOLOGY_TX_SYSTEM_UNSUPPORTED = The code cannot be checked because codeSystem ''{0}'' version ''{1}'' is not supported ({2})
1514
+ INVALID_REGEX = The regex ''{0}'' is not valid: {1}
@@ -2,6 +2,7 @@ const { CodeSystemProvider, FilterExecutionContext } = require('../../tx/cs/cs-a
2
2
  const assert = require('assert');
3
3
  const { CodeSystem } = require("../library/codesystem");
4
4
  const {CodeSystemFactoryProvider} = require("./cs-api");
5
+ const regexUtilities = require("../../library/regex-utilities");
5
6
 
6
7
  class CountryCodeConcept {
7
8
  constructor(userDefined, code, display, french) {
@@ -199,7 +200,7 @@ class CountryCodeServices extends CodeSystemProvider {
199
200
 
200
201
  try {
201
202
  // Create regex with anchors to match the Pascal implementation (^value$)
202
- const regex = new RegExp('^' + value + '$');
203
+ const regex = regexUtilities.compile('^' + value + '$');
203
204
 
204
205
  for (const concept of this.codes) {
205
206
  if (regex.test(concept.code)) {
package/tx/cs/cs-cs.js CHANGED
@@ -6,6 +6,7 @@ const { validateOptionalParameter, getValuePrimitive, validateArrayParameter} =
6
6
  const {Issue} = require("../library/operation-outcome");
7
7
  const {Extensions} = require("../library/extensions");
8
8
  const {BaseCSServices} = require("./cs-base");
9
+ const regexUtilities = require("../../library/regex-utilities");
9
10
 
10
11
  /**
11
12
  * Context class for FHIR CodeSystem provider concepts
@@ -1309,7 +1310,7 @@ class FhirCodeSystemProvider extends BaseCSServices {
1309
1310
  else if (op === 'regex') {
1310
1311
  // Regular expression match
1311
1312
  try {
1312
- const regex = new RegExp('^' + value + '$');
1313
+ const regex = regexUtilities.compile('^' + value + '$');
1313
1314
  const allCodes = this.codeSystem.getAllCodes();
1314
1315
  for (const code of allCodes) {
1315
1316
  if (regex.test(code)) {
@@ -1320,7 +1321,7 @@ class FhirCodeSystemProvider extends BaseCSServices {
1320
1321
  }
1321
1322
  }
1322
1323
  } catch (error) {
1323
- throw new Error(`Invalid regex pattern: ${value}`);
1324
+ throw new Issue('error', 'exception', null, 'INVALID_REGEX', this.opContext.i18n.translate('INVALID_REGEX', this.opContext.langs, [value, error.message]), 'vs-invalid', 422);
1324
1325
  }
1325
1326
  }
1326
1327
 
@@ -1428,7 +1429,7 @@ class FhirCodeSystemProvider extends BaseCSServices {
1428
1429
  }
1429
1430
  else if (op === 'regex') {
1430
1431
  try {
1431
- const regex = new RegExp('^' + value + '$');
1432
+ const regex = regexUtilities.compile('^' + value + '$');
1432
1433
  return properties.some(p => regex.test(this._getPropertyValue(p)));
1433
1434
  } catch (error) {
1434
1435
  return false;
package/tx/cs/cs-loinc.js CHANGED
@@ -6,6 +6,7 @@ const { CodeSystemFactoryProvider} = require('./cs-api');
6
6
  const { validateOptionalParameter, validateArrayParameter} = require("../../library/utilities");
7
7
  const {BaseCSServices} = require("./cs-base");
8
8
  const {sqlEscapeString} = require("../../xig/xig");
9
+ const regexUtilities = require('../../library/regex-utilities');
9
10
 
10
11
  // Context kinds matching Pascal enum
11
12
  const LoincProviderContextKind = {
@@ -938,7 +939,7 @@ class LoincServices extends BaseCSServices {
938
939
  // Helper method for regex matching
939
940
  async #findRegexMatches(sql, pattern, valueColumn, keyColumn = 'Key') {
940
941
  return new Promise((resolve, reject) => {
941
- const regex = new RegExp(pattern);
942
+ const regex = regexUtilities.compile(pattern);
942
943
  const matchingKeys = [];
943
944
 
944
945
  this.db.all(sql, (err, rows) => {
@@ -1622,7 +1622,7 @@ class SnomedServicesFactory extends CodeSystemFactoryProvider {
1622
1622
  internalSource : this,
1623
1623
  relationship: relationship,
1624
1624
  id : id,
1625
- url: `${this.system}?fhir_cm=${id}`,
1625
+ url: `${this.system()}?fhir_cm=${id}`,
1626
1626
  version: this.version(),
1627
1627
  name: `SNOMED CT ${name} Concept Map`,
1628
1628
  description: `The concept map implicitly defined by the ${name} Association Reference Set`,
@@ -0,0 +1,133 @@
1
+ {
2
+ "resourceType": "OperationDefinition",
3
+ "id": "ValueSet-related",
4
+ "url": "http://hl7.org/fhir/OperationDefinition/ValueSet-related",
5
+ "version": "5.0.0",
6
+ "name": "ValueSetRelated",
7
+ "title": "Value Set Related Determination",
8
+ "status": "active",
9
+ "kind": "operation",
10
+ "experimental": false,
11
+ "date": "2023-03-26T15:21:02+11:00",
12
+ "publisher": "FHIRsmith",
13
+ "description": "Determine the relationship between two value sets. Different versions of code systems are considered compatible unless versionNeeded = true for the code system",
14
+ "jurisdiction": [
15
+ {
16
+ "coding": [
17
+ {
18
+ "system": "http://unstats.un.org/unsd/methods/m49/m49.htm",
19
+ "code": "001",
20
+ "display": "World"
21
+ }
22
+ ]
23
+ }
24
+ ],
25
+ "affectsState": false,
26
+ "code": "related",
27
+ "comment": "An $expand will be performed internally if needed.",
28
+ "resource": [
29
+ "ValueSet"
30
+ ],
31
+ "system": false,
32
+ "type": true,
33
+ "instance": false,
34
+ "parameter": [
35
+ {
36
+ "name": "thisUrl",
37
+ "use": "in",
38
+ "scope": [
39
+ "type"
40
+ ],
41
+ "min": 0,
42
+ "max": "1",
43
+ "documentation": "Value set Canonical URL for the first value set of the pair (the base). The server must know the value set (e.g. it is provided as an attached resource, it is defined explicitly in the server's value sets, or it is defined implicitly by some code system known to the server",
44
+ "type": "uri"
45
+ },
46
+ {
47
+ "name": "otherUrl",
48
+ "use": "in",
49
+ "scope": [
50
+ "type"
51
+ ],
52
+ "min": 0,
53
+ "max": "1",
54
+ "documentation": "Value set Canonical URL for the second value set of the pair (the one being compared to base). The server must know the value set (e.g. it is provided as an attached resource, it is defined explicitly in the server's value sets, or it is defined implicitly by some code system known to the server",
55
+ "type": "uri"
56
+ },
57
+ {
58
+ "name": "thisValueSet",
59
+ "use": "in",
60
+ "scope": [
61
+ "type"
62
+ ],
63
+ "min": 0,
64
+ "max": "1",
65
+ "documentation": "The first value set is provided directly as part of the request. Servers may choose not to accept value sets in this fashion. This parameter is used when the client wants the server to expand a value set that is not stored on the server",
66
+ "type": "ValueSet"
67
+ },
68
+ {
69
+ "name": "otherValueSet",
70
+ "use": "in",
71
+ "scope": [
72
+ "type"
73
+ ],
74
+ "min": 0,
75
+ "max": "1",
76
+ "documentation": "The other value set is provided directly as part of the request. Servers may choose not to accept value sets in this fashion. This parameter is used when the client wants the server to expand a value set that is not stored on the server",
77
+ "type": "ValueSet"
78
+ },
79
+ {
80
+ "name": "thisVersion",
81
+ "use": "in",
82
+ "scope": [
83
+ "type"
84
+ ],
85
+ "min": 0,
86
+ "max": "1",
87
+ "documentation": "The identifier that is used to identify a specific version of the value set to be used when validating the code. This is an arbitrary value managed by the value set author and is not expected to be globally unique. For example, it might be a timestamp (e.g. yyyymmdd) if a managed version is not available.",
88
+ "type": "string"
89
+ },
90
+ {
91
+ "name": "otherVersion",
92
+ "use": "in",
93
+ "scope": [
94
+ "type"
95
+ ],
96
+ "min": 0,
97
+ "max": "1",
98
+ "documentation": "The identifier that is used to identify a specific version of the value set to be used when validating the code. This is an arbitrary value managed by the value set author and is not expected to be globally unique. For example, it might be a timestamp (e.g. yyyymmdd) if a managed version is not available.",
99
+ "type": "string"
100
+ },
101
+ {
102
+ "name": "useSupplement",
103
+ "use": "in",
104
+ "min": 0,
105
+ "max": "*",
106
+ "documentation": "The supplement must be used when validating the code. Use of this parameter should result in $validate-code behaving the same way as if the supplements were included in the value set definition using the [http://hl7.org/fhir/StructureDefinition/valueset-supplement](http://hl7.org/fhir/extensions/StructureDefinition-valueset-supplement.html)",
107
+ "type": "canonical"
108
+ },
109
+ {
110
+ "name": "diagnostics",
111
+ "use": "in",
112
+ "min": 0,
113
+ "max": "1",
114
+ "documentation": "Whether to return information about the reasoning process"
115
+ },
116
+ {
117
+ "name": "result",
118
+ "use": "out",
119
+ "min": 1,
120
+ "max": "1",
121
+ "documentation": "The relationship between the ValueSets. One of: same, superset, subset, overlapping, dsjoint, empty, and indeterminate",
122
+ "type": "boolean"
123
+ },
124
+ {
125
+ "name": "message",
126
+ "use": "out",
127
+ "min": 0,
128
+ "max": "1",
129
+ "documentation": "Explanation of the code, with reason if appropriate",
130
+ "type": "string"
131
+ }
132
+ ]
133
+ }
@@ -6,7 +6,7 @@ const ATC_FILE = process.argv[2] || '2025_ATC.xml';
6
6
  const DDD_FILE = process.argv[3] || '2025_ATC_ddd.xml';
7
7
  const OUTPUT_FILE = process.argv[4] || 'atc-codesystem.json';
8
8
 
9
- const PROPERTY_GROUP_EXT_URL = 'http://hl7.org/fhir/property.group';
9
+ const PROPERTY_GROUP_EXT_URL = 'http://hl7.org/fhir/StructureDefinition/Codesystem-property-group';
10
10
 
11
11
  // Parse XML files
12
12
  function parseXML(filePath) {
@@ -277,32 +277,7 @@ try {
277
277
  console.log(`Writing to ${OUTPUT_FILE}...`);
278
278
  fs.writeFileSync(OUTPUT_FILE, JSON.stringify(codeSystem, null, 2));
279
279
  console.log('Done!');
280
-
281
- // Print some stats
282
- function countConcepts(concepts) {
283
- let count = 0;
284
- for (const c of concepts) {
285
- count++;
286
- if (c.concept) {
287
- count += countConcepts(c.concept);
288
- }
289
- }
290
- return count;
291
- }
292
-
293
- function countWithDDD(concepts) {
294
- let count = 0;
295
- for (const c of concepts) {
296
- if (c.property?.some(p => p.code === 'dddValue')) {
297
- count++;
298
- }
299
- if (c.concept) {
300
- count += countWithDDD(c.concept);
301
- }
302
- }
303
- return count;
304
- }
305
-
280
+
306
281
  const totalConcepts = countConcepts(codeSystem.concept);
307
282
  const withDDD = countWithDDD(codeSystem.concept);
308
283
  console.log(`\nStatistics:`);
@@ -314,3 +289,28 @@ try {
314
289
  console.error('Error:', error.message);
315
290
  process.exit(1);
316
291
  }
292
+
293
+ // Print some stats
294
+ function countConcepts(concepts) {
295
+ let count = 0;
296
+ for (const c of concepts) {
297
+ count++;
298
+ if (c.concept) {
299
+ count += countConcepts(c.concept);
300
+ }
301
+ }
302
+ return count;
303
+ }
304
+
305
+ function countWithDDD(concepts) {
306
+ let count = 0;
307
+ for (const c of concepts) {
308
+ if (c.property?.some(p => p.code === 'dddValue')) {
309
+ count++;
310
+ }
311
+ if (c.concept) {
312
+ count += countWithDDD(c.concept);
313
+ }
314
+ }
315
+ return count;
316
+ }
@@ -10,6 +10,7 @@ const {
10
10
  BaseUnit, DefinedUnit, Prefix, Value, Term, Symbol, Factor, Canonical, CanonicalUnit,
11
11
  Registry
12
12
  } = require('./ucum-types.js');
13
+ const regexUtilities = require("../../library/regex-utilities");
13
14
 
14
15
  // Lexer for tokenizing UCUM expressions (port of Lexer.java)
15
16
  class Lexer {
@@ -763,7 +764,7 @@ class Search {
763
764
 
764
765
  if (isRegex) {
765
766
  try {
766
- const regex = new RegExp(text);
767
+ const regex = regexUtilities.compile(text);
767
768
  return regex.test(value);
768
769
  } catch (e) {
769
770
  this.log.error(e);
package/tx/ocl/cs-ocl.cjs CHANGED
@@ -13,6 +13,7 @@ const { OCLBackgroundJobQueue } = require('./jobs/background-queue');
13
13
  const { OCLConceptFilterContext } = require('./model/concept-filter-context');
14
14
  const { toConceptContext } = require('./mappers/concept-mapper');
15
15
  const { patchSearchWorkerForOCLCodeFiltering } = require('./shared/patches');
16
+ const regexUtilities = require("../../library/regex-utilities");
16
17
 
17
18
  patchSearchWorkerForOCLCodeFiltering();
18
19
 
@@ -735,6 +736,17 @@ class OCLSourceCodeSystemProvider extends CodeSystemProvider {
735
736
  return { context: this.conceptCache.get(code), message: null };
736
737
  }
737
738
 
739
+ // OCL concept IDs may differ in case from the FHIR code (e.g. "y" vs "Y").
740
+ // Try a case-insensitive cache lookup before hitting the network.
741
+ const codeLower = code.toLowerCase();
742
+ for (const [key, value] of this.conceptCache.entries()) {
743
+ if (key.toLowerCase() === codeLower) {
744
+ // Cache under the requested case as well so future lookups are O(1).
745
+ this.conceptCache.set(code, value);
746
+ return { context: value, message: null };
747
+ }
748
+ }
749
+
738
750
  if (this.scheduleBackgroundLoad) {
739
751
  this.scheduleBackgroundLoad('lookup-miss');
740
752
  }
@@ -1032,23 +1044,26 @@ class OCLSourceCodeSystemProvider extends CodeSystemProvider {
1032
1044
  this.scheduleBackgroundLoad('concept-miss');
1033
1045
  }
1034
1046
 
1035
- const url = this.#buildConceptUrl(code);
1036
1047
  const pending = (async () => {
1037
- let response;
1038
- try {
1039
- response = await this.httpClient.get(url, { params: { verbose: true } });
1040
- } catch (error) {
1041
- // Missing concept should be treated as not-found, not as an internal server failure.
1042
- if (error && error.response && error.response.status === 404) {
1043
- return null;
1044
- }
1045
- throw error;
1048
+ const concept = await this.#fetchConceptByCode(code);
1049
+ if (concept) {
1050
+ return concept;
1046
1051
  }
1047
- const concept = this.#toConceptContext(response.data);
1048
- if (concept && concept.code) {
1049
- this.conceptCache.set(concept.code, concept);
1052
+ // OCL concept IDs may differ in case from the FHIR code (e.g. "y" vs "Y").
1053
+ // Try common case alternatives before giving up.
1054
+ const lower = code.toLowerCase();
1055
+ const upper = code.toUpperCase();
1056
+ for (const alt of [lower, upper]) {
1057
+ if (alt !== code) {
1058
+ const altConcept = await this.#fetchConceptByCode(alt);
1059
+ if (altConcept) {
1060
+ // Cache under the originally requested code so future lookups hit directly.
1061
+ this.conceptCache.set(code, altConcept);
1062
+ return altConcept;
1063
+ }
1064
+ }
1050
1065
  }
1051
- return concept;
1066
+ return null;
1052
1067
  })();
1053
1068
 
1054
1069
  this.pendingConceptRequests.set(pendingKey, pending);
@@ -1059,6 +1074,24 @@ class OCLSourceCodeSystemProvider extends CodeSystemProvider {
1059
1074
  }
1060
1075
  }
1061
1076
 
1077
+ async #fetchConceptByCode(code) {
1078
+ const url = this.#buildConceptUrl(code);
1079
+ let response;
1080
+ try {
1081
+ response = await this.httpClient.get(url, { params: { verbose: true } });
1082
+ } catch (error) {
1083
+ if (error && error.response && error.response.status === 404) {
1084
+ return null;
1085
+ }
1086
+ throw error;
1087
+ }
1088
+ const concept = this.#toConceptContext(response.data);
1089
+ if (concept && concept.code) {
1090
+ this.conceptCache.set(concept.code, concept);
1091
+ }
1092
+ return concept;
1093
+ }
1094
+
1062
1095
  async #allConceptContexts() {
1063
1096
  const concepts = new Map();
1064
1097
 
@@ -1135,7 +1168,7 @@ class OCLSourceCodeSystemProvider extends CodeSystemProvider {
1135
1168
 
1136
1169
  #buildPropertyMatcher(prop, op, value) {
1137
1170
  if (op === 'regex') {
1138
- const regex = new RegExp(String(value), 'i');
1171
+ const regex = regexUtilities.compile(String(value), 'i');
1139
1172
  return concept => {
1140
1173
  const candidate = this.#valueForFilter(concept, prop);
1141
1174
  if (candidate == null) {
package/tx/ocl/vs-ocl.cjs CHANGED
@@ -389,20 +389,26 @@ class OCLValueSetProvider extends AbstractValueSetProvider {
389
389
  }
390
390
 
391
391
  #indexValueSet(vs) {
392
- const existing = this.valueSetMap.get(vs.url)
393
- || (vs.version ? this.valueSetMap.get(`${vs.url}|${vs.version}`) : null)
394
- || this._idMap.get(vs.id)
395
- || null;
396
-
397
- // indexa se não existe ou se for o mesmo objeto
398
- if (!existing || existing === vs) {
399
- this.valueSetMap.set(vs.url, vs);
400
- if (vs.version) {
401
- this.valueSetMap.set(`${vs.url}|${vs.version}`, vs);
402
- }
403
- this.valueSetMap.set(vs.id, vs);
404
- this._idMap.set(vs.id, vs);
392
+ const existing = this.valueSetMap.get(vs.url) || null;
393
+
394
+ // When fresh discovery metadata replaces a cold-cached entry, carry over
395
+ // the enumerated compose so the expand engine doesn't fall back to
396
+ // "include whole CodeSystem". The background expansion will eventually
397
+ // refresh it with up-to-date collection contents.
398
+ if (existing && existing !== vs
399
+ && Array.isArray(existing.jsonObj?.compose?.include)
400
+ && existing.jsonObj.compose.include.some(inc => Array.isArray(inc.concept) && inc.concept.length > 0)
401
+ && (!vs.jsonObj.compose || !Array.isArray(vs.jsonObj.compose.include) || vs.jsonObj.compose.include.length === 0)
402
+ ) {
403
+ vs.jsonObj.compose = existing.jsonObj.compose;
404
+ }
405
+
406
+ this.valueSetMap.set(vs.url, vs);
407
+ if (vs.version) {
408
+ this.valueSetMap.set(`${vs.url}|${vs.version}`, vs);
405
409
  }
410
+ this.valueSetMap.set(vs.id, vs);
411
+ this._idMap.set(vs.id, vs);
406
412
  }
407
413
 
408
414
  #toValueSet(collection) {
@@ -568,6 +574,17 @@ class OCLValueSetProvider extends AbstractValueSetProvider {
568
574
  ? vs.jsonObj.compose.include
569
575
  : [];
570
576
 
577
+ // If the compose already has enumerated concepts (from background expansion),
578
+ // it is the authoritative representation of the collection contents — don't
579
+ // overwrite it with system-only entries that would cause the expand engine
580
+ // to include ALL concepts from the CodeSystem.
581
+ const hasEnumeratedConcepts = existingInclude.some(
582
+ inc => Array.isArray(inc.concept) && inc.concept.length > 0
583
+ );
584
+ if (hasEnumeratedConcepts) {
585
+ return;
586
+ }
587
+
571
588
  // Always normalize existing compose entries first because discovery metadata
572
589
  // can carry non-canonical preferred_source values.
573
590
  const include = this.#normalizeComposeIncludes(existingInclude);
@@ -972,9 +989,12 @@ class OCLValueSetProvider extends AbstractValueSetProvider {
972
989
  return;
973
990
  }
974
991
 
975
- const cached = this.backgroundExpansionCache.get(cacheKey);
992
+ let cached = this.backgroundExpansionCache.get(cacheKey);
993
+ let invalidated = false;
976
994
  if (cached && !this.#isCachedExpansionValid(vs, cached)) {
977
995
  this.backgroundExpansionCache.delete(cacheKey);
996
+ cached = null;
997
+ invalidated = true;
978
998
  }
979
999
 
980
1000
  // Already have a cached compose ready
@@ -982,23 +1002,22 @@ class OCLValueSetProvider extends AbstractValueSetProvider {
982
1002
  return;
983
1003
  }
984
1004
 
985
- const cacheFilePath = getCacheFilePath(CACHE_VS_DIR, vs.url, vs.version || null, paramsKey);
986
- const cacheAgeFromFileMs = getColdCacheAgeMs(cacheFilePath);
987
- const persistedCache = this.backgroundExpansionCache.get(cacheKey);
988
- const cacheAgeFromMetadataMs = Number.isFinite(persistedCache?.createdAt)
989
- ? Math.max(0, Date.now() - persistedCache.createdAt)
990
- : null;
991
-
992
- // Treat cache as fresh when either file mtime or persisted timestamp is recent.
993
- const freshnessCandidates = [cacheAgeFromFileMs, cacheAgeFromMetadataMs].filter(age => age != null);
994
- const freshestCacheAgeMs = freshnessCandidates.length > 0 ? Math.min(...freshnessCandidates) : null;
995
- if (freshestCacheAgeMs != null && freshestCacheAgeMs <= COLD_CACHE_FRESHNESS_MS) {
996
- const freshnessSource = cacheAgeFromFileMs != null && cacheAgeFromMetadataMs != null
997
- ? 'file+metadata'
998
- : cacheAgeFromFileMs != null
999
- ? 'file'
1000
- : 'metadata';
1001
- return;
1005
+ // Skip freshness check when cache was just invalidated (VS metadata changed
1006
+ // on the server) — the cold cache file is stale even if recently written.
1007
+ if (!invalidated) {
1008
+ const cacheFilePath = getCacheFilePath(CACHE_VS_DIR, vs.url, vs.version || null, paramsKey);
1009
+ const cacheAgeFromFileMs = getColdCacheAgeMs(cacheFilePath);
1010
+ const persistedCache = this.backgroundExpansionCache.get(cacheKey);
1011
+ const cacheAgeFromMetadataMs = Number.isFinite(persistedCache?.createdAt)
1012
+ ? Math.max(0, Date.now() - persistedCache.createdAt)
1013
+ : null;
1014
+
1015
+ // Treat cache as fresh when either file mtime or persisted timestamp is recent.
1016
+ const freshnessCandidates = [cacheAgeFromFileMs, cacheAgeFromMetadataMs].filter(age => age != null);
1017
+ const freshestCacheAgeMs = freshnessCandidates.length > 0 ? Math.min(...freshnessCandidates) : null;
1018
+ if (freshestCacheAgeMs != null && freshestCacheAgeMs <= COLD_CACHE_FRESHNESS_MS) {
1019
+ return;
1020
+ }
1002
1021
  }
1003
1022
 
1004
1023
  const jobKey = `vs:${cacheKey}`;
@@ -1121,7 +1140,11 @@ class OCLValueSetProvider extends AbstractValueSetProvider {
1121
1140
  if (!systemConcepts.has(entry.system)) {
1122
1141
  systemConcepts.set(entry.system, []);
1123
1142
  }
1124
- systemConcepts.get(entry.system).push(entry.code);
1143
+ const concept = { code: entry.code };
1144
+ if (Array.isArray(entry.designation) && entry.designation.length > 0) {
1145
+ concept.designation = entry.designation;
1146
+ }
1147
+ systemConcepts.get(entry.system).push(concept);
1125
1148
  totalCount++;
1126
1149
  }
1127
1150
  if (progressState) {
@@ -1138,9 +1161,9 @@ class OCLValueSetProvider extends AbstractValueSetProvider {
1138
1161
  }
1139
1162
 
1140
1163
  return {
1141
- include: Array.from(systemConcepts.entries()).map(([system, codes]) => ({
1164
+ include: Array.from(systemConcepts.entries()).map(([system, concepts]) => ({
1142
1165
  system,
1143
- concept: codes.map(code => ({ code }))
1166
+ concept: concepts
1144
1167
  }))
1145
1168
  };
1146
1169
  }
@@ -18,11 +18,11 @@ sources:
18
18
  - unii:unii_20240622.db
19
19
  - snomed:sct_intl_20240201.cache
20
20
  - snomed!:sct_intl_20250201.cache
21
- - snomed:sct_se_20231130.cache
22
- - snomed:sct_au_20230731.cache
23
- - snomed:sct_be_20231115.cache
21
+ # - snomed:sct_se_20231130.cache
22
+ # - snomed:sct_au_20230731.cache
23
+ # - snomed:sct_be_20231115.cache
24
24
  - snomed:sct_ch_20230607.cache
25
- - snomed:sct_dk_20250930.cache
25
+ # - snomed:sct_dk_20250930.cache
26
26
  - snomed:sct_ips_20241216.cache
27
27
  - snomed:sct_nl_20240930.cache
28
28
  - snomed:sct_uk_20230412.cache