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.
Files changed (277) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/FHIRsmith.png +0 -0
  3. package/README.md +277 -0
  4. package/config-template.json +144 -0
  5. package/library/folder-setup.js +58 -0
  6. package/library/html-server.js +166 -0
  7. package/library/html.js +835 -0
  8. package/library/i18nsupport.js +259 -0
  9. package/library/languages.js +779 -0
  10. package/library/logger-telnet.js +205 -0
  11. package/library/logger.js +279 -0
  12. package/library/package-manager.js +876 -0
  13. package/library/utilities.js +196 -0
  14. package/library/version-utilities.js +1056 -0
  15. package/npmprojector/config-example.json +13 -0
  16. package/npmprojector/indexer.js +394 -0
  17. package/npmprojector/npmprojector.js +395 -0
  18. package/npmprojector/readme.md +174 -0
  19. package/npmprojector/watcher.js +335 -0
  20. package/package.json +119 -0
  21. package/packages/package-crawler.js +846 -0
  22. package/packages/packages-template.html +126 -0
  23. package/packages/packages.js +2838 -0
  24. package/passwords.ini +2 -0
  25. package/publisher/publisher-template.html +208 -0
  26. package/publisher/publisher.js +2167 -0
  27. package/publisher/task-draft.js +458 -0
  28. package/registry/api.js +735 -0
  29. package/registry/crawler.js +637 -0
  30. package/registry/model.js +513 -0
  31. package/registry/readme.md +243 -0
  32. package/registry/registry-data.json +121015 -0
  33. package/registry/registry-template.html +126 -0
  34. package/registry/registry.js +1395 -0
  35. package/registry/test-runner.js +237 -0
  36. package/root-template.html +124 -0
  37. package/server.js +524 -0
  38. package/shl/private-key.pem +5 -0
  39. package/shl/public-key.pem +18 -0
  40. package/shl/shl.js +1125 -0
  41. package/shl/vhl.js +69 -0
  42. package/static/FHIRsmith128.png +0 -0
  43. package/static/FHIRsmith16.png +0 -0
  44. package/static/FHIRsmith32.png +0 -0
  45. package/static/FHIRsmith64.png +0 -0
  46. package/static/assets/css/bootstrap-fhir.css +5302 -0
  47. package/static/assets/css/bootstrap-glyphicons.css +2 -0
  48. package/static/assets/css/bootstrap.css +4097 -0
  49. package/static/assets/css/jquery-ui.css +523 -0
  50. package/static/assets/css/jquery-ui.structure.css +863 -0
  51. package/static/assets/css/jquery-ui.structure.min.css +5 -0
  52. package/static/assets/css/jquery-ui.theme.css +439 -0
  53. package/static/assets/css/jquery-ui.theme.min.css +5 -0
  54. package/static/assets/css/jquery.ui.all.css +7 -0
  55. package/static/assets/css/modules.css +18 -0
  56. package/static/assets/css/project.css +367 -0
  57. package/static/assets/css/pygments-manni.css +66 -0
  58. package/static/assets/css/tags.css +74 -0
  59. package/static/assets/css/xml.css +2 -0
  60. package/static/assets/fonts/glyphiconshalflings-regular.eot +0 -0
  61. package/static/assets/fonts/glyphiconshalflings-regular.otf +0 -0
  62. package/static/assets/fonts/glyphiconshalflings-regular.svg +175 -0
  63. package/static/assets/fonts/glyphiconshalflings-regular.ttf +0 -0
  64. package/static/assets/fonts/glyphiconshalflings-regular.woff +0 -0
  65. package/static/assets/ico/apple-touch-icon-114-precomposed.png +0 -0
  66. package/static/assets/ico/apple-touch-icon-144-precomposed.png +0 -0
  67. package/static/assets/ico/apple-touch-icon-57-precomposed.png +0 -0
  68. package/static/assets/ico/apple-touch-icon-72-precomposed.png +0 -0
  69. package/static/assets/ico/favicon.ico +0 -0
  70. package/static/assets/ico/favicon.png +0 -0
  71. package/static/assets/images/fhir-logo-www.png +0 -0
  72. package/static/assets/images/fhir-logo.png +0 -0
  73. package/static/assets/images/hl7-logo.png +0 -0
  74. package/static/assets/images/logo_ansinew.jpg +0 -0
  75. package/static/assets/images/search.png +0 -0
  76. package/static/assets/images/stripe.png +0 -0
  77. package/static/assets/images/target.png +0 -0
  78. package/static/assets/images/tx-registry-root.gif +0 -0
  79. package/static/assets/images/tx-registry.png +0 -0
  80. package/static/assets/images/tx-server.png +0 -0
  81. package/static/assets/images/tx-version.png +0 -0
  82. package/static/assets/js/bootstrap.min.js +6 -0
  83. package/static/assets/js/fhir-gw.js +259 -0
  84. package/static/assets/js/fhir.js +2 -0
  85. package/static/assets/js/html5shiv.js +8 -0
  86. package/static/assets/js/jcookie.js +96 -0
  87. package/static/assets/js/jquery-ui.min.js +6 -0
  88. package/static/assets/js/jquery.js +10716 -0
  89. package/static/assets/js/jquery.min.js +2 -0
  90. package/static/assets/js/jquery.ui.core.js +314 -0
  91. package/static/assets/js/jquery.ui.draggable.js +825 -0
  92. package/static/assets/js/jquery.ui.mouse.js +162 -0
  93. package/static/assets/js/jquery.ui.resizable.js +842 -0
  94. package/static/assets/js/jquery.ui.widget.js +268 -0
  95. package/static/assets/js/json2.js +487 -0
  96. package/static/assets/js/jtip.js +97 -0
  97. package/static/assets/js/respond.min.js +6 -0
  98. package/static/assets/js/statuspage.js +70 -0
  99. package/static/assets/js/xml.js +2 -0
  100. package/static/dist/js/bootstrap.js +1964 -0
  101. package/static/favicon.png +0 -0
  102. package/static/fhir.css +626 -0
  103. package/static/icon-fhir-16.png +0 -0
  104. package/static/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  105. package/static/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  106. package/static/images/ui-bg_flat_10_000000_40x100.png +0 -0
  107. package/static/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  108. package/static/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  109. package/static/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  110. package/static/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  111. package/static/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  112. package/static/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  113. package/static/images/ui-icons_222222_256x240.png +0 -0
  114. package/static/images/ui-icons_228ef1_256x240.png +0 -0
  115. package/static/images/ui-icons_ef8c08_256x240.png +0 -0
  116. package/static/images/ui-icons_ffd27a_256x240.png +0 -0
  117. package/static/images/ui-icons_ffffff_256x240.png +0 -0
  118. package/static/js/jquery.effects.blind.js +49 -0
  119. package/static/js/jquery.effects.bounce.js +78 -0
  120. package/static/js/jquery.effects.clip.js +54 -0
  121. package/static/js/jquery.effects.core.js +763 -0
  122. package/static/js/jquery.effects.drop.js +50 -0
  123. package/static/js/jquery.effects.explode.js +79 -0
  124. package/static/js/jquery.effects.fade.js +32 -0
  125. package/static/js/jquery.effects.fold.js +56 -0
  126. package/static/js/jquery.effects.highlight.js +50 -0
  127. package/static/js/jquery.effects.pulsate.js +51 -0
  128. package/static/js/jquery.effects.scale.js +178 -0
  129. package/static/js/jquery.effects.shake.js +57 -0
  130. package/static/js/jquery.effects.slide.js +50 -0
  131. package/static/js/jquery.effects.transfer.js +45 -0
  132. package/static/js/jquery.ui.accordion.js +611 -0
  133. package/static/js/jquery.ui.autocomplete.js +612 -0
  134. package/static/js/jquery.ui.button.js +416 -0
  135. package/static/js/jquery.ui.datepicker.js +1823 -0
  136. package/static/js/jquery.ui.dialog.js +878 -0
  137. package/static/js/jquery.ui.droppable.js +296 -0
  138. package/static/js/jquery.ui.position.js +252 -0
  139. package/static/js/jquery.ui.progressbar.js +109 -0
  140. package/static/js/jquery.ui.selectable.js +266 -0
  141. package/static/js/jquery.ui.slider.js +666 -0
  142. package/static/js/jquery.ui.sortable.js +1077 -0
  143. package/static/js/jquery.ui.tabs.js +758 -0
  144. package/stats.js +80 -0
  145. package/test-cache/vsac/vsac-valuesets.db +0 -0
  146. package/token/nginx_passport_setup.md +383 -0
  147. package/token/security_guide.md +294 -0
  148. package/token/token-template.html +330 -0
  149. package/token/token.js +1300 -0
  150. package/translations/Messages.properties +1510 -0
  151. package/translations/Messages_ar.properties +1399 -0
  152. package/translations/Messages_de.properties +836 -0
  153. package/translations/Messages_es.properties +737 -0
  154. package/translations/Messages_fr.properties +1 -0
  155. package/translations/Messages_ja.properties +893 -0
  156. package/translations/Messages_nl.properties +1357 -0
  157. package/translations/Messages_pt.properties +1302 -0
  158. package/translations/Messages_ru.properties +1 -0
  159. package/translations/Messages_uz.properties +1 -0
  160. package/translations/Messages_zh.properties +1 -0
  161. package/translations/rendering-phrases.properties +1128 -0
  162. package/translations/rendering-phrases_ar.properties +1091 -0
  163. package/translations/rendering-phrases_de.properties +6 -0
  164. package/translations/rendering-phrases_es.properties +6 -0
  165. package/translations/rendering-phrases_fr.properties +624 -0
  166. package/translations/rendering-phrases_ja.properties +21 -0
  167. package/translations/rendering-phrases_nl.properties +970 -0
  168. package/translations/rendering-phrases_pt.properties +1020 -0
  169. package/translations/rendering-phrases_ru.properties +1094 -0
  170. package/translations/rendering-phrases_uz.properties +1 -0
  171. package/translations/rendering-phrases_zh.properties +1 -0
  172. package/tx/README.md +418 -0
  173. package/tx/cm/cm-api.js +110 -0
  174. package/tx/cm/cm-database.js +735 -0
  175. package/tx/cm/cm-package.js +325 -0
  176. package/tx/cs/cs-api.js +789 -0
  177. package/tx/cs/cs-areacode.js +615 -0
  178. package/tx/cs/cs-country.js +1110 -0
  179. package/tx/cs/cs-cpt.js +785 -0
  180. package/tx/cs/cs-cs.js +1579 -0
  181. package/tx/cs/cs-currency.js +539 -0
  182. package/tx/cs/cs-db.js +1321 -0
  183. package/tx/cs/cs-hgvs.js +329 -0
  184. package/tx/cs/cs-lang.js +465 -0
  185. package/tx/cs/cs-loinc.js +1485 -0
  186. package/tx/cs/cs-mimetypes.js +238 -0
  187. package/tx/cs/cs-ndc.js +704 -0
  188. package/tx/cs/cs-omop.js +1025 -0
  189. package/tx/cs/cs-provider-api.js +43 -0
  190. package/tx/cs/cs-provider-list.js +37 -0
  191. package/tx/cs/cs-rxnorm.js +808 -0
  192. package/tx/cs/cs-snomed.js +1102 -0
  193. package/tx/cs/cs-ucum.js +514 -0
  194. package/tx/cs/cs-unii.js +271 -0
  195. package/tx/cs/cs-uri.js +218 -0
  196. package/tx/cs/cs-usstates.js +305 -0
  197. package/tx/dev.fhir.org.yml +14 -0
  198. package/tx/fixtures/test-cases-setup.json +18 -0
  199. package/tx/fixtures/test-cases.yml +16 -0
  200. package/tx/html/codesystem-operations.liquid +25 -0
  201. package/tx/html/home-metrics.liquid +247 -0
  202. package/tx/html/operations-form.liquid +148 -0
  203. package/tx/html/search-form.liquid +62 -0
  204. package/tx/html/tx-template.html +133 -0
  205. package/tx/html/valueset-operations.liquid +54 -0
  206. package/tx/importers/atc-to-fhir.js +316 -0
  207. package/tx/importers/import-loinc.module.js +1536 -0
  208. package/tx/importers/import-ndc.module.js +1088 -0
  209. package/tx/importers/import-rxnorm.module.js +898 -0
  210. package/tx/importers/import-sct.module.js +2457 -0
  211. package/tx/importers/import-unii.module.js +601 -0
  212. package/tx/importers/readme.md +453 -0
  213. package/tx/importers/subset-loinc.module.js +1081 -0
  214. package/tx/importers/subset-rxnorm.module.js +938 -0
  215. package/tx/importers/tx-import-base.js +351 -0
  216. package/tx/importers/tx-import-settings.js +310 -0
  217. package/tx/importers/tx-import.js +357 -0
  218. package/tx/library/canonical-resource.js +88 -0
  219. package/tx/library/capabilitystatement.js +292 -0
  220. package/tx/library/codesystem.js +774 -0
  221. package/tx/library/conceptmap.js +568 -0
  222. package/tx/library/designations.js +932 -0
  223. package/tx/library/errors.js +77 -0
  224. package/tx/library/extensions.js +117 -0
  225. package/tx/library/namingsystem.js +322 -0
  226. package/tx/library/operation-outcome.js +127 -0
  227. package/tx/library/parameters.js +105 -0
  228. package/tx/library/renderer.js +1559 -0
  229. package/tx/library/terminologycapabilities.js +418 -0
  230. package/tx/library/ucum-parsers.js +1029 -0
  231. package/tx/library/ucum-service.js +370 -0
  232. package/tx/library/ucum-types.js +1099 -0
  233. package/tx/library/valueset.js +543 -0
  234. package/tx/library.js +676 -0
  235. package/tx/ocl/cm-ocl.js +106 -0
  236. package/tx/ocl/cs-ocl.js +39 -0
  237. package/tx/ocl/vs-ocl.js +105 -0
  238. package/tx/operation-context.js +568 -0
  239. package/tx/params.js +613 -0
  240. package/tx/provider.js +403 -0
  241. package/tx/sct/ecl.js +1560 -0
  242. package/tx/sct/expressions.js +2077 -0
  243. package/tx/sct/structures.js +1396 -0
  244. package/tx/tx-html.js +1063 -0
  245. package/tx/tx.fhir.org.yml +39 -0
  246. package/tx/tx.js +927 -0
  247. package/tx/vs/vs-api.js +112 -0
  248. package/tx/vs/vs-database.js +786 -0
  249. package/tx/vs/vs-package.js +358 -0
  250. package/tx/vs/vs-vsac.js +366 -0
  251. package/tx/workers/batch-validate.js +129 -0
  252. package/tx/workers/batch.js +361 -0
  253. package/tx/workers/closure.js +32 -0
  254. package/tx/workers/expand.js +1845 -0
  255. package/tx/workers/lookup.js +407 -0
  256. package/tx/workers/metadata.js +467 -0
  257. package/tx/workers/operations.js +34 -0
  258. package/tx/workers/read.js +164 -0
  259. package/tx/workers/search.js +384 -0
  260. package/tx/workers/subsumes.js +334 -0
  261. package/tx/workers/translate.js +492 -0
  262. package/tx/workers/validate.js +2504 -0
  263. package/tx/workers/worker.js +904 -0
  264. package/tx/xml/capabilitystatement-xml.js +63 -0
  265. package/tx/xml/codesystem-xml.js +62 -0
  266. package/tx/xml/conceptmap-xml.js +65 -0
  267. package/tx/xml/namingsystem-xml.js +65 -0
  268. package/tx/xml/operationoutcome-xml.js +127 -0
  269. package/tx/xml/parameters-xml.js +312 -0
  270. package/tx/xml/terminologycapabilities-xml.js +64 -0
  271. package/tx/xml/valueset-xml.js +64 -0
  272. package/tx/xml/xml-base.js +603 -0
  273. package/vcl/vcl-parser.js +1098 -0
  274. package/vcl/vcl.js +253 -0
  275. package/windows-install.js +19 -0
  276. package/xig/xig-template.html +124 -0
  277. 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
+ # ![🔥](../static/FHIRsmith64.png) 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
@@ -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
+ };