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,407 @@
1
+ //
2
+ // Lookup Worker - Handles CodeSystem $lookup operation
3
+ //
4
+ // GET /CodeSystem/$lookup?{params}
5
+ // POST /CodeSystem/$lookup
6
+ // GET /CodeSystem/{id}/$lookup?{params}
7
+ // POST /CodeSystem/{id}/$lookup
8
+ //
9
+
10
+ const { TerminologyWorker } = require('./worker');
11
+ const { FhirCodeSystemProvider } = require('../cs/cs-cs');
12
+ const { Designations} = require("../library/designations");
13
+ const {TxParameters} = require("../params");
14
+ const {Parameters} = require("../library/parameters");
15
+ const {Issue, OperationOutcome} = require("../library/operation-outcome");
16
+
17
+ class LookupWorker extends TerminologyWorker {
18
+ /**
19
+ * @param {OperationContext} opContext - Operation context
20
+ * @param {Logger} log - Logger instance
21
+ * @param {Provider} provider - Provider for code systems and resources
22
+ * @param {LanguageDefinitions} languages - Language definitions
23
+ * @param {I18nSupport} i18n - Internationalization support
24
+ */
25
+ constructor(opContext, log, provider, languages, i18n) {
26
+ super(opContext, log, provider, languages, i18n);
27
+ }
28
+
29
+ /**
30
+ * Get operation name
31
+ * @returns {string}
32
+ */
33
+ opName() {
34
+ return 'lookup';
35
+ }
36
+
37
+ /**
38
+ * Static factory method to handle type-level lookup from Express
39
+ * GET/POST /CodeSystem/$lookup
40
+ * @param {express.Request} req - Express request
41
+ * @param {express.Response} res - Express response
42
+ */
43
+ async handle(req, res) {
44
+ try {
45
+ await this.handleTypeLevelLookup(req, res);
46
+ } catch (error) {
47
+ console.log(error);
48
+ req.logInfo = this.usedSources.join("|")+" - error"+(error.msgId ? " "+error.msgId : "");
49
+ this.log.error(error);
50
+ const statusCode = error.statusCode || 500;
51
+ const issueCode = error.issueCode || 'exception';
52
+ return res.status(statusCode).json({
53
+ resourceType: 'OperationOutcome',
54
+ issue: [{
55
+ severity: 'error',
56
+ code: issueCode,
57
+ diagnostics: error.message
58
+ }]
59
+ });
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Static factory method to handle instance-level lookup from Express
65
+ * GET/POST /CodeSystem/{id}/$lookup
66
+ * @param {express.Request} req - Express request
67
+ * @param {express.Response} res - Express response
68
+ */
69
+ async handleInstance(req, res) {
70
+
71
+ try {
72
+ await this.handleInstanceLevelLookup(req, res);
73
+ } catch (error) {
74
+ req.logInfo = this.usedSources.join("|")+" - error"+(error.msgId ? " "+error.msgId : "");
75
+ this.log.error(error);
76
+ const issueCode = error.issueCode || 'exception';
77
+ return res.status(400).json({
78
+ resourceType: 'OperationOutcome',
79
+ issue: [{
80
+ severity: 'error',
81
+ code: issueCode,
82
+ diagnostics: error.message
83
+ }]
84
+ });
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Handle type-level lookup: /CodeSystem/$lookup
90
+ * CodeSystem identified by system+version params or coding parameter
91
+ */
92
+ async handleTypeLevelLookup(req, res) {
93
+ try {
94
+ this.deadCheck('lookup-type-level');
95
+
96
+ // Handle tx-resource and cache-id parameters from Parameters resource
97
+ if (req.body && req.body.resourceType === 'Parameters') {
98
+ this.setupAdditionalResources(req.body);
99
+ }
100
+
101
+ // Parse parameters from request
102
+ const params = new Parameters(this.buildParameters(req));
103
+ const txp = new TxParameters(this.opContext.i18n.languageDefinitions, this.opContext.i18n);
104
+ txp.readParams(params.jsonObj);
105
+
106
+ // Determine how the code system is identified
107
+ let csProvider;
108
+ let code;
109
+
110
+ if (params.has('coding')) {
111
+ // Coding parameter provided - extract system, version, code
112
+ const coding = params.get('coding');
113
+ if (!coding.system) {
114
+ return res.status(400).json(this.operationOutcome('error', 'invalid',
115
+ 'Coding parameter must include a system'));
116
+ }
117
+ if (!coding.code) {
118
+ return res.status(400).json(this.operationOutcome('error', 'invalid',
119
+ 'Coding parameter must include a code'));
120
+ }
121
+
122
+ // Allow complete or fragment content modes, nullOk = true to handle not-found ourselves
123
+ csProvider = await this.findCodeSystem(coding.system, coding.version || '', txp, ['complete', 'fragment'], true);
124
+ this.seeSourceProvider(csProvider, coding.system);
125
+ code = coding.code;
126
+
127
+ } else if (params.has('system') && params.has('code')) {
128
+ // system + code parameters
129
+ csProvider = await this.findCodeSystem(params.get('system'), params.get('version') || '', txp, ['complete', 'fragment'], true);
130
+ this.seeSourceProvider(csProvider, params.get('system'));
131
+ code = params.get('code');
132
+
133
+ } else {
134
+ return res.status(400).json(this.operationOutcome('error', 'invalid',
135
+ 'Must provide either coding parameter, or system and code parameters'));
136
+ }
137
+
138
+ if (!csProvider) {
139
+ const systemUrl = params.system || params.coding?.system;
140
+ const versionStr = params.version || params.coding?.version;
141
+ const msg = versionStr
142
+ ? `CodeSystem not found: ${systemUrl} version ${versionStr}`
143
+ : `CodeSystem not found: ${systemUrl}`;
144
+ return res.status(404).json(this.operationOutcome('error', 'not-found', msg));
145
+ }
146
+
147
+ // Perform the lookup
148
+ const result = await this.doLookup(csProvider, code, txp);
149
+ return res.status(200).json(result);
150
+ } catch (error) {
151
+ req.logInfo = this.usedSources.join("|")+" - error"+(error.msgId ? " "+error.msgId : "");
152
+ this.log.error(error);
153
+ if (error instanceof Issue) {
154
+ let oo = new OperationOutcome();
155
+ oo.addIssue(error);
156
+ return res.status(error.statusCode || 500).json(oo.jsonObj);
157
+ } else {
158
+ return res.status(error.statusCode || 500).json(this.operationOutcome(
159
+ 'error', error.issueCode || 'exception', error.message));
160
+ }
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Handle instance-level lookup: /CodeSystem/{id}/$lookup
166
+ * CodeSystem identified by resource ID
167
+ */
168
+ async handleInstanceLevelLookup(req, res) {
169
+ try {
170
+ this.deadCheck('lookup-instance-level');
171
+
172
+ const {id} = req.params;
173
+
174
+ // Find the CodeSystem by ID
175
+ let codeSystem = this.provider.getCodeSystemById(this.opContext, id);
176
+ this.seeSourceProvider(codeSystem, id);
177
+
178
+ if (!codeSystem) {
179
+ return res.status(404).json(this.operationOutcome('error', 'not-found',
180
+ `CodeSystem/${id} not found`));
181
+ }
182
+
183
+ // Handle tx-resource and cache-id parameters from Parameters resource
184
+ if (req.body && req.body.resourceType === 'Parameters') {
185
+ this.setupAdditionalResources(req.body);
186
+ }
187
+
188
+ // Parse parameters from request
189
+ const params = new Parameters(this.buildParameters(req));
190
+ const txp = new TxParameters(this.opContext.i18n.languageDefinitions, this.opContext.i18n);
191
+ txp.readParams(params.jsonObj);
192
+
193
+ // For instance-level, code is required (system/version come from the resource)
194
+ let code;
195
+ if (params.has('coding')) {
196
+ code = params.get('coding').code;
197
+ } else if (params.has('code')) {
198
+ code = params.get('code');
199
+ } else {
200
+ return res.status(400).json(this.operationOutcome('error', 'invalid',
201
+ 'Must provide code parameter or coding parameter with code'));
202
+ }
203
+
204
+ // Load any supplements
205
+ const supplements = this.loadSupplements(codeSystem.url, codeSystem.version);
206
+
207
+ // Create a FhirCodeSystemProvider for this CodeSystem
208
+ const csProvider = new FhirCodeSystemProvider(this.opContext, codeSystem, supplements);
209
+
210
+ // Perform the lookup
211
+ const result = await this.doLookup(csProvider, code, txp);
212
+ return res.status(200).json(result);
213
+ } catch (error) {
214
+ req.logInfo = this.usedSources.join("|")+" - error"+(error.msgId ? " "+error.msgId : "");
215
+ this.log.error(error);
216
+ if (error instanceof Issue) {
217
+ let oo = new OperationOutcome();
218
+ oo.addIssue(error);
219
+ return res.status(error.statusCode || 500).json(oo.jsonObj);
220
+ } else {
221
+ return res.status(error.statusCode || 500).json(this.operationOutcome(
222
+ 'error', error.issueCode || 'exception', error.message));
223
+ }
224
+ }
225
+ }
226
+
227
+ /**
228
+ * Perform the actual lookup operation
229
+ * @param {CodeSystemProvider} csProvider - CodeSystem provider
230
+ * @param {string} code - Code to look up
231
+ * @param {Object} params - Parsed parameters
232
+ * @returns {Object} Parameters resource with lookup result
233
+ */
234
+ async doLookup(csProvider, code, params) {
235
+ this.deadCheck('doLookup');
236
+
237
+ // Helper to check if a property should be included
238
+ const hasProp = (name, defaultValue = true) => {
239
+ if (!params.properties || params.properties.length === 0) {
240
+ return defaultValue;
241
+ }
242
+ const lowerName = name.toLowerCase();
243
+ return params.properties.some(p =>
244
+ p.toLowerCase() === lowerName || p === '*'
245
+ );
246
+ };
247
+
248
+ // Locate the code in the code system
249
+ const locateResult = await csProvider.locate(code);
250
+
251
+ if (!locateResult || !locateResult.context) {
252
+ const message = locateResult?.message ||
253
+ `Unable to find code '${code}' in ${csProvider.system()} version ${csProvider.version() || 'unknown'}`;
254
+ throw new Issue('error', 'not-found', null, null, message, null, 404);
255
+ }
256
+
257
+ const ctxt = locateResult.context;
258
+
259
+ // Build the response parameters
260
+ const responseParams = [];
261
+
262
+ // name (required)
263
+ responseParams.push({
264
+ name: 'name',
265
+ valueString: csProvider.name()
266
+ });
267
+ responseParams.push({
268
+ name: 'code',
269
+ valueCode: code
270
+ });
271
+
272
+ responseParams.push({
273
+ name: 'system',
274
+ valueUri: csProvider.system()
275
+ });
276
+
277
+ // version (optional)
278
+ const version = csProvider.version();
279
+ if (version) {
280
+ responseParams.push({
281
+ name: 'version',
282
+ valueString: version
283
+ });
284
+ }
285
+
286
+ // display (required)
287
+ const display = await csProvider.display(ctxt);
288
+ responseParams.push({
289
+ name: 'display',
290
+ valueString: display || code
291
+ });
292
+
293
+ // definition (optional) - top-level parameter
294
+ if (hasProp('definition', true)) {
295
+ const definition = await csProvider.definition(ctxt);
296
+ if (definition) {
297
+ responseParams.push({
298
+ name: 'definition',
299
+ valueString: definition
300
+ });
301
+ }
302
+ }
303
+
304
+ // abstract property (optional)
305
+ if (hasProp('abstract', true)) {
306
+ const isAbstract = await csProvider.isAbstract(ctxt);
307
+ responseParams.push({
308
+ name: 'abstract',
309
+ valueBoolean: isAbstract
310
+ });
311
+ }
312
+
313
+ // inactive property (optional)
314
+ if (hasProp('inactive', true)) {
315
+ const isInactive = await csProvider.isInactive(ctxt);
316
+ responseParams.push({
317
+ name: 'property',
318
+ part: [
319
+ { name: 'code', valueCode: 'inactive' },
320
+ { name: 'value', valueBoolean: isInactive }
321
+ ]
322
+ });
323
+ }
324
+
325
+ // designations (optional)
326
+ if (hasProp('designation', true)) {
327
+ let designations = new Designations(this.languages);
328
+ await csProvider.designations(ctxt, designations);
329
+ if (designations && Array.isArray(designations.designations)) {
330
+ for (const designation of designations.designations) {
331
+ this.deadCheck('doLookup-designations');
332
+ const designationParts = [];
333
+
334
+ if (designation.language) {
335
+ designationParts.push({
336
+ name: 'language',
337
+ valueCode: designation.language.code
338
+ });
339
+ }
340
+
341
+ if (designation.use) {
342
+ designationParts.push({
343
+ name: 'use',
344
+ valueCoding: designation.use
345
+ });
346
+ }
347
+
348
+ designationParts.push({
349
+ name: 'value',
350
+ valueString: designation.value
351
+ });
352
+
353
+ responseParams.push({
354
+ name: 'designation',
355
+ part: designationParts
356
+ });
357
+ }
358
+ }
359
+ }
360
+
361
+ // Let the provider add additional properties
362
+ await csProvider.extendLookup(ctxt, params.property || [], responseParams);
363
+
364
+ return {
365
+ resourceType: 'Parameters',
366
+ parameter: responseParams
367
+ };
368
+ }
369
+
370
+ /**
371
+ * Add a property to the response parameters
372
+ * @param {Array} responseParams - Response parameters array
373
+ * @param {string} code - Property code
374
+ * @param {*} value - Property value
375
+ * @param {string} valueType - FHIR value type (e.g., 'valueString', 'valueBoolean')
376
+ */
377
+ addProperty(responseParams, code, value, valueType) {
378
+ responseParams.push({
379
+ name: 'property',
380
+ part: [
381
+ { name: 'code', valueCode: code },
382
+ { name: 'value', [valueType]: value }
383
+ ]
384
+ });
385
+ }
386
+
387
+
388
+ /**
389
+ * Build an OperationOutcome
390
+ * @param {string} severity - error, warning, information
391
+ * @param {string} code - Issue code
392
+ * @param {string} message - Diagnostic message
393
+ * @returns {Object} OperationOutcome resource
394
+ */
395
+ operationOutcome(severity, code, message) {
396
+ return {
397
+ resourceType: 'OperationOutcome',
398
+ issue: [{
399
+ severity,
400
+ code,
401
+ diagnostics: message
402
+ }]
403
+ };
404
+ }
405
+ }
406
+
407
+ module.exports = LookupWorker;