fhirsmith 0.3.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 +42 -0
- package/FHIRsmith.png +0 -0
- package/README.md +277 -0
- package/config-template.json +144 -0
- package/library/folder-setup.js +58 -0
- package/library/html-server.js +166 -0
- package/library/html.js +835 -0
- package/library/i18nsupport.js +259 -0
- package/library/languages.js +779 -0
- package/library/logger-telnet.js +205 -0
- package/library/logger.js +279 -0
- package/library/package-manager.js +876 -0
- package/library/utilities.js +196 -0
- package/library/version-utilities.js +1056 -0
- package/npmprojector/config-example.json +13 -0
- package/npmprojector/indexer.js +394 -0
- package/npmprojector/npmprojector.js +395 -0
- package/npmprojector/readme.md +174 -0
- package/npmprojector/watcher.js +335 -0
- package/package.json +119 -0
- package/packages/package-crawler.js +846 -0
- package/packages/packages-template.html +126 -0
- package/packages/packages.js +2838 -0
- package/passwords.ini +2 -0
- package/publisher/publisher-template.html +208 -0
- package/publisher/publisher.js +2167 -0
- package/publisher/task-draft.js +458 -0
- package/registry/api.js +735 -0
- package/registry/crawler.js +637 -0
- package/registry/model.js +513 -0
- package/registry/readme.md +243 -0
- package/registry/registry-data.json +121015 -0
- package/registry/registry-template.html +126 -0
- package/registry/registry.js +1395 -0
- package/registry/test-runner.js +237 -0
- package/root-template.html +124 -0
- package/server.js +524 -0
- package/shl/private-key.pem +5 -0
- package/shl/public-key.pem +18 -0
- package/shl/shl.js +1125 -0
- package/shl/vhl.js +69 -0
- package/static/FHIRsmith128.png +0 -0
- package/static/FHIRsmith16.png +0 -0
- package/static/FHIRsmith32.png +0 -0
- package/static/FHIRsmith64.png +0 -0
- package/static/assets/css/bootstrap-fhir.css +5302 -0
- package/static/assets/css/bootstrap-glyphicons.css +2 -0
- package/static/assets/css/bootstrap.css +4097 -0
- package/static/assets/css/jquery-ui.css +523 -0
- package/static/assets/css/jquery-ui.structure.css +863 -0
- package/static/assets/css/jquery-ui.structure.min.css +5 -0
- package/static/assets/css/jquery-ui.theme.css +439 -0
- package/static/assets/css/jquery-ui.theme.min.css +5 -0
- package/static/assets/css/jquery.ui.all.css +7 -0
- package/static/assets/css/modules.css +18 -0
- package/static/assets/css/project.css +367 -0
- package/static/assets/css/pygments-manni.css +66 -0
- package/static/assets/css/tags.css +74 -0
- package/static/assets/css/xml.css +2 -0
- package/static/assets/fonts/glyphiconshalflings-regular.eot +0 -0
- package/static/assets/fonts/glyphiconshalflings-regular.otf +0 -0
- package/static/assets/fonts/glyphiconshalflings-regular.svg +175 -0
- package/static/assets/fonts/glyphiconshalflings-regular.ttf +0 -0
- package/static/assets/fonts/glyphiconshalflings-regular.woff +0 -0
- package/static/assets/ico/apple-touch-icon-114-precomposed.png +0 -0
- package/static/assets/ico/apple-touch-icon-144-precomposed.png +0 -0
- package/static/assets/ico/apple-touch-icon-57-precomposed.png +0 -0
- package/static/assets/ico/apple-touch-icon-72-precomposed.png +0 -0
- package/static/assets/ico/favicon.ico +0 -0
- package/static/assets/ico/favicon.png +0 -0
- package/static/assets/images/fhir-logo-www.png +0 -0
- package/static/assets/images/fhir-logo.png +0 -0
- package/static/assets/images/hl7-logo.png +0 -0
- package/static/assets/images/logo_ansinew.jpg +0 -0
- package/static/assets/images/search.png +0 -0
- package/static/assets/images/stripe.png +0 -0
- package/static/assets/images/target.png +0 -0
- package/static/assets/images/tx-registry-root.gif +0 -0
- package/static/assets/images/tx-registry.png +0 -0
- package/static/assets/images/tx-server.png +0 -0
- package/static/assets/images/tx-version.png +0 -0
- package/static/assets/js/bootstrap.min.js +6 -0
- package/static/assets/js/fhir-gw.js +259 -0
- package/static/assets/js/fhir.js +2 -0
- package/static/assets/js/html5shiv.js +8 -0
- package/static/assets/js/jcookie.js +96 -0
- package/static/assets/js/jquery-ui.min.js +6 -0
- package/static/assets/js/jquery.js +10716 -0
- package/static/assets/js/jquery.min.js +2 -0
- package/static/assets/js/jquery.ui.core.js +314 -0
- package/static/assets/js/jquery.ui.draggable.js +825 -0
- package/static/assets/js/jquery.ui.mouse.js +162 -0
- package/static/assets/js/jquery.ui.resizable.js +842 -0
- package/static/assets/js/jquery.ui.widget.js +268 -0
- package/static/assets/js/json2.js +487 -0
- package/static/assets/js/jtip.js +97 -0
- package/static/assets/js/respond.min.js +6 -0
- package/static/assets/js/statuspage.js +70 -0
- package/static/assets/js/xml.js +2 -0
- package/static/dist/js/bootstrap.js +1964 -0
- package/static/favicon.png +0 -0
- package/static/fhir.css +626 -0
- package/static/icon-fhir-16.png +0 -0
- package/static/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- package/static/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- package/static/images/ui-bg_flat_10_000000_40x100.png +0 -0
- package/static/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- package/static/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- package/static/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- package/static/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- package/static/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- package/static/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- package/static/images/ui-icons_222222_256x240.png +0 -0
- package/static/images/ui-icons_228ef1_256x240.png +0 -0
- package/static/images/ui-icons_ef8c08_256x240.png +0 -0
- package/static/images/ui-icons_ffd27a_256x240.png +0 -0
- package/static/images/ui-icons_ffffff_256x240.png +0 -0
- package/static/js/jquery.effects.blind.js +49 -0
- package/static/js/jquery.effects.bounce.js +78 -0
- package/static/js/jquery.effects.clip.js +54 -0
- package/static/js/jquery.effects.core.js +763 -0
- package/static/js/jquery.effects.drop.js +50 -0
- package/static/js/jquery.effects.explode.js +79 -0
- package/static/js/jquery.effects.fade.js +32 -0
- package/static/js/jquery.effects.fold.js +56 -0
- package/static/js/jquery.effects.highlight.js +50 -0
- package/static/js/jquery.effects.pulsate.js +51 -0
- package/static/js/jquery.effects.scale.js +178 -0
- package/static/js/jquery.effects.shake.js +57 -0
- package/static/js/jquery.effects.slide.js +50 -0
- package/static/js/jquery.effects.transfer.js +45 -0
- package/static/js/jquery.ui.accordion.js +611 -0
- package/static/js/jquery.ui.autocomplete.js +612 -0
- package/static/js/jquery.ui.button.js +416 -0
- package/static/js/jquery.ui.datepicker.js +1823 -0
- package/static/js/jquery.ui.dialog.js +878 -0
- package/static/js/jquery.ui.droppable.js +296 -0
- package/static/js/jquery.ui.position.js +252 -0
- package/static/js/jquery.ui.progressbar.js +109 -0
- package/static/js/jquery.ui.selectable.js +266 -0
- package/static/js/jquery.ui.slider.js +666 -0
- package/static/js/jquery.ui.sortable.js +1077 -0
- package/static/js/jquery.ui.tabs.js +758 -0
- package/stats.js +80 -0
- package/test-cache/vsac/vsac-valuesets.db +0 -0
- package/token/nginx_passport_setup.md +383 -0
- package/token/security_guide.md +294 -0
- package/token/token-template.html +330 -0
- package/token/token.js +1300 -0
- package/translations/Messages.properties +1510 -0
- package/translations/Messages_ar.properties +1399 -0
- package/translations/Messages_de.properties +836 -0
- package/translations/Messages_es.properties +737 -0
- package/translations/Messages_fr.properties +1 -0
- package/translations/Messages_ja.properties +893 -0
- package/translations/Messages_nl.properties +1357 -0
- package/translations/Messages_pt.properties +1302 -0
- package/translations/Messages_ru.properties +1 -0
- package/translations/Messages_uz.properties +1 -0
- package/translations/Messages_zh.properties +1 -0
- package/translations/rendering-phrases.properties +1128 -0
- package/translations/rendering-phrases_ar.properties +1091 -0
- package/translations/rendering-phrases_de.properties +6 -0
- package/translations/rendering-phrases_es.properties +6 -0
- package/translations/rendering-phrases_fr.properties +624 -0
- package/translations/rendering-phrases_ja.properties +21 -0
- package/translations/rendering-phrases_nl.properties +970 -0
- package/translations/rendering-phrases_pt.properties +1020 -0
- package/translations/rendering-phrases_ru.properties +1094 -0
- package/translations/rendering-phrases_uz.properties +1 -0
- package/translations/rendering-phrases_zh.properties +1 -0
- package/tx/README.md +418 -0
- package/tx/cm/cm-api.js +110 -0
- package/tx/cm/cm-database.js +735 -0
- package/tx/cm/cm-package.js +325 -0
- package/tx/cs/cs-api.js +789 -0
- package/tx/cs/cs-areacode.js +615 -0
- package/tx/cs/cs-country.js +1110 -0
- package/tx/cs/cs-cpt.js +785 -0
- package/tx/cs/cs-cs.js +1579 -0
- package/tx/cs/cs-currency.js +539 -0
- package/tx/cs/cs-db.js +1321 -0
- package/tx/cs/cs-hgvs.js +329 -0
- package/tx/cs/cs-lang.js +465 -0
- package/tx/cs/cs-loinc.js +1485 -0
- package/tx/cs/cs-mimetypes.js +238 -0
- package/tx/cs/cs-ndc.js +704 -0
- package/tx/cs/cs-omop.js +1025 -0
- package/tx/cs/cs-provider-api.js +43 -0
- package/tx/cs/cs-provider-list.js +37 -0
- package/tx/cs/cs-rxnorm.js +808 -0
- package/tx/cs/cs-snomed.js +1102 -0
- package/tx/cs/cs-ucum.js +514 -0
- package/tx/cs/cs-unii.js +271 -0
- package/tx/cs/cs-uri.js +218 -0
- package/tx/cs/cs-usstates.js +305 -0
- package/tx/dev.fhir.org.yml +14 -0
- package/tx/fixtures/test-cases-setup.json +18 -0
- package/tx/fixtures/test-cases.yml +16 -0
- package/tx/html/codesystem-operations.liquid +25 -0
- package/tx/html/home-metrics.liquid +247 -0
- package/tx/html/operations-form.liquid +148 -0
- package/tx/html/search-form.liquid +62 -0
- package/tx/html/tx-template.html +133 -0
- package/tx/html/valueset-operations.liquid +54 -0
- package/tx/importers/atc-to-fhir.js +316 -0
- package/tx/importers/import-loinc.module.js +1536 -0
- package/tx/importers/import-ndc.module.js +1088 -0
- package/tx/importers/import-rxnorm.module.js +898 -0
- package/tx/importers/import-sct.module.js +2457 -0
- package/tx/importers/import-unii.module.js +601 -0
- package/tx/importers/readme.md +453 -0
- package/tx/importers/subset-loinc.module.js +1081 -0
- package/tx/importers/subset-rxnorm.module.js +938 -0
- package/tx/importers/tx-import-base.js +351 -0
- package/tx/importers/tx-import-settings.js +310 -0
- package/tx/importers/tx-import.js +357 -0
- package/tx/library/canonical-resource.js +88 -0
- package/tx/library/capabilitystatement.js +292 -0
- package/tx/library/codesystem.js +774 -0
- package/tx/library/conceptmap.js +568 -0
- package/tx/library/designations.js +932 -0
- package/tx/library/errors.js +77 -0
- package/tx/library/extensions.js +117 -0
- package/tx/library/namingsystem.js +322 -0
- package/tx/library/operation-outcome.js +127 -0
- package/tx/library/parameters.js +105 -0
- package/tx/library/renderer.js +1559 -0
- package/tx/library/terminologycapabilities.js +418 -0
- package/tx/library/ucum-parsers.js +1029 -0
- package/tx/library/ucum-service.js +370 -0
- package/tx/library/ucum-types.js +1099 -0
- package/tx/library/valueset.js +543 -0
- package/tx/library.js +676 -0
- package/tx/ocl/cm-ocl.js +106 -0
- package/tx/ocl/cs-ocl.js +39 -0
- package/tx/ocl/vs-ocl.js +105 -0
- package/tx/operation-context.js +568 -0
- package/tx/params.js +613 -0
- package/tx/provider.js +403 -0
- package/tx/sct/ecl.js +1560 -0
- package/tx/sct/expressions.js +2077 -0
- package/tx/sct/structures.js +1396 -0
- package/tx/tx-html.js +1063 -0
- package/tx/tx.fhir.org.yml +39 -0
- package/tx/tx.js +927 -0
- package/tx/vs/vs-api.js +112 -0
- package/tx/vs/vs-database.js +786 -0
- package/tx/vs/vs-package.js +358 -0
- package/tx/vs/vs-vsac.js +366 -0
- package/tx/workers/batch-validate.js +129 -0
- package/tx/workers/batch.js +361 -0
- package/tx/workers/closure.js +32 -0
- package/tx/workers/expand.js +1845 -0
- package/tx/workers/lookup.js +407 -0
- package/tx/workers/metadata.js +467 -0
- package/tx/workers/operations.js +34 -0
- package/tx/workers/read.js +164 -0
- package/tx/workers/search.js +384 -0
- package/tx/workers/subsumes.js +334 -0
- package/tx/workers/translate.js +492 -0
- package/tx/workers/validate.js +2504 -0
- package/tx/workers/worker.js +904 -0
- package/tx/xml/capabilitystatement-xml.js +63 -0
- package/tx/xml/codesystem-xml.js +62 -0
- package/tx/xml/conceptmap-xml.js +65 -0
- package/tx/xml/namingsystem-xml.js +65 -0
- package/tx/xml/operationoutcome-xml.js +127 -0
- package/tx/xml/parameters-xml.js +312 -0
- package/tx/xml/terminologycapabilities-xml.js +64 -0
- package/tx/xml/valueset-xml.js +64 -0
- package/tx/xml/xml-base.js +603 -0
- package/vcl/vcl-parser.js +1098 -0
- package/vcl/vcl.js +253 -0
- package/windows-install.js +19 -0
- package/xig/xig-template.html +124 -0
- package/xig/xig.js +3049 -0
package/tx/library.js
ADDED
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
const fs = require('fs').promises;
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const yaml = require('yaml'); // npm install yaml
|
|
4
|
+
const { PackageManager, PackageContentLoader } = require('../library/package-manager');
|
|
5
|
+
const { CodeSystem } = require("./library/codesystem");
|
|
6
|
+
const {CountryCodeFactoryProvider} = require("./cs/cs-country");
|
|
7
|
+
const {Iso4217FactoryProvider} = require("./cs/cs-currency");
|
|
8
|
+
const {AreaCodeFactoryProvider} = require("./cs/cs-areacode");
|
|
9
|
+
const {MimeTypeServicesFactory} = require("./cs/cs-mimetypes");
|
|
10
|
+
const {USStateFactoryProvider} = require("./cs/cs-usstates");
|
|
11
|
+
const {HGVSServicesFactory} = require("./cs/cs-hgvs");
|
|
12
|
+
const {UcumCodeSystemFactory} = require("./cs/cs-ucum");
|
|
13
|
+
const {UcumService} = require("./library/ucum-service");
|
|
14
|
+
const {readFileSync} = require("fs");
|
|
15
|
+
const https = require('https');
|
|
16
|
+
const http = require('http');
|
|
17
|
+
const {LoincServicesFactory} = require("./cs/cs-loinc");
|
|
18
|
+
const {RxNormServicesFactory} = require("./cs/cs-rxnorm");
|
|
19
|
+
const {NdcServicesFactory} = require("./cs/cs-ndc");
|
|
20
|
+
const {UniiServicesFactory} = require("./cs/cs-unii");
|
|
21
|
+
const {SnomedServicesFactory} = require("./cs/cs-snomed");
|
|
22
|
+
const {CPTServicesFactory} = require("./cs/cs-cpt");
|
|
23
|
+
const {OMOPServicesFactory} = require("./cs/cs-omop");
|
|
24
|
+
const {PackageValueSetProvider} = require("./vs/vs-package");
|
|
25
|
+
const {PackageConceptMapProvider} = require("./cm/cm-package");
|
|
26
|
+
const {IETFLanguageCodeFactory} = require("./cs/cs-lang");
|
|
27
|
+
const {LanguageDefinitions} = require("../library/languages");
|
|
28
|
+
const {VersionUtilities} = require("../library/version-utilities");
|
|
29
|
+
const {ListCodeSystemProvider} = require("./cs/cs-provider-list");
|
|
30
|
+
const { Provider } = require("./provider");
|
|
31
|
+
const {I18nSupport} = require("../library/i18nsupport");
|
|
32
|
+
const folders = require('../library/folder-setup');
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* This class holds all the loaded content ready for processing
|
|
36
|
+
*
|
|
37
|
+
* At the start of every service call, this is turned into a
|
|
38
|
+
* provider structure that holds what's actually in context,
|
|
39
|
+
* based on the stated FHIR version, and the other (optional) context information
|
|
40
|
+
*
|
|
41
|
+
*/
|
|
42
|
+
class Library {
|
|
43
|
+
/**
|
|
44
|
+
* {Map<String, CodeSystemFactoryProvider>} A list of code system factories that contains all the preloaded native code systems
|
|
45
|
+
*/
|
|
46
|
+
codeSystemFactories;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* {Lisr<AbstractCodeSystemProvider>} A list of preloaded FHIR code systems
|
|
50
|
+
*/
|
|
51
|
+
codeSystemProviders;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* {List<AbstractValueSetProvider>} A list of value set providers that know how to provide value sets by request
|
|
55
|
+
*/
|
|
56
|
+
valueSetProviders;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* {List<AbstractConceptMapProvider>} A list of value set providers that know how to provide value sets by request
|
|
60
|
+
*/
|
|
61
|
+
conceptMapProviders;
|
|
62
|
+
|
|
63
|
+
contentSources = [];
|
|
64
|
+
|
|
65
|
+
baseUrl = null;
|
|
66
|
+
cacheFolder = null;
|
|
67
|
+
startTime = Date.now();
|
|
68
|
+
startMemory = process.memoryUsage();
|
|
69
|
+
lastTime = null;
|
|
70
|
+
totalDownloaded = 0;
|
|
71
|
+
|
|
72
|
+
registerProvider(source, factory, isDefault = false) {
|
|
73
|
+
this.#logSystem(factory.system(), factory.version(), source);
|
|
74
|
+
if (isDefault || !this.codeSystemFactories.has(factory.system())) {
|
|
75
|
+
this.codeSystemFactories.set(factory.system(), factory);
|
|
76
|
+
}
|
|
77
|
+
const ver = factory.version() ?? "";
|
|
78
|
+
this.codeSystemFactories.set(factory.system()+"|"+ver, factory);
|
|
79
|
+
const verMin = factory.getPartialVersion();
|
|
80
|
+
if (verMin) {
|
|
81
|
+
this.codeSystemFactories.set(factory.system()+"|"+verMin, factory);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
constructor(configFile, log) {
|
|
86
|
+
this.configFile = configFile;
|
|
87
|
+
this.log = log;
|
|
88
|
+
// Only synchronous initialization here
|
|
89
|
+
this.codeSystemFactories = new Map();
|
|
90
|
+
this.codeSystemProviders = [];
|
|
91
|
+
this.valueSetProviders = [];
|
|
92
|
+
this.conceptMapProviders = [];
|
|
93
|
+
|
|
94
|
+
// Create package manager for FHIR packages
|
|
95
|
+
const packageServers = ['https://packages2.fhir.org/packages'];
|
|
96
|
+
this.cacheFolder = folders.subDir('terminology-cache'); // <-- CHANGE
|
|
97
|
+
this.packageManager = new PackageManager(packageServers, this.cacheFolder);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#logSystemHeader() {
|
|
101
|
+
let time = "Time".padEnd(6);
|
|
102
|
+
// let memory = " MB".padEnd(6);
|
|
103
|
+
let system = "System".padEnd(50);
|
|
104
|
+
let version = "Version".padEnd(62);
|
|
105
|
+
let source = "Source"
|
|
106
|
+
this.log.info(`${time}${system}${version}${source}`);
|
|
107
|
+
this.lastTime = Date.now();
|
|
108
|
+
// this.lastMemory = process.memoryUsage();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#logSystem(url, ver, source) {
|
|
112
|
+
//const mem = process.memoryUsage();
|
|
113
|
+
let time = Math.floor(Date.now() - this.lastTime).toString().padStart(5)+" ";
|
|
114
|
+
let system = url.padEnd(50);
|
|
115
|
+
let version = (ver == null ? "" : ver).padEnd(62);
|
|
116
|
+
this.log.info(`${time}${system}${version}${source}`);
|
|
117
|
+
this.lastTime = Date.now();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#logPackagesHeader() {
|
|
121
|
+
let time = "Time".padEnd(6);
|
|
122
|
+
//let memory = " MB".padEnd(6);
|
|
123
|
+
let id = "ID".padEnd(20);
|
|
124
|
+
let ver = "Version".padEnd(20);
|
|
125
|
+
let cs = "CS".padEnd(6);
|
|
126
|
+
let vs = "VS".padEnd(6);
|
|
127
|
+
this.log.info(`${time}${id}${ver}${cs}${vs}`);
|
|
128
|
+
this.lastTime = Date.now();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#logPackage(idp, verp, csp, vsp) {
|
|
132
|
+
let time = Math.floor(Date.now() - this.lastTime).toString().padStart(5)+" ";
|
|
133
|
+
let id = idp.padEnd(20);
|
|
134
|
+
let ver = verp.padEnd(20);
|
|
135
|
+
let cs = csp.toString().padEnd(6);
|
|
136
|
+
let vs = vsp.toString().padEnd(6);
|
|
137
|
+
this.log.info(`${time}${id}${ver}${cs}${vs}`);
|
|
138
|
+
this.lastTime = Date.now();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async load() {
|
|
142
|
+
this.startTime = Date.now();
|
|
143
|
+
this.languageDefinitions = await LanguageDefinitions.fromFile(path.join(__dirname, '../tx/data/lang.dat'));
|
|
144
|
+
this.i18n = new I18nSupport(path.join(__dirname, '../translations'), this.languageDefinitions);
|
|
145
|
+
await this.i18n.load();
|
|
146
|
+
|
|
147
|
+
// Read and parse YAML configuration
|
|
148
|
+
const yamlPath = this.configFile ? this.configFile : path.join(__dirname, '..', 'tx', 'tx.fhir.org.yml');
|
|
149
|
+
const yamlContent = await fs.readFile(yamlPath, 'utf8');
|
|
150
|
+
const config = yaml.parse(yamlContent);
|
|
151
|
+
this.baseUrl = config.base.url;
|
|
152
|
+
|
|
153
|
+
this.log.info('Fetching Data from '+this.baseUrl);
|
|
154
|
+
|
|
155
|
+
for (const source of config.sources) {
|
|
156
|
+
await this.processSource(source, this.packageManager, "fetch");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this.log.info("Downloaded "+((this.totalDownloaded + this.packageManager.totalDownloaded)/ 1024)+" kB");
|
|
160
|
+
|
|
161
|
+
this.log.info('Loading Code Systems');
|
|
162
|
+
this.#logSystemHeader();
|
|
163
|
+
|
|
164
|
+
for (const source of config.sources) {
|
|
165
|
+
await this.processSource(source, this.packageManager, "cs");
|
|
166
|
+
}
|
|
167
|
+
this.log.info('Loading Packages');
|
|
168
|
+
this.#logPackagesHeader();
|
|
169
|
+
|
|
170
|
+
for (const source of config.sources) {
|
|
171
|
+
await this.processSource(source, this.packageManager, "npm");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const endMemory = process.memoryUsage();
|
|
175
|
+
const totalTime = Date.now() - this.startTime;
|
|
176
|
+
|
|
177
|
+
const memoryIncrease = {
|
|
178
|
+
rss: endMemory.rss - this.startMemory.rss,
|
|
179
|
+
heapUsed: endMemory.heapUsed - this.startMemory.heapUsed,
|
|
180
|
+
heapTotal: endMemory.heapTotal - this.startMemory.heapTotal,
|
|
181
|
+
external: endMemory.external - this.startMemory.external
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
this.log.info(`Loading Time: ${(totalTime / 1000).toLocaleString()}s`);
|
|
185
|
+
this.log.info(`Memory Used: ${(memoryIncrease.rss / 1024 / 1024).toFixed(2)} MB`);
|
|
186
|
+
|
|
187
|
+
this.assignIds();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async processSource(source, packageManager, mode) {
|
|
191
|
+
// Parse the source string
|
|
192
|
+
const colonIndex = source.indexOf(':');
|
|
193
|
+
if (colonIndex === -1) {
|
|
194
|
+
throw new Error(`Invalid source format: ${source}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
let type = source.substring(0, colonIndex);
|
|
198
|
+
const details = source.substring(colonIndex + 1);
|
|
199
|
+
|
|
200
|
+
// Handle special markers (like ! for default)
|
|
201
|
+
let isDefault = false;
|
|
202
|
+
if (type.endsWith('!')) {
|
|
203
|
+
type = type.slice(0, -1);
|
|
204
|
+
isDefault = true;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Switch statement for different source types
|
|
208
|
+
switch (type) {
|
|
209
|
+
case 'internal':
|
|
210
|
+
await this.loadInternal(details, isDefault, mode);
|
|
211
|
+
break;
|
|
212
|
+
|
|
213
|
+
case 'ucum':
|
|
214
|
+
await this.loadUcum(details, isDefault, mode);
|
|
215
|
+
break;
|
|
216
|
+
|
|
217
|
+
case 'loinc':
|
|
218
|
+
await this.loadLoinc(details, isDefault, mode);
|
|
219
|
+
break;
|
|
220
|
+
|
|
221
|
+
case 'rxnorm':
|
|
222
|
+
await this.loadRxnorm(details, isDefault, mode);
|
|
223
|
+
break;
|
|
224
|
+
|
|
225
|
+
case 'ndc':
|
|
226
|
+
await this.loadNdc(details, isDefault, mode);
|
|
227
|
+
break;
|
|
228
|
+
|
|
229
|
+
case 'unii':
|
|
230
|
+
await this.loadUnii(details, isDefault, mode);
|
|
231
|
+
break;
|
|
232
|
+
|
|
233
|
+
case 'snomed':
|
|
234
|
+
await this.loadSnomed(details, isDefault, mode);
|
|
235
|
+
break;
|
|
236
|
+
|
|
237
|
+
case 'cpt':
|
|
238
|
+
await this.loadCpt(details, isDefault, mode);
|
|
239
|
+
break;
|
|
240
|
+
|
|
241
|
+
case 'omop':
|
|
242
|
+
await this.loadOmop(details, isDefault, mode);
|
|
243
|
+
break;
|
|
244
|
+
|
|
245
|
+
case 'npm':
|
|
246
|
+
await this.loadNpm(packageManager, details, isDefault, mode);
|
|
247
|
+
break;
|
|
248
|
+
|
|
249
|
+
default:
|
|
250
|
+
throw new Error(`Unknown source type: ${type}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async loadInternal(details, isDefault, mode) {
|
|
255
|
+
if (isDefault) {
|
|
256
|
+
throw new Error("Default is not supported for internal code system providers");
|
|
257
|
+
}
|
|
258
|
+
if (mode === "fetch" || mode === "npm") {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
switch (details) {
|
|
262
|
+
case "country" : {
|
|
263
|
+
const cc = new CountryCodeFactoryProvider(this.i18n);
|
|
264
|
+
await cc.load();
|
|
265
|
+
this.registerProvider('internal', cc);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case "lang" : {
|
|
269
|
+
const langs = new IETFLanguageCodeFactory(this.i18n);
|
|
270
|
+
await langs.load();
|
|
271
|
+
this.registerProvider('internal', langs);
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
case "currency" : {
|
|
275
|
+
const curr = new Iso4217FactoryProvider(this.i18n);
|
|
276
|
+
await curr.load();
|
|
277
|
+
this.registerProvider('internal', curr);
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
case "areacode" : {
|
|
281
|
+
const ac = new AreaCodeFactoryProvider(this.i18n);
|
|
282
|
+
await ac.load();
|
|
283
|
+
this.registerProvider('internal', ac);
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
case "mimetypes" : {
|
|
287
|
+
const mime = new MimeTypeServicesFactory(this.i18n);
|
|
288
|
+
await mime.load();
|
|
289
|
+
this.registerProvider('internal', mime);
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
case "usstates" : {
|
|
293
|
+
const uss = new USStateFactoryProvider(this.i18n);
|
|
294
|
+
await uss.load();
|
|
295
|
+
this.registerProvider('internal', uss);
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
case "hgvs" : {
|
|
299
|
+
const hgvs = new HGVSServicesFactory(this.i18n);
|
|
300
|
+
await hgvs.load();
|
|
301
|
+
this.registerProvider('internal', hgvs);
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
default:
|
|
305
|
+
throw new Error("Unknown Internal Provider "+details);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async loadUcum(details, isDefault, mode) {
|
|
310
|
+
if (mode === "fetch" || mode === "npm") {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const source = path.join(__dirname, '..', details);
|
|
314
|
+
|
|
315
|
+
const ucumEssenceXml = readFileSync(source, 'utf8');
|
|
316
|
+
const ucumService = new UcumService();
|
|
317
|
+
await ucumService.init(ucumEssenceXml);
|
|
318
|
+
|
|
319
|
+
const ucum = new UcumCodeSystemFactory(this.i18n, ucumService);
|
|
320
|
+
await ucum.load();
|
|
321
|
+
this.registerProvider(source, ucum, isDefault);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
async loadLoinc(details, isDefault, mode) {
|
|
325
|
+
const loincFN = await this.getOrDownloadFile(details);
|
|
326
|
+
if (mode === "fetch" || mode === "npm") {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const loinc = new LoincServicesFactory(this.i18n, loincFN);
|
|
331
|
+
await loinc.load();
|
|
332
|
+
this.registerProvider(loincFN, loinc, isDefault);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async loadRxnorm(details, isDefault, mode) {
|
|
336
|
+
const rxNormFN = await this.getOrDownloadFile(details);
|
|
337
|
+
if (mode === "fetch" || mode === "npm") {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
const rxn = new RxNormServicesFactory(this.i18n, rxNormFN);
|
|
341
|
+
await rxn.load();
|
|
342
|
+
this.registerProvider(rxNormFN, rxn, isDefault);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
async loadNdc(details, isDefault, mode) {
|
|
346
|
+
const ndcFN = await this.getOrDownloadFile(details);
|
|
347
|
+
if (mode === "fetch" || mode === "npm") {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const ndc = new NdcServicesFactory(this.i18n, ndcFN);
|
|
351
|
+
await ndc.load();
|
|
352
|
+
this.registerProvider(ndcFN, ndc, isDefault);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
async loadUnii(details, isDefault, mode) {
|
|
356
|
+
const uniFN = await this.getOrDownloadFile(details);
|
|
357
|
+
if (mode === "fetch" || mode === "npm") {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
const unii = new UniiServicesFactory(this.i18n, uniFN);
|
|
361
|
+
await unii.load();
|
|
362
|
+
this.registerProvider(uniFN, unii, isDefault);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async loadSnomed(details, isDefault, mode) {
|
|
366
|
+
const sctFN = await this.getOrDownloadFile(details);
|
|
367
|
+
if (mode === "fetch" || mode === "npm") {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const sct = new SnomedServicesFactory(this.i18n, sctFN);
|
|
371
|
+
await sct.load();
|
|
372
|
+
this.registerProvider(sctFN, sct, isDefault);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
async loadCpt(details, isDefault, mode) {
|
|
376
|
+
const cptFN = await this.getOrDownloadFile(details);
|
|
377
|
+
if (mode === "fetch" || mode === "npm") {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const cpt = new CPTServicesFactory(this.i18n, cptFN);
|
|
381
|
+
await cpt.load();
|
|
382
|
+
this.registerProvider(cptFN, cpt, isDefault);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
async loadOmop(details, isDefault, mode) {
|
|
386
|
+
const omopFN = await this.getOrDownloadFile(details);
|
|
387
|
+
if (mode === "fetch" || mode === "npm") {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
const omop = new OMOPServicesFactory(this.i18n, omopFN);
|
|
391
|
+
await omop.load();
|
|
392
|
+
this.registerProvider(omopFN, omop, isDefault);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
async loadNpm(packageManager, details, isDefault, mode) {
|
|
396
|
+
// Parse packageId and version from details (e.g., "hl7.terminology.r4#6.0.2")
|
|
397
|
+
let packageId = details;
|
|
398
|
+
let version = null;
|
|
399
|
+
if (details.includes('#')) {
|
|
400
|
+
const parts = details.split('#');
|
|
401
|
+
packageId = parts[0];
|
|
402
|
+
version = parts[1];
|
|
403
|
+
}
|
|
404
|
+
const packagePath = await packageManager.fetch(packageId, version);
|
|
405
|
+
if (mode === "fetch" || mode === "cs") {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
const fullPackagePath = path.join(this.cacheFolder, packagePath);
|
|
409
|
+
const contentLoader = new PackageContentLoader(fullPackagePath);
|
|
410
|
+
await contentLoader.initialize();
|
|
411
|
+
|
|
412
|
+
this.contentSources.push(contentLoader.id()+"#"+contentLoader.version());
|
|
413
|
+
|
|
414
|
+
let cp = new ListCodeSystemProvider();
|
|
415
|
+
const resources = await contentLoader.getResourcesByType("CodeSystem");
|
|
416
|
+
let csc = 0;
|
|
417
|
+
for (const resource of resources) {
|
|
418
|
+
const cs = new CodeSystem(await contentLoader.loadFile(resource, contentLoader.fhirVersion()));
|
|
419
|
+
cs.sourcePackage = contentLoader.pid();
|
|
420
|
+
cp.codeSystems.set(cs.url, cs);
|
|
421
|
+
cp.codeSystems.set(cs.vurl, cs);
|
|
422
|
+
csc++;
|
|
423
|
+
}
|
|
424
|
+
this.codeSystemProviders.push(cp);
|
|
425
|
+
const vs = new PackageValueSetProvider(contentLoader);
|
|
426
|
+
await vs.initialize();
|
|
427
|
+
this.valueSetProviders.push(vs);
|
|
428
|
+
const cm = new PackageConceptMapProvider(contentLoader);
|
|
429
|
+
await cm.initialize();
|
|
430
|
+
this.conceptMapProviders.push(cm);
|
|
431
|
+
|
|
432
|
+
this.#logPackage(contentLoader.id(), contentLoader.version(), csc, vs.valueSetMap.size);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Gets a file from local folder or downloads it from URL
|
|
437
|
+
* @param {string} fileName - Name of the file
|
|
438
|
+
* @returns {Promise<string>} Full path to the file
|
|
439
|
+
* @throws {Error} If file cannot be downloaded or accessed
|
|
440
|
+
*/
|
|
441
|
+
async getOrDownloadFile(fileName) {
|
|
442
|
+
// Ensure folder exists
|
|
443
|
+
await this.ensureFolderExists(this.cacheFolder);
|
|
444
|
+
|
|
445
|
+
const filePath = path.join(this.cacheFolder, fileName);
|
|
446
|
+
|
|
447
|
+
// Check if file already exists
|
|
448
|
+
if (await this.fileExists(filePath)) {
|
|
449
|
+
return filePath;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// File doesn't exist, download it
|
|
453
|
+
this.log.info(`Downloading: ${fileName}`);
|
|
454
|
+
|
|
455
|
+
const downloadUrl = this.baseUrl.endsWith('/') ? this.baseUrl + fileName : this.baseUrl + '/' + fileName;
|
|
456
|
+
|
|
457
|
+
try {
|
|
458
|
+
await this.downloadFile(downloadUrl, filePath);
|
|
459
|
+
return filePath;
|
|
460
|
+
} catch (error) {
|
|
461
|
+
throw new Error(`Failed to download file ${fileName} from ${downloadUrl}: ${error.message}`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Check if a file exists
|
|
467
|
+
* @param {string} filePath - Path to check
|
|
468
|
+
* @returns {Promise<boolean>} True if file exists
|
|
469
|
+
*/
|
|
470
|
+
async fileExists(filePath) {
|
|
471
|
+
try {
|
|
472
|
+
await fs.access(filePath);
|
|
473
|
+
return true;
|
|
474
|
+
} catch {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Ensure a folder exists, create it if it doesn't
|
|
481
|
+
* @param {string} folderPath - Path to folder
|
|
482
|
+
*/
|
|
483
|
+
async ensureFolderExists(folderPath) {
|
|
484
|
+
try {
|
|
485
|
+
await fs.mkdir(folderPath, { recursive: true });
|
|
486
|
+
} catch (error) {
|
|
487
|
+
if (error.code !== 'EEXIST') {
|
|
488
|
+
throw new Error(`Failed to create folder ${folderPath}: ${error.message}`);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Download a file from URL to local path
|
|
495
|
+
* @param {string} url - URL to download from
|
|
496
|
+
* @param {string} filePath - Local path to save file
|
|
497
|
+
* @returns {Promise<void>}
|
|
498
|
+
*/
|
|
499
|
+
async downloadFile(url, filePath) {
|
|
500
|
+
return new Promise((resolve, reject) => {
|
|
501
|
+
const protocol = url.startsWith('https:') ? https : http;
|
|
502
|
+
|
|
503
|
+
const request = protocol.get(url, (response) => {
|
|
504
|
+
// Handle redirects
|
|
505
|
+
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
|
506
|
+
return this.downloadFile(response.headers.location, filePath)
|
|
507
|
+
.then(resolve)
|
|
508
|
+
.catch(reject);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Check for successful response
|
|
512
|
+
if (response.statusCode !== 200) {
|
|
513
|
+
reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Create write stream
|
|
518
|
+
const fileStream = require('fs').createWriteStream(filePath);
|
|
519
|
+
|
|
520
|
+
// Handle stream errors
|
|
521
|
+
fileStream.on('error', (error) => {
|
|
522
|
+
reject(new Error(`Failed to write file: ${error.message}`));
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// Handle download completion
|
|
526
|
+
fileStream.on('finish', () => {
|
|
527
|
+
fileStream.close();
|
|
528
|
+
const statsFs = require('fs').statSync(filePath);
|
|
529
|
+
this.totalDownloaded = this.totalDownloaded + statsFs.size;
|
|
530
|
+
resolve();
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
// Pipe response to file
|
|
534
|
+
response.pipe(fileStream);
|
|
535
|
+
|
|
536
|
+
}).on('error', (error) => {
|
|
537
|
+
reject(new Error(`Download request failed: ${error.message}`));
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
// Set timeout for request
|
|
541
|
+
request.setTimeout(30000, () => {
|
|
542
|
+
request.destroy();
|
|
543
|
+
reject(new Error('Download timeout (30 seconds)'));
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Creates a provider for the specified version , and context.
|
|
550
|
+
*
|
|
551
|
+
* @param {string} fhirVersion - FHIR version (e.g., '4.0.1', '5.0.0')
|
|
552
|
+
* @param {string} context - other information from the client that sets the context
|
|
553
|
+
* @returns {Promise<Provider>} New provider instance with FHIR packages loaded
|
|
554
|
+
*/
|
|
555
|
+
async cloneWithFhirVersion(fhirVersion, context, path) {
|
|
556
|
+
// Create new provider instance
|
|
557
|
+
const provider = new Provider();
|
|
558
|
+
provider.i18n = this.i18n;
|
|
559
|
+
provider.codeSystemFactories = new Map(this.codeSystemFactories); // all of them
|
|
560
|
+
provider.codeSystems = new Map();
|
|
561
|
+
provider.valueSetProviders = [];
|
|
562
|
+
provider.conceptMapProviders = [];
|
|
563
|
+
provider.path = path;
|
|
564
|
+
if (VersionUtilities.isR5Ver(fhirVersion)) {
|
|
565
|
+
provider.fhirVersion = 5;
|
|
566
|
+
} else if (VersionUtilities.isR4Ver(fhirVersion)) {
|
|
567
|
+
provider.fhirVersion = 4;
|
|
568
|
+
} else if (VersionUtilities.isR3Ver(fhirVersion)) {
|
|
569
|
+
provider.fhirVersion = 3;
|
|
570
|
+
} else {
|
|
571
|
+
provider.fhirVersion = 6;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
// Load FHIR core packages first
|
|
577
|
+
const fhirPackages = this.#getFhirPackagesForVersion(fhirVersion);
|
|
578
|
+
|
|
579
|
+
this.log.info(`Loading FHIR ${fhirVersion} packages`);
|
|
580
|
+
this.#logPackagesHeader();
|
|
581
|
+
|
|
582
|
+
// Load FHIR packages - these will be added to valueSetProviders first
|
|
583
|
+
for (const packageId of fhirPackages) {
|
|
584
|
+
await provider.loadNpm(this.packageManager, this.cacheFolder, packageId, false, "npm");
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
for (const cp of this.codeSystemProviders) {
|
|
589
|
+
const csMap = await cp.listCodeSystems(fhirVersion, context);
|
|
590
|
+
for (const [key, value] of csMap) {
|
|
591
|
+
provider.codeSystems.set(key, value);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
// Don't clone valueSetProviders yet - we'll build it with correct order
|
|
595
|
+
|
|
596
|
+
// Copy other properties
|
|
597
|
+
provider.baseUrl = this.baseUrl;
|
|
598
|
+
provider.cacheFolder = this.cacheFolder;
|
|
599
|
+
provider.startTime = this.startTime;
|
|
600
|
+
provider.startMemory = this.startMemory;
|
|
601
|
+
provider.lastTime = this.lastTime;
|
|
602
|
+
provider.lastMemory = this.lastMemory;
|
|
603
|
+
provider.totalDownloaded = this.totalDownloaded;
|
|
604
|
+
provider.contentSources = this.contentSources;
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
// Now add the existing value set providers after the FHIR core packages
|
|
608
|
+
provider.valueSetProviders.push(...this.valueSetProviders);
|
|
609
|
+
provider.conceptMapProviders.push(...this.conceptMapProviders);
|
|
610
|
+
|
|
611
|
+
return provider;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Gets the list of FHIR packages for a specific version
|
|
616
|
+
* @param {string} fhirVersion - FHIR version
|
|
617
|
+
* @returns {string} Package Id
|
|
618
|
+
* @private
|
|
619
|
+
*/
|
|
620
|
+
#getFhirPackagesForVersion(ver) {
|
|
621
|
+
if (VersionUtilities.isR3Ver(ver)) {
|
|
622
|
+
return ["hl7.fhir.r3.core"];
|
|
623
|
+
}
|
|
624
|
+
if (VersionUtilities.isR4Ver(ver) ||VersionUtilities.isR4BVer(ver)) {
|
|
625
|
+
return ["hl7.fhir.r4.core"];
|
|
626
|
+
}
|
|
627
|
+
if (VersionUtilities.isR5Ver(ver)) {
|
|
628
|
+
return ["hl7.fhir.r5.core"];
|
|
629
|
+
}
|
|
630
|
+
throw new Error(`Unsupported FHIR version: ${ver}. Supported versions: R3, R4, R5`);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* all the loaded resources must have unique IDs for the get operation
|
|
635
|
+
* they must be assigned by the library on loading. providers can either assign
|
|
636
|
+
* ids from the global space at start up, or, if they can provide new resources
|
|
637
|
+
* later in an ongoing fashion, allocate them in their own space
|
|
638
|
+
*/
|
|
639
|
+
assignIds() {
|
|
640
|
+
let ids = new Set();
|
|
641
|
+
// these don't have ids - not available directly for (const cs of this.codeSystemFactories) { .. }
|
|
642
|
+
let i = 0;
|
|
643
|
+
for (const cp of this.codeSystemProviders) {
|
|
644
|
+
cp.spaceId = String(++i);
|
|
645
|
+
cp.assignIds(ids);
|
|
646
|
+
}
|
|
647
|
+
i = 0;
|
|
648
|
+
for (const vp of this.valueSetProviders) {
|
|
649
|
+
vp.spaceId = String(++i);
|
|
650
|
+
vp.assignIds(ids);
|
|
651
|
+
}
|
|
652
|
+
i = 0;
|
|
653
|
+
for (const cmp of this.conceptMapProviders) {
|
|
654
|
+
cmp.spaceId = String(++i);
|
|
655
|
+
cmp.assignIds(ids);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
async close() {
|
|
661
|
+
for (let csp of this.codeSystemProviders) {
|
|
662
|
+
csp.close();
|
|
663
|
+
}
|
|
664
|
+
for (let csp of this.codeSystemFactories.values()) {
|
|
665
|
+
csp.close();
|
|
666
|
+
}
|
|
667
|
+
for (let vsp of this.valueSetProviders) {
|
|
668
|
+
vsp.close();
|
|
669
|
+
}
|
|
670
|
+
for (let cmp of this.conceptMapProviders) {
|
|
671
|
+
cmp.close();
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
module.exports = { Library };
|