fhirsmith 0.8.3 → 0.8.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.
@@ -149,57 +149,8 @@ class SearchWorker extends TerminologyWorker {
149
149
  // If no search params, return all
150
150
  const hasSearchParams = Object.keys(searchParams).length > 0;
151
151
 
152
- for (const [key, cs] of this.provider.codeSystems) {
153
- this.deadCheck('searchCodeSystems');
154
-
155
- if (key == cs.vurl) {
156
- const json = cs.jsonObj;
157
-
158
- if (!hasSearchParams) {
159
- matches.push(json);
160
- continue;
161
- }
162
-
163
- // Check each search parameter for partial match
164
- let isMatch = true;
165
- for (const [param, searchValue] of Object.entries(searchParams)) {
166
-
167
- // Map content-mode to content property
168
- const jsonProp = param === 'content-mode' ? 'content' : param;
169
-
170
- if (param === 'jurisdiction') {
171
- // Special handling for jurisdiction - array of CodeableConcept
172
- if (!this.matchJurisdiction(json.jurisdiction, searchValue)) {
173
- isMatch = false;
174
- break;
175
- }
176
- } else if (param === 'text') {
177
- const propValue = json.title + json.description;
178
- if (!this.matchValue(propValue, searchValue)) {
179
- isMatch = false;
180
- break;
181
- }
182
- } else if (param === 'url' || param === 'system') { // exact match
183
- const propValue = json.url;
184
- if (propValue !== searchValue) {
185
- isMatch = false;
186
- break;
187
- }
188
- } else {
189
- // Standard partial text match
190
- const propValue = json[jsonProp];
191
- if (!this.matchValue(propValue, searchValue)) {
192
- isMatch = false;
193
- break;
194
- }
195
- }
196
- }
197
-
198
- if (isMatch) {
199
- matches.push(json);
200
- }
201
- }
202
- }
152
+ this.searchCodeSystemResources(searchParams, hasSearchParams, matches);
153
+ this.searchCodeSystemProviders(searchParams, hasSearchParams, matches);
203
154
 
204
155
  return matches;
205
156
  }
@@ -473,6 +424,130 @@ class SearchWorker extends TerminologyWorker {
473
424
 
474
425
  return filtered;
475
426
  }
427
+
428
+ searchCodeSystemResources(searchParams, hasSearchParams, matches) {
429
+ for (const [key, cs] of this.provider.codeSystems) {
430
+ this.deadCheck('searchCodeSystems');
431
+
432
+ if (key == cs.vurl) {
433
+ const json = cs.jsonObj;
434
+
435
+ if (!hasSearchParams) {
436
+ matches.push(json);
437
+ continue;
438
+ }
439
+
440
+ // Check each search parameter for partial match
441
+ let isMatch = true;
442
+ for (const [param, searchValue] of Object.entries(searchParams)) {
443
+
444
+ // Map content-mode to content property
445
+ const jsonProp = param === 'content-mode' ? 'content' : param;
446
+
447
+ if (param === 'jurisdiction') {
448
+ // Special handling for jurisdiction - array of CodeableConcept
449
+ if (!this.matchJurisdiction(json.jurisdiction, searchValue)) {
450
+ isMatch = false;
451
+ break;
452
+ }
453
+ } else if (param === 'text') {
454
+ const propValue = json.title + json.description;
455
+ if (!this.matchValue(propValue, searchValue)) {
456
+ isMatch = false;
457
+ break;
458
+ }
459
+ } else if (param === 'url' || param === 'system') { // exact match
460
+ const propValue = json.url;
461
+ if (propValue !== searchValue) {
462
+ isMatch = false;
463
+ break;
464
+ }
465
+ } else {
466
+ // Standard partial text match
467
+ const propValue = json[jsonProp];
468
+ if (!this.matchValue(propValue, searchValue)) {
469
+ isMatch = false;
470
+ break;
471
+ }
472
+ }
473
+ }
474
+
475
+ if (isMatch) {
476
+ matches.push(json);
477
+ }
478
+ }
479
+ }
480
+ }
481
+
482
+ searchCodeSystemProviders(searchParams, hasSearchParams, matches) {
483
+ let seen = new Set();
484
+ for (const csp of this.provider.codeSystemFactories.values()) {
485
+ this.deadCheck('searchCodeSystems');
486
+
487
+ if (seen.has(csp.id())) {
488
+ continue;
489
+ }
490
+ seen.add(csp.id());
491
+
492
+ let json = {
493
+ resourceType: "CodeSystem",
494
+ id: "x-" + csp.id(),
495
+ url: csp.system(),
496
+ version: csp.version(),
497
+ name: csp.name(),
498
+ status: "active",
499
+ description: "This is a place holder for the code system which is fully supported through internal means (not by this code system)",
500
+ content: "not-present"
501
+ }
502
+ if (csp.webSource()) {
503
+ json.extension = [{ url: "http://hl7.org/fhir/StructureDefinition/web-source", valueUrl : csp.webSource()}];
504
+ }
505
+
506
+ if (!hasSearchParams) {
507
+ matches.push(json);
508
+ continue;
509
+ }
510
+
511
+ // Check each search parameter for partial match
512
+ let isMatch = true;
513
+ for (const [param, searchValue] of Object.entries(searchParams)) {
514
+
515
+ // Map content-mode to content property
516
+ const jsonProp = param === 'content-mode' ? 'content' : param;
517
+
518
+ if (param === 'jurisdiction') {
519
+ // Special handling for jurisdiction - array of CodeableConcept
520
+ if (!this.matchJurisdiction(json.jurisdiction, searchValue)) {
521
+ isMatch = false;
522
+ break;
523
+ }
524
+ } else if (param === 'text') {
525
+ const propValue = json.title + json.description;
526
+ if (!this.matchValue(propValue, searchValue)) {
527
+ isMatch = false;
528
+ break;
529
+ }
530
+ } else if (param === 'url' || param === 'system') { // exact match
531
+ const propValue = json.url;
532
+ if (propValue !== searchValue) {
533
+ isMatch = false;
534
+ break;
535
+ }
536
+ } else {
537
+ // Standard partial text match
538
+ const propValue = json[jsonProp];
539
+ if (!this.matchValue(propValue, searchValue)) {
540
+ isMatch = false;
541
+ break;
542
+ }
543
+ }
544
+ }
545
+
546
+ if (isMatch) {
547
+ matches.push(json);
548
+ }
549
+ }
550
+ }
476
551
  }
477
552
 
478
553
  module.exports = SearchWorker;
@@ -387,7 +387,7 @@ class TranslateWorker extends TerminologyWorker {
387
387
  }
388
388
  if (!explicit) {
389
389
  matchParts.push({
390
- name: 'sourceMap',
390
+ name: 'originMap',
391
391
  valueCanonical: cm.vurl
392
392
  });
393
393
  }
@@ -476,7 +476,7 @@ class TranslateWorker extends TerminologyWorker {
476
476
  }
477
477
  if (!explicit) {
478
478
  matchParts.push({
479
- name: 'sourceMap',
479
+ name: 'originMap',
480
480
  valueCanonical: cm.vurl
481
481
  });
482
482
  }
@@ -538,7 +538,7 @@ class TranslateWorker extends TerminologyWorker {
538
538
  }
539
539
  if (!explicit) {
540
540
  matchParts.push({
541
- name: 'sourceMap',
541
+ name: 'originMap',
542
542
  valueCanonical: cm.vurl
543
543
  });
544
544
  }
@@ -252,6 +252,7 @@ class TerminologyWorker {
252
252
  loadSupplements(url, version = '', statedSupplements) {
253
253
  const supplements = [];
254
254
 
255
+ supplements.push(...this.provider.loadSupplements(url, version, statedSupplements));
255
256
  // todo: look in provider for supplements
256
257
 
257
258
  if (!this.additionalResources) {
@@ -306,7 +307,7 @@ class TerminologyWorker {
306
307
  * @param {CodeSystemProvider} cs - Code system provider
307
308
  * @param {Object} src - Source element (for extensions)
308
309
  */
309
- checkSupplements(cs, src, requiredSupplements, usedSupplements = null) {
310
+ checkSupplements(cs, src, requiredSupplements, usedSupplements = null, reportedSupplements = null) {
310
311
  // Check for required supplements in extensions
311
312
  if (src && src.extension) {
312
313
  const supplementExtensions = src.extension.filter(x => x.url == 'http://hl7.org/fhir/StructureDefinition/valueset-supplement');
@@ -318,7 +319,12 @@ class TerminologyWorker {
318
319
  }
319
320
  }
320
321
 
321
- // Note required supplements that are satisfied
322
+ if (reportedSupplements) {
323
+ for (let s of cs.listSupplements(true)) {
324
+ reportedSupplements.add(s);
325
+ }
326
+ }
327
+ // Note required supplements that are satisfied - and might be version independent
322
328
  if (usedSupplements) {
323
329
  for (const s of requiredSupplements) {
324
330
  if (cs.hasSupplement(s)) {
@@ -9,11 +9,11 @@ const {VersionUtilities} = require("../../library/version-utilities");
9
9
  */
10
10
 
11
11
  function codeSystemToR5(jsonObj, version) {
12
- if (version === 'R5') {
12
+ if (VersionUtilities.isR5Ver(version)) {
13
13
  return jsonObj; // Already R5, no conversion needed
14
14
  }
15
15
 
16
- if (version === 'R3') {
16
+ if (VersionUtilities.isR3Ver(version)) {
17
17
  // R3 to R5: Convert identifier from single object to array
18
18
  if (jsonObj.identifier && !Array.isArray(jsonObj.identifier)) {
19
19
  jsonObj.identifier = [jsonObj.identifier];
@@ -21,7 +21,7 @@ function codeSystemToR5(jsonObj, version) {
21
21
  return jsonObj;
22
22
  }
23
23
 
24
- if (version === 'R4') {
24
+ if (VersionUtilities.isR4Ver(version)) {
25
25
  // R4 to R5: identifier is already an array, no conversion needed
26
26
  return jsonObj;
27
27
  }
@@ -17,10 +17,10 @@ function parametersToR5(jsonObj, sourceVersion) {
17
17
  }
18
18
  }
19
19
 
20
- const {convertResourceFromR5} = require("./xv-resource");
20
+ const {convertResourceToR5} = require("./xv-resource");
21
21
  for (let p of jsonObj.parameter) {
22
22
  if (p.resource) {
23
- p.resource = convertResourceFromR5(p.resource, sourceVersion);
23
+ p.resource = convertResourceToR5(p.resource, sourceVersion);
24
24
  }
25
25
  }
26
26
  return jsonObj;
@@ -203,8 +203,7 @@ function convertContainsPropertyR5ToR4(containsList) {
203
203
  */
204
204
  function isR5OnlyFilterOperator(operator) {
205
205
  const r5OnlyOperators = [
206
- 'generalizes', // Added in R5
207
- // Add other R5-only operators as they're identified
206
+ 'child-of', ' descendent-leaf' // Added in R5
208
207
  ];
209
208
  return r5OnlyOperators.includes(operator);
210
209
  }