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.
Files changed (73) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +3 -2
  3. package/config-template.json +20 -0
  4. package/library/fhir-openapi-schema.js +441 -0
  5. package/library/html-server.js +9 -3
  6. package/library/languages.js +15 -0
  7. package/library/npm-audit.js +265 -0
  8. package/library/openapi-doc.js +557 -0
  9. package/library/same-origin.js +62 -0
  10. package/library/utilities.js +21 -0
  11. package/nginx.md +17 -9
  12. package/package.json +10 -4
  13. package/packages/openapi.js +13 -0
  14. package/packages/openapi.yaml +603 -0
  15. package/packages/packages-template.html +4 -2
  16. package/packages/packages.js +286 -81
  17. package/packages/readme.md +120 -0
  18. package/publisher/publisher-template.html +1 -0
  19. package/publisher/publisher.js +95 -42
  20. package/registry/api.js +117 -41
  21. package/registry/crawler.js +24 -0
  22. package/registry/fhirsmith-releases.js +170 -0
  23. package/registry/model.js +10 -0
  24. package/registry/openapi.js +13 -0
  25. package/registry/openapi.yaml +311 -0
  26. package/registry/readme.md +107 -208
  27. package/registry/registry-template.html +4 -1
  28. package/registry/registry.js +183 -20
  29. package/server.js +25 -6
  30. package/testing/openapi-schemas.config.js +58 -0
  31. package/testing/openapi-schemas.json +1920 -0
  32. package/testing/openapi.js +15 -0
  33. package/testing/openapi.yaml +273 -0
  34. package/testing/readme.md +75 -1
  35. package/testing/render.js +270 -29
  36. package/testing/search.js +1 -1
  37. package/testing/store.js +152 -8
  38. package/testing/testing-template.html +2 -0
  39. package/testing/testing.js +307 -9
  40. package/translations/Messages.properties +1 -0
  41. package/tx/README.md +58 -0
  42. package/tx/cm/cm-database.js +10 -1
  43. package/tx/cm/cm-package.js +8 -1
  44. package/tx/cs/cs-rxnorm.js +23 -6
  45. package/tx/cs/cs-snomed.js +3 -72
  46. package/tx/html/tx-template.html +2 -0
  47. package/tx/library/canonical-resource.js +50 -1
  48. package/tx/library/codesystem.js +1 -0
  49. package/tx/library/conceptmap.js +1 -0
  50. package/tx/library/valueset.js +16 -0
  51. package/tx/library.js +17 -2
  52. package/tx/openapi-operations.js +363 -0
  53. package/tx/openapi-schemas.config.js +118 -0
  54. package/tx/openapi-schemas.json +7903 -0
  55. package/tx/openapi.js +289 -0
  56. package/tx/openapi.yaml +151 -0
  57. package/tx/operation-context.js +15 -0
  58. package/tx/params.js +3 -12
  59. package/tx/provider.js +10 -1
  60. package/tx/sct/editions.js +70 -0
  61. package/tx/tx-html.js +6 -0
  62. package/tx/tx.js +55 -0
  63. package/tx/vs/vs-database.js +14 -5
  64. package/tx/vs/vs-package.js +10 -0
  65. package/tx/workers/expand.js +37 -18
  66. package/tx/workers/metadata.js +0 -13
  67. package/tx/workers/translate.js +25 -1
  68. package/tx/workers/validate.js +74 -24
  69. package/tx/workers/worker.js +32 -43
  70. package/utilities/extract-schema-json.js +167 -0
  71. package/utilities/generate-openapi-schemas.js +49 -0
  72. package/utilities/submit-test-report.js +1 -1
  73. 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 }
@@ -1,225 +1,124 @@
1
1
  # Terminology Server Registry
2
2
 
3
- A Node.js module for crawling and querying FHIR terminology servers. This module maintains a registry of terminology servers, periodically crawls them to gather capability information, and provides an API to find the best server for specific code systems or value sets.
4
-
5
- ## Architecture
6
-
7
- The module consists of three main components:
8
-
9
- ### 1. Data Model (`registry-model.js`)
10
- - **ServerRegistries**: Top-level container for all registry data
11
- - **ServerRegistry**: Individual registry containing multiple servers
12
- - **ServerInformation**: Server metadata and authoritative designations
13
- - **ServerVersionInformation**: Version-specific server capabilities
14
- - **ServerRow**: Flattened representation for API responses
15
- - **ServerRegistryUtilities**: Helper functions for matching and filtering
16
-
17
- ### 2. Crawler (`registry-crawler.js`)
18
- - Periodically fetches capability statements from configured servers
19
- - Extracts security models, supported code systems, and value sets
20
- - Handles retries and error recovery
21
- - Maintains current state of all servers
22
-
23
- ### 3. API Processor (`registry-api.js`)
24
- - Provides query endpoints for finding servers
25
- - Ranks servers based on:
26
- - Authoritative designation
27
- - Availability (no errors)
28
- - Recency of successful connection
29
- - Number of resources available
30
- - Supports filtering by registry, server, version, and resource
31
-
32
- ## Installation
33
-
34
- ```bash
35
- npm install
36
- ```
37
-
38
- ## Usage
39
-
40
- ### Basic Server Setup
41
-
42
- ```javascript
43
- const express = require('express');
44
- const RegistryCrawler = require('./crawler');
45
- const RegistryAPI = require('./api');
46
-
47
- // Configure crawler
48
- const crawler = new RegistryCrawler({
49
- timeout: 30000,
50
- crawlInterval: 5 * 60 * 1000, // 5 minutes
51
- registryConfigs: [
52
- {
53
- code: 'main',
54
- name: 'Main Registry',
55
- servers: [
56
- {
57
- code: 'tx1',
58
- name: 'TX Server',
59
- authCSList: ['http://loinc.org*'],
60
- versions: [
61
- {
62
- version: '4.0.1',
63
- address: 'https://tx.fhir.org/r4'
64
- }
65
- ]
66
- }
67
- ]
68
- }
69
- ]
70
- });
71
-
72
- // Create API
73
- const api = new RegistryAPI(crawler);
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
- ### Registry Configuration
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
- ```javascript
168
- {
169
- version: '4.0.1', // FHIR version
170
- address: 'https://...' // Version-specific endpoint
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
- ## Authoritative Designations
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
- Servers can be marked as authoritative for specific code systems or value sets. This affects ranking:
98
+ ## Scanning
177
99
 
178
- - Authoritative servers are always ranked first
179
- - Wildcards are supported (e.g., `http://loinc.org*`)
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
- ## Testing
187
-
188
- Run the test suite:
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
- ## Security Models
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 crawler detects the following security models:
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
- - `open`: No authentication required
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
- ## License
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
- BSD-3-Clause
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> &nbsp;|&nbsp;
60
61
  <a href="/tx-reg" style="color: gold">Registry Home</a> &nbsp;|&nbsp;
61
62
  <a href="/tx-reg/resolve" style="color: gold">Resolve</a> &nbsp;|&nbsp;
63
+ <a href="/tx-reg/software" style="color: gold">Software</a> &nbsp;|&nbsp;
62
64
  <a href="/tx-reg/log" style="color: gold">Crawler Log</a> &nbsp;|&nbsp;
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> &copy; HL7.org 2011+. &nbsp;|&nbsp;
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%] &copy; HealthIntersections.com.au 2023+ &nbsp;|&nbsp;
95
- Terminology Registry last updated as of [%crawler-date%] &nbsp;|&nbsp; [%total-packages%] packages &nbsp;|
98
+ Terminology Registry [%crawler-status%] &nbsp;|
96
99
  &nbsp; ([%ms%] ms)
97
100
  [%sponsorMessage%]
98
101
  </p>