fhirsmith 0.14.0 → 0.14.2
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 +64 -0
- package/README.md +3 -2
- package/config-template.json +20 -0
- package/library/fhir-openapi-schema.js +441 -0
- package/library/html-server.js +9 -3
- package/library/languages.js +15 -0
- package/library/npm-audit.js +265 -0
- package/library/openapi-doc.js +557 -0
- package/library/same-origin.js +62 -0
- package/library/utilities.js +21 -0
- package/nginx.md +17 -9
- package/package.json +10 -4
- package/packages/openapi.js +13 -0
- package/packages/openapi.yaml +603 -0
- package/packages/packages-template.html +4 -2
- package/packages/packages.js +286 -81
- package/packages/readme.md +120 -0
- package/publisher/publisher-template.html +1 -0
- package/publisher/publisher.js +95 -42
- package/registry/api.js +117 -41
- package/registry/crawler.js +24 -0
- package/registry/fhirsmith-releases.js +170 -0
- package/registry/model.js +10 -0
- package/registry/openapi.js +13 -0
- package/registry/openapi.yaml +311 -0
- package/registry/readme.md +107 -208
- package/registry/registry-template.html +4 -1
- package/registry/registry.js +183 -20
- package/server.js +25 -6
- package/testing/openapi-schemas.config.js +58 -0
- package/testing/openapi-schemas.json +1920 -0
- package/testing/openapi.js +15 -0
- package/testing/openapi.yaml +273 -0
- package/testing/readme.md +75 -1
- package/testing/render.js +270 -29
- package/testing/search.js +1 -1
- package/testing/store.js +152 -8
- package/testing/testing-template.html +2 -0
- package/testing/testing.js +307 -9
- package/translations/Messages.properties +1 -0
- package/tx/README.md +58 -0
- package/tx/cm/cm-database.js +10 -1
- package/tx/cm/cm-package.js +8 -1
- package/tx/cs/cs-rxnorm.js +23 -6
- package/tx/cs/cs-snomed.js +3 -72
- package/tx/html/tx-template.html +2 -0
- package/tx/library/canonical-resource.js +50 -1
- package/tx/library/codesystem.js +1 -0
- package/tx/library/conceptmap.js +1 -0
- package/tx/library/valueset.js +16 -0
- package/tx/library.js +17 -2
- package/tx/openapi-operations.js +363 -0
- package/tx/openapi-schemas.config.js +118 -0
- package/tx/openapi-schemas.json +7903 -0
- package/tx/openapi.js +289 -0
- package/tx/openapi.yaml +151 -0
- package/tx/operation-context.js +15 -0
- package/tx/params.js +3 -12
- package/tx/provider.js +10 -1
- package/tx/sct/editions.js +70 -0
- package/tx/tx-html.js +6 -0
- package/tx/tx.js +55 -0
- package/tx/vs/vs-database.js +14 -5
- package/tx/vs/vs-package.js +10 -0
- package/tx/workers/expand.js +37 -18
- package/tx/workers/metadata.js +0 -13
- package/tx/workers/translate.js +25 -1
- package/tx/workers/validate.js +74 -24
- package/tx/workers/worker.js +32 -43
- package/utilities/extract-schema-json.js +167 -0
- package/utilities/generate-openapi-schemas.js +49 -0
- package/utilities/submit-test-report.js +1 -1
- package/xig/xig.js +2 -4
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# OpenAPI description of the FHIRsmith terminology server registry (/tx-reg) - the
|
|
2
|
+
# coordination server of the HL7 terminology ecosystem.
|
|
3
|
+
#
|
|
4
|
+
# The normative description of this API is the ecosystem page of the terminology
|
|
5
|
+
# ecosystem IG (https://build.fhir.org/ig/HL7/fhir-tx-ecosystem-ig/ecosystem.html); this
|
|
6
|
+
# file describes what this server implements, including its extensions. It is maintained by
|
|
7
|
+
# hand, and tests/registry/openapi.test.js keeps it honest: every route the router registers
|
|
8
|
+
# must be described here or explicitly excluded, and the documented query parameters must
|
|
9
|
+
# be the ones the handlers read (DISCOVERY_PARAMS, RESOLVE_PARAMS in registry.js).
|
|
10
|
+
#
|
|
11
|
+
# info.version is filled in from package.json when the spec is served.
|
|
12
|
+
|
|
13
|
+
openapi: 3.1.0
|
|
14
|
+
info:
|
|
15
|
+
title: FHIRsmith Terminology Server Registry
|
|
16
|
+
version: "0.0.0"
|
|
17
|
+
summary: Find the right terminology server for a code system or value set
|
|
18
|
+
description: |
|
|
19
|
+
The coordination server of a terminology server ecosystem. It regularly scans the
|
|
20
|
+
servers listed in the ecosystem's master registration file - their
|
|
21
|
+
CapabilityStatement, TerminologyCapabilities and ValueSets - and answers two
|
|
22
|
+
questions:
|
|
23
|
+
|
|
24
|
+
* **Discovery** (`GET /`): which terminology server endpoints are there?
|
|
25
|
+
* **Resolution** (`GET /resolve`): which server should be used for this code system
|
|
26
|
+
or value set?
|
|
27
|
+
|
|
28
|
+
Servers can claim to be **authoritative** for code systems and value sets (by URL
|
|
29
|
+
mask) in their registration. A server that hosts the content but makes no claim is a
|
|
30
|
+
**candidate**. A server is only ever returned for content it actually hosts.
|
|
31
|
+
|
|
32
|
+
**Content negotiation.** If the request's `Accept` header contains `text/html`, these
|
|
33
|
+
endpoints return a browsable HTML page instead of JSON. The JSON form is the contract.
|
|
34
|
+
|
|
35
|
+
**Parameters are read leniently**: unknown parameters are ignored, and a repeated
|
|
36
|
+
parameter takes its first value.
|
|
37
|
+
license:
|
|
38
|
+
name: BSD-3-Clause
|
|
39
|
+
url: https://opensource.org/license/bsd-3-clause
|
|
40
|
+
externalDocs:
|
|
41
|
+
description: Terminology ecosystem IG - the ecosystem and the coordination server API
|
|
42
|
+
url: https://build.fhir.org/ig/HL7/fhir-tx-ecosystem-ig/ecosystem.html
|
|
43
|
+
servers:
|
|
44
|
+
- url: /tx-reg
|
|
45
|
+
tags:
|
|
46
|
+
- name: discovery
|
|
47
|
+
description: List the servers in the ecosystem
|
|
48
|
+
- name: resolution
|
|
49
|
+
description: Choose a server for a code system or value set
|
|
50
|
+
|
|
51
|
+
paths:
|
|
52
|
+
/:
|
|
53
|
+
get:
|
|
54
|
+
tags: [discovery]
|
|
55
|
+
operationId: discover
|
|
56
|
+
summary: List terminology server endpoints
|
|
57
|
+
description: |
|
|
58
|
+
Lists the server endpoints in the ecosystem, one entry per server per FHIR
|
|
59
|
+
version, optionally filtered.
|
|
60
|
+
|
|
61
|
+
With `url`, only endpoints that host that code system are listed, those
|
|
62
|
+
authoritative for it first, and each entry's `candidate` list says whether the
|
|
63
|
+
endpoint hosts it without claiming authority. A server that excludes the code
|
|
64
|
+
system is not listed.
|
|
65
|
+
|
|
66
|
+
Without `url`, each entry's `authoritative` and `authoritative-valuesets` are the
|
|
67
|
+
server's claim masks, and there are no candidate lists (listing everything a server
|
|
68
|
+
hosts would make the response very large).
|
|
69
|
+
parameters:
|
|
70
|
+
- name: registry
|
|
71
|
+
in: query
|
|
72
|
+
description: Only endpoints from this registry (its code in the master registration file).
|
|
73
|
+
schema: { type: string }
|
|
74
|
+
- name: server
|
|
75
|
+
in: query
|
|
76
|
+
description: Only endpoints of this server (its code in its registry).
|
|
77
|
+
schema: { type: string }
|
|
78
|
+
example: tx.fhir.org
|
|
79
|
+
- $ref: '#/components/parameters/fhirVersionOptional'
|
|
80
|
+
- name: url
|
|
81
|
+
in: query
|
|
82
|
+
description: Only endpoints that host this code system (`url` or `url|version`).
|
|
83
|
+
schema: { type: string }
|
|
84
|
+
example: http://loinc.org
|
|
85
|
+
- name: authoritativeOnly
|
|
86
|
+
in: query
|
|
87
|
+
description: With `url`, only endpoints that are authoritative for it.
|
|
88
|
+
schema: { type: string, enum: ['true', 'false'], default: 'false' }
|
|
89
|
+
- $ref: '#/components/parameters/language'
|
|
90
|
+
responses:
|
|
91
|
+
'200':
|
|
92
|
+
description: The matching endpoints
|
|
93
|
+
content:
|
|
94
|
+
application/json:
|
|
95
|
+
schema: { $ref: '#/components/schemas/DiscoveryResult' }
|
|
96
|
+
text/html:
|
|
97
|
+
schema: { type: string }
|
|
98
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
99
|
+
'500': { $ref: '#/components/responses/ServerError' }
|
|
100
|
+
|
|
101
|
+
/resolve:
|
|
102
|
+
get:
|
|
103
|
+
tags: [resolution]
|
|
104
|
+
operationId: resolve
|
|
105
|
+
summary: Choose a server for a code system or value set
|
|
106
|
+
description: |
|
|
107
|
+
Returns the endpoints to use for a code system (`url`) or a value set (`valueSet`)
|
|
108
|
+
at a FHIR version: those authoritative for it, then the other candidates that host
|
|
109
|
+
it. Choosing between several is up to the client.
|
|
110
|
+
|
|
111
|
+
* An endpoint is only listed if it hosts the code system (+version). A SNOMED CT
|
|
112
|
+
edition (`http://snomed.info/sct|http://snomed.info/sct/{edition}`) is hosted by an
|
|
113
|
+
endpoint that hosts any version of that edition.
|
|
114
|
+
* An endpoint listed as authoritative is not also listed as a candidate.
|
|
115
|
+
* A server whose registration has a `usage` list is only returned if the request's
|
|
116
|
+
`usage` is in it.
|
|
117
|
+
* A server that excludes the code system or value set is never returned.
|
|
118
|
+
* `authoritative` and `candidates` are omitted when empty.
|
|
119
|
+
|
|
120
|
+
With `language`, endpoints matched on a language specific claim come first in
|
|
121
|
+
`authoritative`, and candidates are marked `language-support: unknown`. Value set
|
|
122
|
+
resolution has no language dimension.
|
|
123
|
+
|
|
124
|
+
A browser request (`Accept: text/html`) without the required parameters returns a
|
|
125
|
+
form for making the request.
|
|
126
|
+
parameters:
|
|
127
|
+
- name: fhirVersion
|
|
128
|
+
in: query
|
|
129
|
+
required: true
|
|
130
|
+
description: The FHIR version, as a release code (`R4`, `R4B`, `R5` ...) or a version (`4.0.1`, `4.0`).
|
|
131
|
+
schema: { type: string }
|
|
132
|
+
example: R4
|
|
133
|
+
- name: url
|
|
134
|
+
in: query
|
|
135
|
+
description: The code system, `url` or `url|version`. One of `url` and `valueSet` is required.
|
|
136
|
+
schema: { type: string }
|
|
137
|
+
example: http://snomed.info/sct|http://snomed.info/sct/32506021000036107
|
|
138
|
+
- name: version
|
|
139
|
+
in: query
|
|
140
|
+
description: |
|
|
141
|
+
A version for `url`, as an alternative to `url|version`. Ignored if `url` already
|
|
142
|
+
has a version. (An extension to the ecosystem IG.)
|
|
143
|
+
schema: { type: string }
|
|
144
|
+
- name: valueSet
|
|
145
|
+
in: query
|
|
146
|
+
description: The value set, `url` or `url|version`.
|
|
147
|
+
schema: { type: string }
|
|
148
|
+
example: http://hl7.org/fhir/ValueSet/observation-codes
|
|
149
|
+
- name: authoritativeOnly
|
|
150
|
+
in: query
|
|
151
|
+
description: Only return authoritative endpoints (no candidates).
|
|
152
|
+
schema: { type: string, enum: ['true', 'false'], default: 'false' }
|
|
153
|
+
- $ref: '#/components/parameters/language'
|
|
154
|
+
- name: usage
|
|
155
|
+
in: query
|
|
156
|
+
description: |
|
|
157
|
+
What the client is doing, for servers that restrict their use. The HL7 Java
|
|
158
|
+
tools send `publication`, `validation` or `code-generation`.
|
|
159
|
+
schema: { type: string }
|
|
160
|
+
example: publication
|
|
161
|
+
responses:
|
|
162
|
+
'200':
|
|
163
|
+
description: The endpoints to use
|
|
164
|
+
content:
|
|
165
|
+
application/json:
|
|
166
|
+
schema: { $ref: '#/components/schemas/ResolveResult' }
|
|
167
|
+
text/html:
|
|
168
|
+
schema: { type: string }
|
|
169
|
+
'400':
|
|
170
|
+
description: A required parameter is missing, or a URL is malformed
|
|
171
|
+
content:
|
|
172
|
+
application/json:
|
|
173
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
174
|
+
|
|
175
|
+
components:
|
|
176
|
+
parameters:
|
|
177
|
+
fhirVersionOptional:
|
|
178
|
+
name: fhirVersion
|
|
179
|
+
in: query
|
|
180
|
+
description: Only endpoints for this FHIR version, as a release code (`R4`, `R4B`, `R5` ...) or a version (`4.0.1`, `4.0`).
|
|
181
|
+
schema: { type: string }
|
|
182
|
+
example: R4
|
|
183
|
+
language:
|
|
184
|
+
name: language
|
|
185
|
+
in: query
|
|
186
|
+
description: |
|
|
187
|
+
The language of the request being routed, in Accept-Language syntax: one BCP-47
|
|
188
|
+
tag, or a weighted list (`de-AT, de;q=0.9, en;q=0.1`). Pass it only when the
|
|
189
|
+
operation is language-sensitive. With discovery, only meaningful with `url`.
|
|
190
|
+
schema: { type: string }
|
|
191
|
+
example: de
|
|
192
|
+
|
|
193
|
+
responses:
|
|
194
|
+
BadRequest:
|
|
195
|
+
description: A parameter is malformed
|
|
196
|
+
content:
|
|
197
|
+
application/json:
|
|
198
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
199
|
+
ServerError:
|
|
200
|
+
description: The server failed to process the request
|
|
201
|
+
content:
|
|
202
|
+
application/json:
|
|
203
|
+
schema: { $ref: '#/components/schemas/Error' }
|
|
204
|
+
|
|
205
|
+
schemas:
|
|
206
|
+
SecurityFlags:
|
|
207
|
+
type: object
|
|
208
|
+
description: |
|
|
209
|
+
How the endpoint can be accessed, as the boolean flags of the ecosystem IG (`open`
|
|
210
|
+
for unauthenticated use; an API key is reported as `token`), plus the scanner's own
|
|
211
|
+
`security` string (`open` or `api-key`), kept for existing clients.
|
|
212
|
+
properties:
|
|
213
|
+
security: { type: string, enum: [open, api-key] }
|
|
214
|
+
open: { type: boolean, const: true }
|
|
215
|
+
password: { type: boolean, const: true }
|
|
216
|
+
token: { type: boolean, const: true }
|
|
217
|
+
oauth: { type: boolean, const: true }
|
|
218
|
+
smart: { type: boolean, const: true }
|
|
219
|
+
cert: { type: boolean, const: true }
|
|
220
|
+
|
|
221
|
+
DiscoveryResult:
|
|
222
|
+
type: object
|
|
223
|
+
required: [last-update, master-url, results]
|
|
224
|
+
properties:
|
|
225
|
+
last-update:
|
|
226
|
+
type: [string, 'null']
|
|
227
|
+
format: date-time
|
|
228
|
+
description: When the ecosystem was last scanned
|
|
229
|
+
master-url: { type: string, format: uri, description: The master registration file that was scanned }
|
|
230
|
+
results:
|
|
231
|
+
type: array
|
|
232
|
+
items: { $ref: '#/components/schemas/DiscoveryEntry' }
|
|
233
|
+
|
|
234
|
+
DiscoveryEntry:
|
|
235
|
+
allOf:
|
|
236
|
+
- $ref: '#/components/schemas/SecurityFlags'
|
|
237
|
+
- type: object
|
|
238
|
+
required: [server-name, server-code, registry-name, registry-code, url, fhirVersion, systems, authoritative, authoritative-valuesets]
|
|
239
|
+
properties:
|
|
240
|
+
server-name: { type: string }
|
|
241
|
+
server-code: { type: string }
|
|
242
|
+
registry-name: { type: string }
|
|
243
|
+
registry-code: { type: string }
|
|
244
|
+
registry-url: { type: string, format: uri }
|
|
245
|
+
url: { type: string, format: uri, description: The FHIR endpoint }
|
|
246
|
+
fhirVersion: { type: string, example: 4.0.1 }
|
|
247
|
+
error:
|
|
248
|
+
type: [string, 'null']
|
|
249
|
+
description: What went wrong the last time the endpoint was scanned; null if it worked
|
|
250
|
+
last-success:
|
|
251
|
+
type: [integer, 'null']
|
|
252
|
+
description: Milliseconds since the endpoint was last scanned successfully; null if never
|
|
253
|
+
systems: { type: integer, description: Number of code systems the endpoint hosts }
|
|
254
|
+
authoritative:
|
|
255
|
+
type: array
|
|
256
|
+
items: { type: string }
|
|
257
|
+
description: The code system masks the server claims authority for
|
|
258
|
+
authoritative-valuesets:
|
|
259
|
+
type: array
|
|
260
|
+
items: { type: string }
|
|
261
|
+
description: The value set masks the server claims authority for
|
|
262
|
+
candidate:
|
|
263
|
+
type: array
|
|
264
|
+
items: { type: string }
|
|
265
|
+
description: With `url`, present when the endpoint hosts it without claiming authority
|
|
266
|
+
languages:
|
|
267
|
+
type: array
|
|
268
|
+
items: { type: string }
|
|
269
|
+
description: With `url` and `language`, the language tag of the claim the endpoint matched on
|
|
270
|
+
|
|
271
|
+
ResolveResult:
|
|
272
|
+
type: object
|
|
273
|
+
required: [formatVersion, registry-url]
|
|
274
|
+
properties:
|
|
275
|
+
formatVersion: { type: string, const: '1' }
|
|
276
|
+
registry-url: { type: string, format: uri, description: The master registration file }
|
|
277
|
+
authoritative:
|
|
278
|
+
type: array
|
|
279
|
+
items: { $ref: '#/components/schemas/ResolvedServer' }
|
|
280
|
+
candidates:
|
|
281
|
+
type: array
|
|
282
|
+
items: { $ref: '#/components/schemas/ResolvedServer' }
|
|
283
|
+
|
|
284
|
+
ResolvedServer:
|
|
285
|
+
allOf:
|
|
286
|
+
- $ref: '#/components/schemas/SecurityFlags'
|
|
287
|
+
- type: object
|
|
288
|
+
required: [server-name, url, fhirVersion]
|
|
289
|
+
properties:
|
|
290
|
+
server-name: { type: string }
|
|
291
|
+
url: { type: string, format: uri, description: The FHIR endpoint to use }
|
|
292
|
+
fhirVersion: { type: string, example: 4.0.1 }
|
|
293
|
+
access_info: { type: string, description: How to get access (markdown), from the server's registration }
|
|
294
|
+
content:
|
|
295
|
+
type: string
|
|
296
|
+
enum: [not-present, example, fragment, complete, supplement]
|
|
297
|
+
description: Candidates only - the content mode of the code system on this server, if it says
|
|
298
|
+
languages:
|
|
299
|
+
type: array
|
|
300
|
+
items: { type: string }
|
|
301
|
+
description: Authoritative entries matched on a language specific claim - that claim's language tag
|
|
302
|
+
language-support:
|
|
303
|
+
type: string
|
|
304
|
+
const: unknown
|
|
305
|
+
description: Candidates, when the request had a language - the ecosystem can't say whether this server has it
|
|
306
|
+
|
|
307
|
+
Error:
|
|
308
|
+
type: object
|
|
309
|
+
required: [error]
|
|
310
|
+
properties:
|
|
311
|
+
error: { type: string }
|
package/registry/readme.md
CHANGED
|
@@ -1,225 +1,124 @@
|
|
|
1
1
|
# Terminology Server Registry
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// Set up Express
|
|
76
|
-
const app = express();
|
|
77
|
-
api.registerRoutes(app);
|
|
78
|
-
|
|
79
|
-
// Start crawler and server
|
|
80
|
-
crawler.start();
|
|
81
|
-
app.listen(3000);
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### API Endpoints
|
|
85
|
-
|
|
86
|
-
#### Query Endpoints
|
|
87
|
-
|
|
88
|
-
**Find servers for a code system:**
|
|
89
|
-
```
|
|
90
|
-
GET /api/query/codesystem?system=http://loinc.org&version=4.0
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
**Find servers for a value set:**
|
|
94
|
-
```
|
|
95
|
-
GET /api/query/valueset?valueset=http://hl7.org/fhir/ValueSet/observation-codes
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
**Find the best server:**
|
|
99
|
-
```
|
|
100
|
-
GET /api/best-server/codesystem?url=http://snomed.info/sct
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
#### Registry Information
|
|
104
|
-
|
|
105
|
-
**Get statistics:**
|
|
106
|
-
```
|
|
107
|
-
GET /api/registry/stats
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
**List all registries:**
|
|
111
|
-
```
|
|
112
|
-
GET /api/registry
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
**Get servers in a registry:**
|
|
116
|
-
```
|
|
117
|
-
GET /api/registry/main/servers
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
#### Admin Endpoints
|
|
121
|
-
|
|
122
|
-
**Trigger manual crawl:**
|
|
123
|
-
```
|
|
124
|
-
POST /api/admin/crawl
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
**Export/Import data:**
|
|
128
|
-
```
|
|
129
|
-
GET /api/admin/data
|
|
130
|
-
POST /api/admin/data
|
|
131
|
-
```
|
|
3
|
+
The coordination server of a terminology server ecosystem, as described by the
|
|
4
|
+
[terminology ecosystem IG](https://build.fhir.org/ig/HL7/fhir-tx-ecosystem-ig/ecosystem.html).
|
|
5
|
+
It regularly scans the servers listed in the ecosystem's master registration file, and tells
|
|
6
|
+
clients which terminology server to use for a code system or value set. It runs at
|
|
7
|
+
http://tx.fhir.org/tx-reg for the HL7 ecosystem.
|
|
8
|
+
|
|
9
|
+
Its main client is the HL7 Java tooling (`TerminologyClientManager` in org.hl7.fhir.r5),
|
|
10
|
+
which calls `/resolve` to route each terminology operation to the right server.
|
|
11
|
+
|
|
12
|
+
## API
|
|
13
|
+
|
|
14
|
+
The public API is described by an OpenAPI 3.1 spec:
|
|
15
|
+
|
|
16
|
+
| URL | |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `/tx-reg/openapi` | Browsable reference (HTML), with a "try it" form for each GET operation |
|
|
19
|
+
| `/tx-reg/openapi.json` | The spec as JSON |
|
|
20
|
+
| `/tx-reg/openapi.yaml` | The spec as YAML (the source file, [openapi.yaml](openapi.yaml)) |
|
|
21
|
+
|
|
22
|
+
Every response carries a `Link: </tx-reg/openapi.json>; rel="service-desc"` header
|
|
23
|
+
(RFC 8631), and the HTML pages carry the matching `<link>` element.
|
|
24
|
+
|
|
25
|
+
| Endpoint | Purpose |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `GET /tx-reg/` | **Discovery**: the server endpoints in the ecosystem. Filters: `registry`, `server`, `fhirVersion`, `url`, `authoritativeOnly`, `language` |
|
|
28
|
+
| `GET /tx-reg/resolve` | **Resolution**: which endpoints to use for a code system (`url`) or value set (`valueSet`) at a `fhirVersion`. Also `authoritativeOnly`, `language`, `usage`, `version` |
|
|
29
|
+
|
|
30
|
+
Both return an HTML page instead of JSON when the request's `Accept` header contains
|
|
31
|
+
`text/html`. `/tx-reg/resolve` without parameters is a form for trying it out.
|
|
32
|
+
`/tx-reg/log` (the crawler log) is operational, and not in the spec.
|
|
33
|
+
|
|
34
|
+
Parameters are read leniently: unknown parameters are ignored, and a repeated parameter
|
|
35
|
+
takes its first value.
|
|
36
|
+
|
|
37
|
+
### How resolution decides
|
|
38
|
+
|
|
39
|
+
* An endpoint is only returned for content it actually hosts, as reported by its
|
|
40
|
+
TerminologyCapabilities (code systems) and ValueSet search (value sets).
|
|
41
|
+
* A SNOMED CT edition (`http://snomed.info/sct|http://snomed.info/sct/{edition}`) is hosted
|
|
42
|
+
by any endpoint that hosts a version of that edition. Otherwise SNOMED CT versions match
|
|
43
|
+
exactly; for other code systems, a server that hosts the code system hosts all its
|
|
44
|
+
versions.
|
|
45
|
+
* Endpoints whose server claims authority (the `authoritative` masks in its registration)
|
|
46
|
+
are listed as `authoritative`; the others as `candidates`.
|
|
47
|
+
* With `language`, servers with a matching language specific claim (`languages` in the
|
|
48
|
+
registration) come first, most specific tag first; candidates are marked
|
|
49
|
+
`language-support: unknown`.
|
|
50
|
+
* A server with a `usage` list is only returned when the request's `usage` is in it.
|
|
51
|
+
* A server's `exclusions` hide the matching content from it entirely.
|
|
52
|
+
* FHIR versions can be given as release codes (`R4`, `R4B`, `R5`, `R6` ...) or numbers
|
|
53
|
+
(`4.0.1`, `4.0`).
|
|
54
|
+
|
|
55
|
+
### Differences from the ecosystem IG
|
|
56
|
+
|
|
57
|
+
* Discovery: without `url`, a row's `authoritative`/`authoritative-valuesets` are the
|
|
58
|
+
server's claim masks, and there are no candidate lists. With `url`, `candidate` is
|
|
59
|
+
`[url]` when the endpoint hosts it without claiming authority.
|
|
60
|
+
* Entries carry the IG's security flags (`open`, `token`...) and also a `security` string
|
|
61
|
+
(`open` or `api-key`). Note that this records how the *registry* reaches the server: an
|
|
62
|
+
endpoint is `api-key` when the registry is configured with a key for it (`apiKeys`), and
|
|
63
|
+
`open` otherwise.
|
|
64
|
+
* Resolve takes a `version` parameter, as an alternative to `url|version`.
|
|
65
|
+
* Resolve omits `authoritative` and `candidates` when they are empty.
|
|
66
|
+
|
|
67
|
+
### Keeping the spec honest
|
|
68
|
+
|
|
69
|
+
[openapi.yaml](openapi.yaml) is maintained by hand. `tests/registry/openapi.test.js` fails
|
|
70
|
+
if a route is added without being described (or listed in the test's `EXCLUDED` table), if
|
|
71
|
+
the spec describes a route the router doesn't have, or if the documented query parameters
|
|
72
|
+
differ from `DISCOVERY_PARAMS` and `RESOLVE_PARAMS` in `registry.js`. So when you change a
|
|
73
|
+
route or a parameter, change `openapi.yaml` with it.
|
|
132
74
|
|
|
133
75
|
## Configuration
|
|
134
76
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
```javascript
|
|
138
|
-
{
|
|
139
|
-
code: 'main', // Unique registry identifier
|
|
140
|
-
name: 'Main Registry', // Display name
|
|
141
|
-
address: 'https://...', // Registry URL
|
|
142
|
-
authority: 'HL7', // Managing authority
|
|
143
|
-
servers: [...] // Array of server configs
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Server Configuration
|
|
148
|
-
|
|
149
|
-
```javascript
|
|
150
|
-
{
|
|
151
|
-
code: 'tx1', // Unique server identifier
|
|
152
|
-
name: 'TX Server', // Display name
|
|
153
|
-
address: 'https://...', // Base server URL
|
|
154
|
-
accessInfo: '...', // Access information
|
|
155
|
-
authCSList: [ // Authoritative code systems
|
|
156
|
-
'http://loinc.org*', // Supports wildcards
|
|
157
|
-
'http://snomed.info/sct'
|
|
158
|
-
],
|
|
159
|
-
authVSList: [...], // Authoritative value sets
|
|
160
|
-
usageList: ['public'], // Usage tags
|
|
161
|
-
versions: [...] // Array of version configs
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### Version Configuration
|
|
77
|
+
In the server config, under `modules.registry`:
|
|
166
78
|
|
|
167
|
-
```
|
|
168
|
-
{
|
|
169
|
-
|
|
170
|
-
|
|
79
|
+
```json
|
|
80
|
+
"registry": {
|
|
81
|
+
"enabled": true,
|
|
82
|
+
"masterUrl": "https://fhir.github.io/ig-registry/tx-servers.json",
|
|
83
|
+
"crawlInterval": 30,
|
|
84
|
+
"timeout": 30000,
|
|
85
|
+
"userAgent": "YourServer/1.0",
|
|
86
|
+
"apiKeys": {}
|
|
171
87
|
}
|
|
172
88
|
```
|
|
173
89
|
|
|
174
|
-
|
|
90
|
+
| Setting | |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `masterUrl` | The ecosystem's master registration file. Defaults to the HL7 one. |
|
|
93
|
+
| `crawlInterval` | Minutes between scans. 0 or absent: no scanning. |
|
|
94
|
+
| `timeout` | Per-request timeout for scanning, in milliseconds. |
|
|
95
|
+
| `userAgent` | The User-Agent the scanner sends. |
|
|
96
|
+
| `apiKeys` | API keys for servers that need one, by server code. |
|
|
175
97
|
|
|
176
|
-
|
|
98
|
+
## Scanning
|
|
177
99
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
- Non-authoritative servers are still returned but ranked lower
|
|
181
|
-
- Language specific claims (`languages`: BCP-47 tag -> mask list) make a server authoritative for
|
|
182
|
-
requests in that language only; matched entries rank ahead of language independent claims
|
|
183
|
-
- `exclusions` hides matching code systems/value sets from the ecosystem entirely (never
|
|
184
|
-
authoritative, never a candidate)
|
|
100
|
+
Each scan reads the master registration file, each registry it lists, and then, for each
|
|
101
|
+
server endpoint:
|
|
185
102
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
```bash
|
|
191
|
-
npm test
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
Run with Jest (if installed):
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
npm run test:jest
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
## Data Persistence
|
|
201
|
-
|
|
202
|
-
The crawler saves and loads its state in [data]/registry-data.json
|
|
203
|
-
|
|
204
|
-
## Development
|
|
205
|
-
|
|
206
|
-
Start development server with auto-reload:
|
|
207
|
-
|
|
208
|
-
```bash
|
|
209
|
-
npm run dev
|
|
210
|
-
```
|
|
103
|
+
* `/metadata` (the CapabilityStatement, for the software name and version)
|
|
104
|
+
* `/metadata?mode=terminology` (the TerminologyCapabilities, for the code systems and
|
|
105
|
+
versions it hosts)
|
|
106
|
+
* `/ValueSet?_elements=url,version` (the value sets it hosts)
|
|
211
107
|
|
|
212
|
-
|
|
108
|
+
An endpoint that fails keeps the content found by its last successful scan, and reports the
|
|
109
|
+
error. The scanner refuses to fetch from private or loopback addresses (SSRF protection).
|
|
213
110
|
|
|
214
|
-
The
|
|
111
|
+
The results are saved to `[data]/registry/registry-data.json` after each scan, and loaded at
|
|
112
|
+
startup, so the registry can answer immediately after a restart.
|
|
215
113
|
|
|
216
|
-
|
|
217
|
-
- `password`: Basic authentication
|
|
218
|
-
- `token`: Token-based authentication
|
|
219
|
-
- `oauth`: OAuth 2.0
|
|
220
|
-
- `smart`: SMART on FHIR
|
|
221
|
-
- `cert`: Certificate-based authentication
|
|
114
|
+
## Code
|
|
222
115
|
|
|
223
|
-
|
|
116
|
+
| File | |
|
|
117
|
+
|---|---|
|
|
118
|
+
| `registry.js` | The module: routes, HTML pages, scan scheduling |
|
|
119
|
+
| `api.js` | Discovery and resolution |
|
|
120
|
+
| `crawler.js` | Scanning |
|
|
121
|
+
| `model.js` | The data model, and mask and version matching |
|
|
122
|
+
| `openapi.yaml`, `openapi.js` | The API description |
|
|
224
123
|
|
|
225
|
-
|
|
124
|
+
Tests are in `tests/registry`.
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
<meta content="http://hl7.org/fhir" name="author"/>
|
|
10
10
|
<meta charset="utf-8" http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
11
11
|
|
|
12
|
+
<link rel="service-desc" type="application/json" href="/tx-reg/openapi.json"/>
|
|
12
13
|
<link rel="stylesheet" href="/fhir.css"/>
|
|
13
14
|
|
|
14
15
|
|
|
@@ -59,7 +60,9 @@
|
|
|
59
60
|
<a href="/" style="color: gold"> Server Home</a> |
|
|
60
61
|
<a href="/tx-reg" style="color: gold">Registry Home</a> |
|
|
61
62
|
<a href="/tx-reg/resolve" style="color: gold">Resolve</a> |
|
|
63
|
+
<a href="/tx-reg/software" style="color: gold">Software</a> |
|
|
62
64
|
<a href="/tx-reg/log" style="color: gold">Crawler Log</a> |
|
|
65
|
+
<a href="/tx-reg/openapi" style="color: gold">API</a>
|
|
63
66
|
</div> <!-- /container -->
|
|
64
67
|
</div> <!-- /container -->
|
|
65
68
|
</div>
|
|
@@ -92,7 +95,7 @@
|
|
|
92
95
|
<p>
|
|
93
96
|
<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 2011+. |
|
|
94
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+ |
|
|
95
|
-
Terminology Registry
|
|
98
|
+
Terminology Registry [%crawler-status%] |
|
|
96
99
|
([%ms%] ms)
|
|
97
100
|
[%sponsorMessage%]
|
|
98
101
|
</p>
|