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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Rendering = one,other
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Rendering = one,other
|
package/tx/README.md
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
#  TX Module - FHIR Terminology Server
|
|
2
|
+
|
|
3
|
+
The TX module provides FHIR terminology services for CodeSystem, ValueSet, and ConceptMap resources. It supports multiple endpoints at different FHIR versions, all backed by a shared terminology library. It is the reference terminology server for the FHIR community and the FHIR terminology ecosystem.
|
|
4
|
+
|
|
5
|
+
## Todo
|
|
6
|
+
|
|
7
|
+
* More work on the HTML interface (external code systems, global functions, render capability statements)
|
|
8
|
+
* add more tests for the code system providers - filters, extended lookup, designations and languages
|
|
9
|
+
* more refactoring in validate.js and expand.js
|
|
10
|
+
* full batch support
|
|
11
|
+
* check vsac support
|
|
12
|
+
* get tx tests running in pipelines
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
Unlike other modules in this server that mount at a single path (e.g., `/shl`, `/packages`), the TX module registers multiple endpoints directly at the root level. Each endpoint is configured with its own path, FHIR version, and optional context string.
|
|
17
|
+
|
|
18
|
+
When a request arrives at an endpoint, the module:
|
|
19
|
+
1. Creates a Provider instance from the shared Library using the configured FHIR version and context
|
|
20
|
+
2. Passes the Provider to the appropriate worker to handle the operation
|
|
21
|
+
3. Returns the FHIR-compliant response
|
|
22
|
+
|
|
23
|
+
## Configuration
|
|
24
|
+
|
|
25
|
+
Add the `tx` section to your `config.json`:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"modules": {
|
|
30
|
+
"tx": {
|
|
31
|
+
"enabled": true,
|
|
32
|
+
"librarySource": "/path/to/library.yml",
|
|
33
|
+
"cacheTimeout": 30,
|
|
34
|
+
"expansionCacheSize": 1000,
|
|
35
|
+
"expansionCacheMemoryThreshold": 0,
|
|
36
|
+
"endpoints": [
|
|
37
|
+
{
|
|
38
|
+
"path": "/tx/r5",
|
|
39
|
+
"fhirVersion": 5,
|
|
40
|
+
"context": null
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"path": "/tx/r4",
|
|
44
|
+
"fhirVersion": 4,
|
|
45
|
+
"context": null
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"path": "/tx/r3",
|
|
49
|
+
"fhirVersion": 3,
|
|
50
|
+
"context": null
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"path": "/tx/r4/demo",
|
|
54
|
+
"fhirVersion": 4,
|
|
55
|
+
"context": "demo"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Configuration Options
|
|
64
|
+
|
|
65
|
+
| Option | Type | Required | Description |
|
|
66
|
+
|--------|------|----------|-------------|
|
|
67
|
+
| `enabled` | boolean | Yes | Whether the module is enabled |
|
|
68
|
+
| `cacheTimeout` | integer | No | How many minutes to keep client side caches (for cache-id parameter). Default: 30 |
|
|
69
|
+
| `expansionCacheSize` | integer | No | Maximum number of expanded ValueSets to cache. Default: 1000 |
|
|
70
|
+
| `expansionCacheMemoryThreshold` | integer | No | Heap memory usage in MB that triggers evicting oldest half of expansion cache. 0 = disabled. Default: 0 |
|
|
71
|
+
| `librarySource` | string | Yes | Path to the YAML file that defines the terminology sources to load |
|
|
72
|
+
| `endpoints` | array | Yes | List of endpoint configurations (at least one required) |
|
|
73
|
+
|
|
74
|
+
### Endpoint Configuration
|
|
75
|
+
|
|
76
|
+
Each endpoint in the `endpoints` array has:
|
|
77
|
+
|
|
78
|
+
| Option | Type | Required | Description |
|
|
79
|
+
|--------|------|----------|-------------|
|
|
80
|
+
| `path` | string | Yes | The URL path where this endpoint will be mounted (e.g., `/tx/r4`) |
|
|
81
|
+
| `fhirVersion` | number | Yes | FHIR version: `3` (STU3), `4` (R4), `5` (R5), or `6` (R6) |
|
|
82
|
+
| `context` | string | No | Optional context string passed to the Library when creating Providers |
|
|
83
|
+
|
|
84
|
+
**Note:** Endpoint paths must be unique. The module will throw an error if duplicate paths are configured or if a path conflicts with another module.
|
|
85
|
+
|
|
86
|
+
## Supported Operations
|
|
87
|
+
|
|
88
|
+
Each endpoint provides the following FHIR terminology operations:
|
|
89
|
+
|
|
90
|
+
### CodeSystem Operations
|
|
91
|
+
|
|
92
|
+
| Operation | Endpoints | Methods |
|
|
93
|
+
|-----------|-----------|---------|
|
|
94
|
+
| Read | `GET /{path}/CodeSystem/{id}` | GET |
|
|
95
|
+
| Search | `GET /{path}/CodeSystem?{params}` | GET, POST |
|
|
96
|
+
| $lookup | `GET/POST /{path}/CodeSystem/$lookup` | GET, POST |
|
|
97
|
+
| $lookup (instance) | `GET/POST /{path}/CodeSystem/{id}/$lookup` | GET, POST |
|
|
98
|
+
| $validate-code | `GET/POST /{path}/CodeSystem/$validate-code` | GET, POST |
|
|
99
|
+
| $validate-code (instance) | `GET/POST /{path}/CodeSystem/{id}/$validate-code` | GET, POST |
|
|
100
|
+
| $subsumes | `GET/POST /{path}/CodeSystem/$subsumes` | GET, POST |
|
|
101
|
+
| $subsumes (instance) | `GET/POST /{path}/CodeSystem/{id}/$subsumes` | GET, POST |
|
|
102
|
+
|
|
103
|
+
### ValueSet Operations
|
|
104
|
+
|
|
105
|
+
| Operation | Endpoints | Methods |
|
|
106
|
+
|-----------|-----------|---------|
|
|
107
|
+
| Read | `GET /{path}/ValueSet/{id}` | GET |
|
|
108
|
+
| Search | `GET /{path}/ValueSet?{params}` | GET, POST |
|
|
109
|
+
| $expand | `GET/POST /{path}/ValueSet/$expand` | GET, POST |
|
|
110
|
+
| $expand (instance) | `GET/POST /{path}/ValueSet/{id}/$expand` | GET, POST |
|
|
111
|
+
| $validate-code | `GET/POST /{path}/ValueSet/$validate-code` | GET, POST |
|
|
112
|
+
| $validate-code (instance) | `GET/POST /{path}/ValueSet/{id}/$validate-code` | GET, POST |
|
|
113
|
+
|
|
114
|
+
### ConceptMap Operations
|
|
115
|
+
|
|
116
|
+
| Operation | Endpoints | Methods |
|
|
117
|
+
|-----------|-----------|---------|
|
|
118
|
+
| Read | `GET /{path}/ConceptMap/{id}` | GET |
|
|
119
|
+
| Search | `GET /{path}/ConceptMap?{params}` | GET, POST |
|
|
120
|
+
| $translate | `GET/POST /{path}/ConceptMap/$translate` | GET, POST |
|
|
121
|
+
| $translate (instance) | `GET/POST /{path}/ConceptMap/{id}/$translate` | GET, POST |
|
|
122
|
+
| $closure | `GET/POST /{path}/ConceptMap/$closure` | GET, POST |
|
|
123
|
+
|
|
124
|
+
### Metadata
|
|
125
|
+
|
|
126
|
+
Each endpoint also provides:
|
|
127
|
+
- `GET /{path}/metadata` - Returns a CapabilityStatement describing the endpoint's capabilities
|
|
128
|
+
- `GET /{path}/` - Returns basic endpoint information
|
|
129
|
+
|
|
130
|
+
## Library Configuration
|
|
131
|
+
|
|
132
|
+
The library - the source to load - is configured using a YAML file.
|
|
133
|
+
|
|
134
|
+
### YAML Structure
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
base:
|
|
138
|
+
url: https://example.com/terminology-files
|
|
139
|
+
|
|
140
|
+
sources:
|
|
141
|
+
- internal:lang
|
|
142
|
+
- ucum:tx/data/ucum-essence.xml
|
|
143
|
+
- snomed!:sct_intl_20250201.cache
|
|
144
|
+
- npm:hl7.terminology
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Base Configuration
|
|
148
|
+
|
|
149
|
+
| Option | Type | Required | Description |
|
|
150
|
+
|--------|------|----------|-------------|
|
|
151
|
+
| `url` | string | Yes | Base URL for downloading external terminology files. Files specified in sources (for types that require downloads) will be fetched from this URL if not already cached locally. |
|
|
152
|
+
|
|
153
|
+
The idea here is that the configuration file is probably in a git repo somewhere, but lots of the content it points to isn't and can't or
|
|
154
|
+
shouldn't be - too big. Note that that files in the list below are considered to never change once they are created.
|
|
155
|
+
|
|
156
|
+
### Source Format
|
|
157
|
+
|
|
158
|
+
Each source entry follows the format:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
type[!]:details
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- **type**: The source type (see Source Types below)
|
|
165
|
+
- **!** (optional): Append to type to mark this source as the default for its code system. When multiple versions of the same code system are loaded, the default is used when no version is specified.
|
|
166
|
+
- **details**: Type-specific configuration (filename, package name, or internal provider name)
|
|
167
|
+
|
|
168
|
+
### Source Types
|
|
169
|
+
|
|
170
|
+
#### `internal` - Built-in Code Systems
|
|
171
|
+
|
|
172
|
+
Built-in code system providers that are compiled into the server. These don't require external files.
|
|
173
|
+
|
|
174
|
+
```yaml
|
|
175
|
+
- internal:lang # IETF BCP-47 language codes
|
|
176
|
+
- internal:country # ISO 3166 country codes
|
|
177
|
+
- internal:currency # ISO 4217 currency codes
|
|
178
|
+
- internal:areacode # Telephone area codes
|
|
179
|
+
- internal:mimetypes # MIME types
|
|
180
|
+
- internal:usstates # US state codes
|
|
181
|
+
- internal:hgvs # HGVS (Human Genome Variation Society) nomenclature
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Note:** The `!` default marker is not supported for internal providers.
|
|
185
|
+
|
|
186
|
+
#### `ucum` - UCUM (Unified Code for Units of Measure)
|
|
187
|
+
|
|
188
|
+
Loads UCUM from a local XML file (ucum-essence format).
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
- ucum:tx/data/ucum-essence.xml
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The path is relative to the server's base directory. The UCUM essence XML file can be obtained from https://ucum.org.
|
|
195
|
+
|
|
196
|
+
#### `loinc` - LOINC (Logical Observation Identifiers Names and Codes)
|
|
197
|
+
|
|
198
|
+
Loads LOINC from a SQLite database file.
|
|
199
|
+
|
|
200
|
+
```yaml
|
|
201
|
+
- loinc:loinc-2.81-b.db
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The filename is downloaded from the base URL if not cached. Database files must be in the server's proprietary format.
|
|
205
|
+
The file is built by importing LOINC (to be documented)
|
|
206
|
+
|
|
207
|
+
#### `rxnorm` - RxNorm
|
|
208
|
+
|
|
209
|
+
Loads RxNorm drug terminology from a SQLite database file.
|
|
210
|
+
|
|
211
|
+
```yaml
|
|
212
|
+
- rxnorm:rxnorm_02032025-a.db
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
The file is built by importing RxNorm (to be documented)
|
|
216
|
+
|
|
217
|
+
#### `ndc` - NDC (National Drug Code)
|
|
218
|
+
|
|
219
|
+
Loads NDC codes from a SQLite database file.
|
|
220
|
+
|
|
221
|
+
```yaml
|
|
222
|
+
- ndc:ndc-20211101.db
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
#### `unii` - UNII (Unique Ingredient Identifier)
|
|
226
|
+
|
|
227
|
+
Loads FDA UNII codes from a SQLite database file.
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
- unii:unii_20240622.db
|
|
231
|
+
```
|
|
232
|
+
The file is built by importing UNII (to be documented)
|
|
233
|
+
|
|
234
|
+
#### `snomed` - SNOMED CT
|
|
235
|
+
|
|
236
|
+
Loads SNOMED CT from a cache file. Multiple editions and versions can be loaded simultaneously.
|
|
237
|
+
|
|
238
|
+
```yaml
|
|
239
|
+
- snomed!:sct_intl_20250201.cache # International edition (default)
|
|
240
|
+
- snomed:sct_intl_20240201.cache # Older international edition
|
|
241
|
+
- snomed:sct_us_20250901.cache # US edition
|
|
242
|
+
- snomed:sct_au_20230731.cache # Australian edition
|
|
243
|
+
- snomed:sct_uk_20230412.cache # UK edition
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Common edition identifiers:
|
|
247
|
+
- `intl` - International
|
|
248
|
+
- `us` - United States
|
|
249
|
+
- `au` - Australia
|
|
250
|
+
- `uk` - United Kingdom
|
|
251
|
+
- `se` - Sweden
|
|
252
|
+
- `be` - Belgium
|
|
253
|
+
- `ch` - Switzerland
|
|
254
|
+
- `dk` - Denmark
|
|
255
|
+
- `nl` - Netherlands
|
|
256
|
+
- `ips` - IPS (International Patient Summary) Free Set
|
|
257
|
+
|
|
258
|
+
The file is built by importing SNOMED CT (to be documented)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
#### `cpt` - CPT (Current Procedural Terminology)
|
|
262
|
+
|
|
263
|
+
Loads CPT codes from a SQLite database file.
|
|
264
|
+
|
|
265
|
+
```yaml
|
|
266
|
+
- cpt:cpt-2023-fragment-0.1.db
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Note:** CPT is copyrighted by the American Medical Association. Ensure you have appropriate licensing.
|
|
270
|
+
|
|
271
|
+
The file is built by importing CPT (to be documented)
|
|
272
|
+
|
|
273
|
+
#### `omop` - OMOP Vocabularies
|
|
274
|
+
|
|
275
|
+
Loads OMOP (Observational Medical Outcomes Partnership) vocabulary mappings from a SQLite database file.
|
|
276
|
+
|
|
277
|
+
```yaml
|
|
278
|
+
- omop:omop_v20250227.db
|
|
279
|
+
```
|
|
280
|
+
The file is built by importing OMOP (to be documented)
|
|
281
|
+
|
|
282
|
+
#### `npm` - FHIR NPM Packages
|
|
283
|
+
|
|
284
|
+
Loads CodeSystem, ValueSet, and ConceptMap resources from FHIR NPM packages. Packages are fetched from the FHIR package registry (packages2.fhir.org).
|
|
285
|
+
|
|
286
|
+
```yaml
|
|
287
|
+
- npm:hl7.terminology # HL7 Terminology (THO)
|
|
288
|
+
- npm:fhir.tx.support.r4 # TX support package
|
|
289
|
+
- npm:ihe.formatcode.fhir # IHE format codes
|
|
290
|
+
- npm:fhir.dicom # DICOM terminology
|
|
291
|
+
- npm:hl7.fhir.us.core # US Core profiles
|
|
292
|
+
- npm:us.nlm.vsac # VSAC value sets
|
|
293
|
+
- npm:us.cdc.phinvads # CDC PHIN VADS
|
|
294
|
+
- npm:hl7.fhir.uv.sdc # Structured Data Capture
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
You can specify a version using the `#` syntax:
|
|
298
|
+
|
|
299
|
+
```yaml
|
|
300
|
+
- npm:hl7.terminology#5.0.0
|
|
301
|
+
- npm:hl7.fhir.us.core#6.1.0
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
If no version is specified, the latest released version is fetched.
|
|
305
|
+
|
|
306
|
+
### Default Marker (`!`)
|
|
307
|
+
|
|
308
|
+
When multiple versions of the same code system are loaded, append `!` to mark one as the default:
|
|
309
|
+
|
|
310
|
+
```yaml
|
|
311
|
+
- snomed!:sct_intl_20250201.cache # This is the default SNOMED CT
|
|
312
|
+
- snomed:sct_intl_20240201.cache # Also available, but not default
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
When a terminology operation doesn't specify a version, the default version is used. Only one source per code system should be marked as default.
|
|
316
|
+
|
|
317
|
+
### File Caching
|
|
318
|
+
|
|
319
|
+
Files specified in sources (except `internal` and `ucum`) are:
|
|
320
|
+
1. First checked in the local cache folder (`terminology-cache`)
|
|
321
|
+
2. Downloaded from the `base.url` if not present
|
|
322
|
+
3. Cached locally for future use
|
|
323
|
+
|
|
324
|
+
NPM packages are handled separately through the FHIR package registry.
|
|
325
|
+
|
|
326
|
+
### Example Configuration
|
|
327
|
+
|
|
328
|
+
Here's a complete example for a production terminology server:
|
|
329
|
+
|
|
330
|
+
```yaml
|
|
331
|
+
base:
|
|
332
|
+
url: https://storage.googleapis.com/tx-fhir-org
|
|
333
|
+
|
|
334
|
+
sources:
|
|
335
|
+
# Built-in code systems
|
|
336
|
+
- internal:lang
|
|
337
|
+
- internal:country
|
|
338
|
+
- internal:currency
|
|
339
|
+
- internal:mimetypes
|
|
340
|
+
|
|
341
|
+
# Units of measure
|
|
342
|
+
- ucum:tx/data/ucum-essence.xml
|
|
343
|
+
|
|
344
|
+
# Clinical terminologies
|
|
345
|
+
- loinc:loinc-2.81-b.db
|
|
346
|
+
- rxnorm:rxnorm_02032025-a.db
|
|
347
|
+
- snomed!:sct_intl_20250201.cache
|
|
348
|
+
- snomed:sct_us_20250901.cache
|
|
349
|
+
|
|
350
|
+
# FHIR packages
|
|
351
|
+
- npm:hl7.terminology
|
|
352
|
+
- npm:hl7.fhir.us.core
|
|
353
|
+
- npm:us.nlm.vsac
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Also see tx.fhir.org.yml for the production configuration for tx.fhir.org
|
|
357
|
+
|
|
358
|
+
## Architecture
|
|
359
|
+
|
|
360
|
+
```
|
|
361
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
362
|
+
│ Library │
|
|
363
|
+
│ (Loaded once at startup from YAML) │
|
|
364
|
+
│ - Code System Factories │
|
|
365
|
+
│ - Code System Providers │
|
|
366
|
+
│ - Value Set Providers │
|
|
367
|
+
└─────────────────────────────────────────────────────────────┘
|
|
368
|
+
│
|
|
369
|
+
│ cloneWithFhirVersion(version, context)
|
|
370
|
+
▼
|
|
371
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
372
|
+
│ Provider │
|
|
373
|
+
│ (Created per-request with FHIR version context) │
|
|
374
|
+
└─────────────────────────────────────────────────────────────┘
|
|
375
|
+
│
|
|
376
|
+
┌───────────────────┼───────────────────┐
|
|
377
|
+
▼ ▼ ▼
|
|
378
|
+
┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
379
|
+
│ /tx/r5 │ │ /tx/r4 │ │ /tx/r3 │
|
|
380
|
+
│ FHIR R5 │ │ FHIR R4 │ │ FHIR R3 │
|
|
381
|
+
└──────────┘ └──────────┘ └──────────┘
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## Workers
|
|
385
|
+
|
|
386
|
+
The module uses worker classes to handle specific operations:
|
|
387
|
+
|
|
388
|
+
| Worker | Operations |
|
|
389
|
+
|--------|------------|
|
|
390
|
+
| `read.js` | Resource read operations |
|
|
391
|
+
| `search.js` | Resource search operations |
|
|
392
|
+
| `lookup.js` | CodeSystem $lookup |
|
|
393
|
+
| `subsumes.js` | CodeSystem $subsumes |
|
|
394
|
+
| `validate.js` | CodeSystem and ValueSet $validate-code |
|
|
395
|
+
| `expand.js` | ValueSet $expand |
|
|
396
|
+
| `translate.js` | ConceptMap $translate |
|
|
397
|
+
| `closure.js` | ConceptMap $closure |
|
|
398
|
+
|
|
399
|
+
## Error Handling
|
|
400
|
+
|
|
401
|
+
All errors are returned as FHIR OperationOutcome resources:
|
|
402
|
+
|
|
403
|
+
```json
|
|
404
|
+
{
|
|
405
|
+
"resourceType": "OperationOutcome",
|
|
406
|
+
"issue": [{
|
|
407
|
+
"severity": "error",
|
|
408
|
+
"code": "not-found",
|
|
409
|
+
"diagnostics": "CodeSystem/example not found"
|
|
410
|
+
}]
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## Notes
|
|
415
|
+
|
|
416
|
+
- Write operations (PUT, POST, DELETE, PATCH) on resources are not supported and return 405 Method Not Allowed
|
|
417
|
+
- The Library is loaded once at startup; changes to the YAML source require a server restart
|
|
418
|
+
- Each endpoint has it's own Provider instance
|
package/tx/cm/cm-api.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base class for Concept Map providers
|
|
3
|
+
* Defines the interface that all Concept Map providers must implement
|
|
4
|
+
*/
|
|
5
|
+
class AbstractConceptMapProvider {
|
|
6
|
+
/**
|
|
7
|
+
* {int} Unique number assigned to this provider
|
|
8
|
+
*/
|
|
9
|
+
spaceId;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* ensure that the ids on the Concept Maps are unique, if they are
|
|
13
|
+
* in the global namespace
|
|
14
|
+
*
|
|
15
|
+
* @param {Set<String>} ids
|
|
16
|
+
*/
|
|
17
|
+
// eslint-disable-next-line no-unused-vars
|
|
18
|
+
assignIds(ids) {
|
|
19
|
+
throw new Error('assignIds must be implemented by AbstractConceptMapProvider subclass');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Fetches a specific Concept Map by URL and version
|
|
24
|
+
* @param {string} url - The URL/identifier of the Concept Map
|
|
25
|
+
* @param {string} version - The version of the Concept Map
|
|
26
|
+
* @returns {Promise<ConceptMap>} The requested Concept Map
|
|
27
|
+
* @throws {Error} Must be implemented by subclasses
|
|
28
|
+
*/
|
|
29
|
+
// eslint-disable-next-line no-unused-vars
|
|
30
|
+
async fetchConceptMap(url, version) {
|
|
31
|
+
throw new Error('fetchConceptMap must be implemented by subclass');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Fetches a specific Concept Map by id. ConceptMap providers must enforce that Concept Map ids are unique
|
|
36
|
+
* either globally (as enforced by assignIds) or in their space
|
|
37
|
+
*
|
|
38
|
+
* @param {string} id - The id of the Concept Map
|
|
39
|
+
* @returns {Promise<ConceptMap>} The requested Concept Map
|
|
40
|
+
* @throws {Error} Must be implemented by subclasses
|
|
41
|
+
*/
|
|
42
|
+
// eslint-disable-next-line no-unused-vars
|
|
43
|
+
async fetchConceptMapById(id) {
|
|
44
|
+
throw new Error('fetchConceptMapById must be implemented by subclass');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Searches for Concept Maps based on provided criteria
|
|
49
|
+
* @param {Array<{name: string, value: string}>} searchParams - List of name/value pairs for search criteria
|
|
50
|
+
* @returns {Promise<Array<ConceptMap>>} List of matching Concept Maps
|
|
51
|
+
* @throws {Error} Must be implemented by subclasses
|
|
52
|
+
*/
|
|
53
|
+
// eslint-disable-next-line no-unused-vars
|
|
54
|
+
async searchConceptMaps(searchParams, elements = null) {
|
|
55
|
+
throw new Error('searchConceptMaps must be implemented by subclass');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Validates search parameters
|
|
60
|
+
* @param {Array<{name: string, value: string}>} searchParams - Search parameters to validate
|
|
61
|
+
* @protected
|
|
62
|
+
*/
|
|
63
|
+
_validateSearchParams(searchParams) {
|
|
64
|
+
if (!Array.isArray(searchParams)) {
|
|
65
|
+
throw new Error('Search parameters must be an array');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for (const param of searchParams) {
|
|
69
|
+
if (!param || typeof param !== 'object') {
|
|
70
|
+
throw new Error('Each search parameter must be an object');
|
|
71
|
+
}
|
|
72
|
+
if (typeof param.name !== 'string' || typeof param.value !== 'string') {
|
|
73
|
+
throw new Error('Search parameter must have string name and value properties');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Validates URL and version parameters
|
|
80
|
+
* @param {string} url - URL to validate
|
|
81
|
+
* @param {string} version - Version to validate
|
|
82
|
+
* @protected
|
|
83
|
+
*/
|
|
84
|
+
_validateFetchParams(url, version) {
|
|
85
|
+
if (typeof url !== 'string' || !url.trim()) {
|
|
86
|
+
throw new Error('URL must be a non-empty string');
|
|
87
|
+
}
|
|
88
|
+
if (version != null && typeof version !== 'string') {
|
|
89
|
+
throw new Error('Version must be a string');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// eslint-disable-next-line no-unused-vars
|
|
94
|
+
async findConceptMapForTranslation(opContext, conceptMaps, sourceSystem, sourceScope, targetScope, targetSystem) {
|
|
95
|
+
// nothing
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
cmCount() {
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async close() {
|
|
103
|
+
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = {
|
|
109
|
+
AbstractConceptMapProvider
|
|
110
|
+
};
|