fhirsmith 0.18.1 → 1.0.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/ACCESSIBILITY.md +119 -0
- package/CHANGELOG.md +190 -9
- package/CONFIGURATION.md +305 -0
- package/LICENSE +29 -0
- package/README.md +29 -122
- package/cluster.js +1220 -0
- package/cluster.md +707 -0
- package/config-template.json +77 -8
- package/extension-tracker/extension-tracker-template.html +5 -8
- package/extension-tracker/extension-tracker.js +0 -2
- package/folder/folder.js +7 -6
- package/ips/analysis.js +560 -0
- package/ips/ips-template.html +5 -8
- package/ips/ips.js +331 -33
- package/ips/jurisdictions.js +65 -0
- package/ips/nationality.js +120 -0
- package/ips/pipeline.js +131 -17
- package/ips/presenter.js +1 -1
- package/ips/profile-editor.js +283 -4
- package/ips/readme.md +170 -20
- package/ips/render.js +769 -109
- package/ips/scripts.js +46 -0
- package/ips/store.js +123 -11
- package/ips/structure.js +247 -0
- package/ips/terminology.js +1 -1
- package/library/body-limit.js +22 -0
- package/library/cache-generation.js +15 -0
- package/library/cgroup-memory.js +133 -1
- package/library/cluster-counts.js +121 -0
- package/library/cluster-events.js +153 -0
- package/library/cluster-metrics.js +193 -0
- package/library/cluster-status.js +468 -0
- package/library/config-reader.js +96 -0
- package/library/daily-report.js +100 -2
- package/library/html-server.js +27 -1
- package/library/i18nsupport.js +23 -1
- package/library/keep-alive.js +18 -0
- package/library/languages.js +17 -3
- package/library/logger.js +31 -0
- package/library/memory-guard.js +428 -0
- package/library/native-memory.js +52 -0
- package/library/npm-audit.js +51 -25
- package/library/openapi-doc.js +7 -5
- package/library/package-manager.js +8 -0
- package/library/role.js +197 -0
- package/library/server-credentials.js +169 -0
- package/library/sqlite-utilities.js +59 -0
- package/library/ssrf-guard.js +100 -0
- package/library/static-response-stats.js +16 -0
- package/library/version-utilities.js +50 -0
- package/library/worker-count.js +192 -0
- package/nginx.md +30 -11
- package/npmprojector/indexer.js +18 -10
- package/package.json +11 -8
- package/packages/feed-check-page.js +117 -0
- package/packages/feed-check.js +279 -0
- package/packages/npm-check.js +57 -3
- package/packages/npm-signing.js +219 -0
- package/packages/openapi.yaml +207 -1
- package/packages/package-crawler.js +322 -41
- package/packages/packages-template.html +6 -8
- package/packages/packages.js +604 -57
- package/packages/readme.md +113 -1
- package/publisher/publisher-template.html +2 -5
- package/publisher/publisher.js +121 -110
- package/publisher/readme.md +75 -0
- package/registry/api.js +179 -1
- package/registry/crawler.js +86 -108
- package/registry/documentation/api.md +68 -2
- package/registry/documentation/configuration.md +34 -0
- package/registry/documentation/internals.md +4 -1
- package/registry/documentation/readme.md +3 -2
- package/registry/model.js +8 -0
- package/registry/openapi.yaml +84 -0
- package/registry/registry-template.html +5 -8
- package/registry/registry.js +58 -6
- package/root-bare-template.html +7 -4
- package/root-template.html +5 -8
- package/server.js +398 -198
- package/shl/shl.js +38 -37
- package/static/a11y/a11y-check.js +832 -0
- package/static/a11y/axe.min.js +12 -0
- package/static/assets/css/bootstrap-fhir.css +15 -15
- package/static/assets/images/flags/au.svg +18 -0
- package/static/assets/images/flags/unknown.svg +11 -0
- package/static/assets/images/flags/us.svg +63 -0
- package/static/assets/images/icon_audit.png +0 -0
- package/static/assets/images/icon_clinical.png +0 -0
- package/static/assets/images/icon_document.png +0 -0
- package/static/assets/images/icon_external.png +0 -0
- package/static/assets/images/icon_medication.png +0 -0
- package/static/assets/images/icon_organization.png +0 -0
- package/static/assets/images/icon_other.png +0 -0
- package/static/assets/images/icon_person.png +0 -0
- package/static/assets/images/icon_section.png +0 -0
- package/stats-db.js +45 -0
- package/stats.js +197 -10
- package/testing/testing-template.html +5 -8
- package/token/nginx_passport_setup.md +1 -1
- package/token/security_guide.md +1 -1
- package/token/token-template.html +2 -5
- package/token/token.js +40 -36
- package/translations/Messages.properties +19 -0
- package/tx/README.md +158 -4
- package/tx/closure/closure-store.js +126 -3
- package/tx/cm/cm-database.js +69 -57
- package/tx/cm/cm-package.js +50 -16
- package/tx/cs/cs-api.js +284 -19
- package/tx/cs/cs-api.md +41 -4
- package/tx/cs/cs-areacode.js +1 -1
- package/tx/cs/cs-country.js +17 -5
- package/tx/cs/cs-cpt.js +33 -16
- package/tx/cs/cs-cs.js +199 -24
- package/tx/cs/cs-currency.js +1 -1
- package/tx/cs/cs-icd11.js +21 -13
- package/tx/cs/cs-icf.js +22 -3
- package/tx/cs/cs-lang.js +2 -2
- package/tx/cs/cs-loinc.js +193 -67
- package/tx/cs/cs-mimetypes.js +12 -2
- package/tx/cs/cs-ndc.js +40 -25
- package/tx/cs/cs-omop.js +54 -29
- package/tx/cs/cs-rxnorm.js +300 -196
- package/tx/cs/cs-snomed.js +861 -95
- package/tx/cs/cs-ucum.js +14 -4
- package/tx/cs/cs-unii.js +18 -14
- package/tx/cs/cs-virtual.js +210 -0
- package/tx/ecosystem-resolver.js +413 -0
- package/tx/html/cluster-dash-metrics.liquid +26 -0
- package/tx/html/cluster-home-metrics.liquid +31 -0
- package/tx/html/cluster-metrics-script.liquid +251 -0
- package/tx/html/codesystem-operations.liquid +3 -3
- package/tx/html/ecl-panel.liquid +1 -1
- package/tx/html/external-metrics.liquid +17 -0
- package/tx/html/operations-form.liquid +17 -17
- package/tx/html/search-form.liquid +11 -11
- package/tx/html/status-line.liquid +58 -0
- package/tx/html/status-panel.liquid +140 -0
- package/tx/html/status-tasks.liquid +25 -0
- package/tx/html/tx-template.html +2 -5
- package/tx/importers/atc-to-fhir.js +17 -16
- package/tx/importers/export-icd11-codesystem.js +3 -2
- package/tx/importers/import-icd11.js +4 -3
- package/tx/importers/import-loinc.module.js +118 -56
- package/tx/importers/import-ndc.module.js +56 -44
- package/tx/importers/import-rxnorm.module.js +118 -79
- package/tx/importers/import-sct.module.js +125 -61
- package/tx/importers/import-unii.module.js +37 -36
- package/tx/importers/subset-loinc.module.js +49 -48
- package/tx/importers/subset-rxnorm.module.js +29 -28
- package/tx/importers/terminal.js +18 -0
- package/tx/importers/tx-import-base.js +13 -12
- package/tx/importers/tx-import-settings.js +5 -4
- package/tx/importers/tx-import.js +53 -52
- package/tx/library/canonical-resource.js +49 -0
- package/tx/library/codesystem.js +94 -5
- package/tx/library/designations.js +45 -2
- package/tx/library/extensions.js +13 -7
- package/tx/library/implicit-valuesets.js +66 -0
- package/tx/library/renderer.js +77 -21
- package/tx/library/sqlite-utilities.js +2 -0
- package/tx/library/tho-precedence.js +40 -0
- package/tx/library/ucum-parsers.js +11 -1
- package/tx/library/wait-for-cache.js +43 -0
- package/tx/library.js +321 -22
- package/tx/openapi-operations.js +6 -4
- package/tx/operation-context.js +460 -99
- package/tx/params.js +25 -0
- package/tx/problems.js +3 -5
- package/tx/provider.js +314 -67
- package/tx/resource-cache-sqlite.js +1050 -0
- package/tx/sct/documentation.md +45 -21
- package/tx/sct/ecl.js +81 -17
- package/tx/sct/editions.js +39 -0
- package/tx/sct/expressions.js +10 -1
- package/tx/sct/load-config.js +107 -0
- package/tx/sct/mmap.js +109 -0
- package/tx/sct/structures.js +175 -15
- package/tx/sct/text-index.js +5 -1
- package/tx/syndication/syndication-feed.js +2 -2
- package/tx/tx-html.js +44 -8
- package/tx/tx.fhir.org.yml +8 -8
- package/tx/tx.js +282 -80
- package/tx/usage-tracker.js +39 -11
- package/tx/vs/vs-api.js +19 -0
- package/tx/vs/vs-database.js +386 -62
- package/tx/vs/vs-package.js +44 -17
- package/tx/vs/vs-vsac.js +649 -101
- package/tx/workers/batch-validate.js +37 -10
- package/tx/workers/batch.js +6 -1
- package/tx/workers/cache-control.js +15 -4
- package/tx/workers/closure.js +156 -13
- package/tx/workers/compare.js +8 -5
- package/tx/workers/expand.js +1173 -289
- package/tx/workers/metadata.js +35 -0
- package/tx/workers/search.js +53 -1
- package/tx/workers/supplement-filters.js +145 -0
- package/tx/workers/translate.js +169 -4
- package/tx/workers/validate.js +223 -119
- package/tx/workers/worker.js +123 -31
- package/tx/xversion/xv-valueset.js +7 -4
- package/utilities/submit-test-report.js +3 -1
- package/utilities/tx-stress-test.js +482 -0
- package/vcl/readme.md +37 -0
- package/vcl/vcl-parser.js +15 -0
- package/xig/readme.md +52 -0
- package/xig/xig-template.html +5 -8
- package/xig/xig.js +238 -422
- package/changelog-template.md +0 -22
- package/registry/test-runner.js +0 -237
- package/release.sh +0 -80
- package/test-scripts/repro-re2-wasm-leak.js +0 -34
- package/tsconfig.eslint.json +0 -9
- package/tx/html/dash-metrics.liquid +0 -147
- package/tx/html/home-metrics.liquid +0 -225
package/registry/model.js
CHANGED
|
@@ -362,6 +362,8 @@ class ServerRegistries {
|
|
|
362
362
|
constructor() {
|
|
363
363
|
this.address = '';
|
|
364
364
|
this.doco = '';
|
|
365
|
+
this.registration = ''; // URL: how to register your own server in this ecosystem
|
|
366
|
+
this.ecosystemDoco = ''; // URL: documentation for this ecosystem
|
|
365
367
|
this.lastRun = null; // Date object
|
|
366
368
|
this.outcome = '';
|
|
367
369
|
this.registries = []; // Array of ServerRegistry
|
|
@@ -386,6 +388,8 @@ class ServerRegistries {
|
|
|
386
388
|
this.lastRun = source.lastRun;
|
|
387
389
|
this.outcome = source.outcome;
|
|
388
390
|
this.doco = source.doco;
|
|
391
|
+
this.registration = source.registration;
|
|
392
|
+
this.ecosystemDoco = source.ecosystemDoco;
|
|
389
393
|
|
|
390
394
|
source.registries.forEach(sourceRegistry => {
|
|
391
395
|
const existing = this.getRegistry(sourceRegistry.code);
|
|
@@ -402,6 +406,8 @@ class ServerRegistries {
|
|
|
402
406
|
version: '1',
|
|
403
407
|
address: this.address,
|
|
404
408
|
doco: this.doco,
|
|
409
|
+
registration: this.registration,
|
|
410
|
+
'ecosystem-documentation': this.ecosystemDoco,
|
|
405
411
|
'last-run': this.lastRun?.toISOString() || '',
|
|
406
412
|
outcome: this.outcome,
|
|
407
413
|
registries: this.registries.map(r => r.toJSON())
|
|
@@ -416,6 +422,8 @@ class ServerRegistries {
|
|
|
416
422
|
const instance = new ServerRegistries();
|
|
417
423
|
instance.address = json.address || '';
|
|
418
424
|
instance.doco = json.doco || '';
|
|
425
|
+
instance.registration = json.registration || '';
|
|
426
|
+
instance.ecosystemDoco = json['ecosystem-documentation'] || '';
|
|
419
427
|
instance.lastRun = json['last-run'] ? new Date(json['last-run']) : null;
|
|
420
428
|
instance.outcome = json.outcome || '';
|
|
421
429
|
instance.registries = (json.registries || []).map(r => ServerRegistry.fromJSON(r));
|
package/registry/openapi.yaml
CHANGED
|
@@ -25,6 +25,9 @@ info:
|
|
|
25
25
|
* **Resolution** (`GET /resolve`): which server should be used for this code system
|
|
26
26
|
or value set?
|
|
27
27
|
|
|
28
|
+
It also offers **server choice** (`GET /choose-server`): given all the code systems a
|
|
29
|
+
request involves, and the client's default server, which one server should it go to?
|
|
30
|
+
|
|
28
31
|
Servers can claim to be **authoritative** for code systems and value sets (by URL
|
|
29
32
|
mask) in their registration. A server that hosts the content but makes no claim is a
|
|
30
33
|
**candidate**. A server is only ever returned for content it actually hosts.
|
|
@@ -182,6 +185,77 @@ paths:
|
|
|
182
185
|
schema: { $ref: '#/components/schemas/Error' }
|
|
183
186
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
184
187
|
|
|
188
|
+
/choose-server:
|
|
189
|
+
get:
|
|
190
|
+
tags: [resolution]
|
|
191
|
+
operationId: chooseServer
|
|
192
|
+
summary: Choose one server for a request involving several code systems
|
|
193
|
+
description: |
|
|
194
|
+
For clients that aren't the HL7 Java tooling: the same choice the Java tooling makes
|
|
195
|
+
(TerminologyClientManager.chooseServer), made from the registry's own data. Returns
|
|
196
|
+
the server to send the request to, and a log of how it was chosen.
|
|
197
|
+
|
|
198
|
+
The client works out the code systems the request involves - from the codings, and
|
|
199
|
+
the value set's includes and excludes, following imported value sets - and applies
|
|
200
|
+
any versions fixed by expansion parameters. If it can't follow an import, it should
|
|
201
|
+
use its default server without asking.
|
|
202
|
+
|
|
203
|
+
In order, the choice is:
|
|
204
|
+
|
|
205
|
+
1. a server authoritative for all the code systems
|
|
206
|
+
2. a server authoritative for one, and authoritative or a candidate for the others
|
|
207
|
+
3. for several code systems including SNOMED CT, the choice for SNOMED CT alone; for
|
|
208
|
+
a code system tx.fhir.org handles specially (LOINC, UCUM, RxNorm ...), the default
|
|
209
|
+
4. a server that is a candidate for all of them, and reports a usable (complete or
|
|
210
|
+
fragment) copy of each, or no content mode at all
|
|
211
|
+
5. the server authoritative for the most of them
|
|
212
|
+
6. the server the value set comes from (resolved by `valueSet`), else the default
|
|
213
|
+
|
|
214
|
+
In 2 and 4, a code system that no server hosts doesn't count against a server.
|
|
215
|
+
parameters:
|
|
216
|
+
- name: fhirVersion
|
|
217
|
+
in: query
|
|
218
|
+
required: true
|
|
219
|
+
description: The FHIR version, as a release code (`R4`, `R4B`, `R5` ...) or a version (`4.0.1`, `4.0`).
|
|
220
|
+
schema: { type: string }
|
|
221
|
+
example: R4
|
|
222
|
+
- name: system
|
|
223
|
+
in: query
|
|
224
|
+
description: |
|
|
225
|
+
A code system the request involves, `url` or `url|version`. Repeat for each one
|
|
226
|
+
(`system=a&system=b`). With none, the answer is the default server.
|
|
227
|
+
schema: { type: array, items: { type: string } }
|
|
228
|
+
style: form
|
|
229
|
+
explode: true
|
|
230
|
+
example: [http://loinc.org, http://snomed.info/sct|http://snomed.info/sct/32506021000036107]
|
|
231
|
+
- name: default
|
|
232
|
+
in: query
|
|
233
|
+
required: true
|
|
234
|
+
description: The client's default terminology server (the one it would use without the ecosystem).
|
|
235
|
+
schema: { type: string, format: uri }
|
|
236
|
+
example: http://tx.fhir.org/r4
|
|
237
|
+
- name: valueSet
|
|
238
|
+
in: query
|
|
239
|
+
description: The value set the request is about, `url` or `url|version`, if there is one. Used for the log, and in step 6.
|
|
240
|
+
schema: { type: string }
|
|
241
|
+
- $ref: '#/components/parameters/language'
|
|
242
|
+
- name: usage
|
|
243
|
+
in: query
|
|
244
|
+
description: What the client is doing, for servers that restrict their use (as for `/resolve`).
|
|
245
|
+
schema: { type: string }
|
|
246
|
+
responses:
|
|
247
|
+
'200':
|
|
248
|
+
description: The chosen server
|
|
249
|
+
content:
|
|
250
|
+
application/json:
|
|
251
|
+
schema: { $ref: '#/components/schemas/ChooseServerResult' }
|
|
252
|
+
'400':
|
|
253
|
+
description: A required parameter is missing, or a URL is malformed
|
|
254
|
+
content:
|
|
255
|
+
application/json:
|
|
256
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
257
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
258
|
+
|
|
185
259
|
components:
|
|
186
260
|
securitySchemes:
|
|
187
261
|
bearer:
|
|
@@ -311,6 +385,16 @@ components:
|
|
|
311
385
|
type: array
|
|
312
386
|
items: { $ref: '#/components/schemas/ResolvedServer' }
|
|
313
387
|
|
|
388
|
+
ChooseServerResult:
|
|
389
|
+
type: object
|
|
390
|
+
required: [server, log]
|
|
391
|
+
properties:
|
|
392
|
+
server: { type: string, format: uri, description: The FHIR endpoint to send the request to }
|
|
393
|
+
log:
|
|
394
|
+
type: array
|
|
395
|
+
items: { type: string }
|
|
396
|
+
description: How the server was chosen - what the registry says about each code system, then the rule that decided. For people, not for parsing
|
|
397
|
+
|
|
314
398
|
ResolvedServer:
|
|
315
399
|
allOf:
|
|
316
400
|
- $ref: '#/components/schemas/SecurityFlags'
|
|
@@ -55,8 +55,6 @@
|
|
|
55
55
|
<div class="container"> <!-- container -->
|
|
56
56
|
<div style="background-color: #ad1f2f; padding: 6px; color: white;"> <!-- container -->
|
|
57
57
|
|
|
58
|
-
<a href="http://www.hl7.org/fhir" style="color: gold" title="Fast Healthcare Interoperability Resources - Home Page"><img border="0" src="/icon-fhir-16.png" style="vertical-align: text-bottom"/> <b>FHIR</b></a> © HL7.org |
|
|
59
|
-
<a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" style="color: gold"><img border="0" src="/FHIRsmith16.png" style="vertical-align: text-bottom"/> FHIRsmith</a> [%ver%] |
|
|
60
58
|
<a href="/" style="color: gold"> Server Home</a> |
|
|
61
59
|
<a href="/tx-reg" style="color: gold">Registry Home</a> |
|
|
62
60
|
<a href="/tx-reg/resolve" style="color: gold">Resolve</a> |
|
|
@@ -75,7 +73,7 @@
|
|
|
75
73
|
<div class="inner-wrapper">
|
|
76
74
|
<div class="col-9">
|
|
77
75
|
|
|
78
|
-
<h2><img border="0" src="
|
|
76
|
+
<h2><a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" title="FHIRsmith [%ver%]"><img border="0" src="/FHIRsmith32.png" alt="FHIRsmith Logo" style="vertical-align: text-bottom"/></a> [%title%] </h2>
|
|
79
77
|
|
|
80
78
|
[%content%]
|
|
81
79
|
|
|
@@ -93,8 +91,7 @@
|
|
|
93
91
|
<div class="container"> <!-- container -->
|
|
94
92
|
<div class="inner-wrapper">
|
|
95
93
|
<p>
|
|
96
|
-
<a href="
|
|
97
|
-
<a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" style="color: gold"><img border="0" src="/FHIRsmith16.png" style="vertical-align: text-bottom"/> FHIRsmith</a> [%ver%] © HealthIntersections.com.au 2023+ |
|
|
94
|
+
<a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" style="color: gold"><img border="0" src="/FHIRsmith16.png" alt="FHIRsmith Logo" style="vertical-align: text-bottom"/> FHIRsmith</a> [%ver%] © HealthIntersections.com.au 2023+ |
|
|
98
95
|
Terminology Registry [%crawler-status%] |
|
|
99
96
|
([%ms%] ms)
|
|
100
97
|
[%sponsorMessage%]
|
|
@@ -118,10 +115,10 @@
|
|
|
118
115
|
================================================== -->
|
|
119
116
|
<!-- Placed at the end of the document so the pages load faster -->
|
|
120
117
|
<!-- <script src="/assets/js/jquery.js"/> -->
|
|
121
|
-
<script src="/assets/js/bootstrap.min.js"
|
|
122
|
-
<script src="/assets/js/respond.min.js"
|
|
118
|
+
<script src="/assets/js/bootstrap.min.js"></script>
|
|
119
|
+
<script src="/assets/js/respond.min.js"></script>
|
|
123
120
|
|
|
124
|
-
<script src="/assets/js/fhir.js"
|
|
121
|
+
<script src="/assets/js/fhir.js"></script>
|
|
125
122
|
|
|
126
123
|
<!-- Analytics Below
|
|
127
124
|
================================================== -->
|
package/registry/registry.js
CHANGED
|
@@ -20,6 +20,7 @@ const { RegistryAuth } = require('./auth');
|
|
|
20
20
|
// parameters are ignored) because existing ecosystem clients rely on that.
|
|
21
21
|
const DISCOVERY_PARAMS = ['registry', 'server', 'fhirVersion', 'url', 'authoritativeOnly', 'language'];
|
|
22
22
|
const RESOLVE_PARAMS = ['fhirVersion', 'url', 'version', 'valueSet', 'authoritativeOnly', 'language', 'usage'];
|
|
23
|
+
const CHOOSE_SERVER_PARAMS = ['fhirVersion', 'system', 'default', 'valueSet', 'usage', 'language'];
|
|
23
24
|
|
|
24
25
|
// A link to a URL from a registry list or a crawled server: those are other people's
|
|
25
26
|
// content, so only an http(s) URL is linked, and it is escaped
|
|
@@ -90,6 +91,7 @@ class RegistryModule {
|
|
|
90
91
|
timeout: config.timeout || 30000,
|
|
91
92
|
userAgent: config.userAgent || 'FHIRRegistryServer/1.0',
|
|
92
93
|
apiKeys: config.apiKeys || {},
|
|
94
|
+
oauth: config.oauth || {},
|
|
93
95
|
maxResponseMB: config.maxResponseMB,
|
|
94
96
|
uptimeWindowDays: config.uptimeWindowDays,
|
|
95
97
|
uptimeRetentionDays: config.uptimeRetentionDays
|
|
@@ -325,6 +327,8 @@ class RegistryModule {
|
|
|
325
327
|
// Main registry page
|
|
326
328
|
this.router.get('/', apiLimiter, apiGuard, session, this.handleMainPage.bind(this));
|
|
327
329
|
this.router.get('/resolve', apiLimiter, apiGuard, session, this.handleResolveEndpoint.bind(this));
|
|
330
|
+
// JSON only - there's no page for a browser, so it's always guarded
|
|
331
|
+
this.router.get('/choose-server', apiLimiter, guard, this.handleChooseServerEndpoint.bind(this));
|
|
328
332
|
this.router.get('/log', session, this.handleLogEndpoint.bind(this));
|
|
329
333
|
this.router.get('/software', session, this.handleSoftwarePage.bind(this));
|
|
330
334
|
|
|
@@ -807,8 +811,15 @@ class RegistryModule {
|
|
|
807
811
|
const lastRunDate = new Date(stats.lastRun);
|
|
808
812
|
lastUpdatedText = `Last Updated: ${lastRunDate.toLocaleString()}`;
|
|
809
813
|
}
|
|
810
|
-
|
|
811
|
-
|
|
814
|
+
// what goes here depends on the ecosystem, so it comes from the master registration file
|
|
815
|
+
html += `<p>${lastUpdatedText}.`;
|
|
816
|
+
if (data.registration) {
|
|
817
|
+
html += ` <a href="${safeHref(data.registration)}">Register your own server</a>`;
|
|
818
|
+
}
|
|
819
|
+
if (data.ecosystemDoco) {
|
|
820
|
+
html += `${data.registration ? ' -' : ''} see <a href="${safeHref(data.ecosystemDoco)}">Documentation</a>`;
|
|
821
|
+
}
|
|
822
|
+
html += '</p>';
|
|
812
823
|
|
|
813
824
|
html += '<table class="grid">';
|
|
814
825
|
html += '<thead><tr>';
|
|
@@ -1503,13 +1514,53 @@ class RegistryModule {
|
|
|
1503
1514
|
}
|
|
1504
1515
|
}
|
|
1505
1516
|
|
|
1517
|
+
/**
|
|
1518
|
+
* GET /choose-server: which one server to use for a request involving a set of code
|
|
1519
|
+
* systems (see RegistryAPI.chooseServer). system repeats; the other parameters take their
|
|
1520
|
+
* first value
|
|
1521
|
+
*/
|
|
1522
|
+
handleChooseServerEndpoint(req, res) {
|
|
1523
|
+
const start = Date.now();
|
|
1524
|
+
try {
|
|
1525
|
+
const params = this._normalizeQueryParams(req.query);
|
|
1526
|
+
const {fhirVersion, valueSet, usage, language} = params;
|
|
1527
|
+
const defaultServer = params.default;
|
|
1528
|
+
const raw = req.query.system;
|
|
1529
|
+
const systems = (raw == null ? [] : Array.isArray(raw) ? raw : [raw]).map(String).filter(s => s);
|
|
1530
|
+
|
|
1531
|
+
if (!fhirVersion) {
|
|
1532
|
+
return res.status(400).json({error: 'A FHIR version is required'});
|
|
1533
|
+
}
|
|
1534
|
+
if (!defaultServer || !this._isValidUrl(defaultServer, ['http:', 'https:'])) {
|
|
1535
|
+
return res.status(400).json({error: 'A default server (an http or https URL) is required'});
|
|
1536
|
+
}
|
|
1537
|
+
for (const system of systems) {
|
|
1538
|
+
if (!this._isValidUrl(system.split('|')[0])) {
|
|
1539
|
+
return res.status(400).json({error: 'Invalid code system URL format'});
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
if (valueSet && !this._isValidUrl(valueSet.split('|')[0])) {
|
|
1543
|
+
return res.status(400).json({error: 'Invalid value set URL format'});
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
const result = this.api.chooseServer(fhirVersion, systems, defaultServer, valueSet, usage, language);
|
|
1547
|
+
this.logger.info(`Chose ${result.server} for ${systems.join(', ') || '(no systems)'} (FHIR ${fhirVersion}, usage=${usage}, language=${language || 'none'})`);
|
|
1548
|
+
res.json(result);
|
|
1549
|
+
} catch (error) {
|
|
1550
|
+
this.logger.error('Error in choose-server endpoint:', error);
|
|
1551
|
+
res.status(400).json({error: error.message});
|
|
1552
|
+
} finally {
|
|
1553
|
+
this.stats.countRequest('choose-server', Date.now() - start);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1506
1557
|
buildResolveResultContent(result, fhirVersion, resourceUrl, usage, language) {
|
|
1507
1558
|
let html = '';
|
|
1508
1559
|
|
|
1509
1560
|
// Query information section
|
|
1510
1561
|
html += '<div class="card mb-4">';
|
|
1511
1562
|
html += '<div class="card-header">';
|
|
1512
|
-
html += '<
|
|
1563
|
+
html += '<h3 class="card-title">Query Information</h3>';
|
|
1513
1564
|
html += '</div>';
|
|
1514
1565
|
html += '<div class="card-body">';
|
|
1515
1566
|
html += `<p><strong>FHIR Version:</strong> ${escape(fhirVersion)}</p>`;
|
|
@@ -1527,7 +1578,7 @@ class RegistryModule {
|
|
|
1527
1578
|
// Authoritative servers section
|
|
1528
1579
|
html += '<div class="card mb-4">';
|
|
1529
1580
|
html += '<div class="card-header">';
|
|
1530
|
-
html += '<
|
|
1581
|
+
html += '<h3 class="card-title">Authoritative Servers</h3>';
|
|
1531
1582
|
html += '</div>';
|
|
1532
1583
|
html += '<div class="card-body">';
|
|
1533
1584
|
|
|
@@ -1566,7 +1617,7 @@ class RegistryModule {
|
|
|
1566
1617
|
// Candidate servers section
|
|
1567
1618
|
html += '<div class="card mb-4">';
|
|
1568
1619
|
html += '<div class="card-header">';
|
|
1569
|
-
html += '<
|
|
1620
|
+
html += '<h3 class="card-title">Candidate Servers</h3>';
|
|
1570
1621
|
html += '</div>';
|
|
1571
1622
|
html += '<div class="card-body">';
|
|
1572
1623
|
|
|
@@ -1817,7 +1868,7 @@ class RegistryModule {
|
|
|
1817
1868
|
case 'error': levelStyle = 'color: #d9534f; font-weight: bold;'; break;
|
|
1818
1869
|
case 'warn': levelStyle = 'color: #f0ad4e;'; break;
|
|
1819
1870
|
case 'debug': levelStyle = 'color: #5cb85c;'; break;
|
|
1820
|
-
default: levelStyle = 'color: #
|
|
1871
|
+
default: levelStyle = 'color: #0056b3;'; // info
|
|
1821
1872
|
}
|
|
1822
1873
|
|
|
1823
1874
|
// Format: [time] [LEVEL] message
|
|
@@ -1833,6 +1884,7 @@ class RegistryModule {
|
|
|
1833
1884
|
|
|
1834
1885
|
RegistryModule.DISCOVERY_PARAMS = DISCOVERY_PARAMS;
|
|
1835
1886
|
RegistryModule.RESOLVE_PARAMS = RESOLVE_PARAMS;
|
|
1887
|
+
RegistryModule.CHOOSE_SERVER_PARAMS = CHOOSE_SERVER_PARAMS;
|
|
1836
1888
|
|
|
1837
1889
|
module.exports = RegistryModule;
|
|
1838
1890
|
module.exports.commonBaseUrl = commonBaseUrl;
|
package/root-bare-template.html
CHANGED
|
@@ -71,9 +71,12 @@
|
|
|
71
71
|
|
|
72
72
|
<body style="margin-left: 10px">
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
<!-- the page's one h1, the size of an h2 as before -->
|
|
75
|
+
<h1 style="font-size:1.5em;margin:0.83em 0">[%title%] </h1>
|
|
75
76
|
|
|
77
|
+
<main>
|
|
76
78
|
[%content%]
|
|
79
|
+
</main>
|
|
77
80
|
|
|
78
81
|
|
|
79
82
|
<!-- JS and analytics only. -->
|
|
@@ -81,10 +84,10 @@
|
|
|
81
84
|
================================================== -->
|
|
82
85
|
<!-- Placed at the end of the document so the pages load faster -->
|
|
83
86
|
<!-- <script src="/assets/js/jquery.js"/> -->
|
|
84
|
-
<script src="/assets/js/bootstrap.min.js"
|
|
85
|
-
<script src="/assets/js/respond.min.js"
|
|
87
|
+
<script src="/assets/js/bootstrap.min.js"></script>
|
|
88
|
+
<script src="/assets/js/respond.min.js"></script>
|
|
86
89
|
|
|
87
|
-
<script src="/assets/js/fhir.js"
|
|
90
|
+
<script src="/assets/js/fhir.js"></script>
|
|
88
91
|
|
|
89
92
|
<!-- Analytics Below
|
|
90
93
|
================================================== -->
|
package/root-template.html
CHANGED
|
@@ -53,8 +53,6 @@
|
|
|
53
53
|
<div id="stripe"> </div>
|
|
54
54
|
<div class="container"> <!-- container -->
|
|
55
55
|
<div style="background-color: #ad1f2f; padding: 6px; color: white;"> <!-- container -->
|
|
56
|
-
<a href="http://www.hl7.org/fhir" style="color: gold" title="Fast Healthcare Interoperability Resources - Home Page"><img border="0" src="/icon-fhir-16.png" style="vertical-align: text-bottom"/> <b>FHIR</b></a> © HL7.org |
|
|
57
|
-
<a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" style="color: gold"><img border="0" src="/FHIRsmith16.png" style="vertical-align: text-bottom"/> FHIRsmith</a> [%ver%] |
|
|
58
56
|
<a href="/" style="color: gold"> Server Home</a>
|
|
59
57
|
|
|
60
58
|
|
|
@@ -70,7 +68,7 @@
|
|
|
70
68
|
<div class="inner-wrapper">
|
|
71
69
|
<div class="col-9">
|
|
72
70
|
|
|
73
|
-
|
|
71
|
+
<h2><a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" title="FHIRsmith [%ver%]"><img border="0" src="/FHIRsmith32.png" alt="FHIRsmith Logo" style="vertical-align: text-bottom"/></a> FHIRsmith: [%title%] </h2>
|
|
74
72
|
|
|
75
73
|
[%content%]
|
|
76
74
|
|
|
@@ -89,8 +87,7 @@
|
|
|
89
87
|
<div class="container"> <!-- container -->
|
|
90
88
|
<div class="inner-wrapper">
|
|
91
89
|
<p>
|
|
92
|
-
<a href="
|
|
93
|
-
<a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" style="color: gold"><img border="0" src="/FHIRsmith16.png" style="vertical-align: text-bottom"/> FHIRsmith</a> [%ver%] © HealthIntersections.com.au 2023+ |
|
|
90
|
+
<a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" style="color: gold"><img border="0" src="/FHIRsmith16.png" alt="FHIRsmith Logo" style="vertical-align: text-bottom"/> FHIRsmith</a> [%ver%] © HealthIntersections.com.au 2023+ |
|
|
94
91
|
([%ms%] ms)
|
|
95
92
|
[%sponsorMessage%]
|
|
96
93
|
</p>
|
|
@@ -113,10 +110,10 @@
|
|
|
113
110
|
================================================== -->
|
|
114
111
|
<!-- Placed at the end of the document so the pages load faster -->
|
|
115
112
|
<!-- <script src="/assets/js/jquery.js"/> -->
|
|
116
|
-
<script src="/assets/js/bootstrap.min.js"
|
|
117
|
-
<script src="/assets/js/respond.min.js"
|
|
113
|
+
<script src="/assets/js/bootstrap.min.js"></script>
|
|
114
|
+
<script src="/assets/js/respond.min.js"></script>
|
|
118
115
|
|
|
119
|
-
<script src="/assets/js/fhir.js"
|
|
116
|
+
<script src="/assets/js/fhir.js"></script>
|
|
120
117
|
|
|
121
118
|
<!-- Analytics Below
|
|
122
119
|
================================================== -->
|