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,418 @@
1
+ const {CanonicalResource} = require("./canonical-resource");
2
+ const {VersionUtilities} = require("../../library/version-utilities");
3
+
4
+ /**
5
+ * Represents a FHIR TerminologyCapabilities resource with version conversion support.
6
+ * Note: TerminologyCapabilities was introduced in R4. For R3, it is represented as a
7
+ * Parameters resource with a specific structure.
8
+ * @class
9
+ */
10
+ class TerminologyCapabilities extends CanonicalResource {
11
+
12
+ /**
13
+ * Creates a new TerminologyCapabilities instance
14
+ * @param {Object} jsonObj - The JSON object containing TerminologyCapabilities data
15
+ * @param {string} [fhirVersion='R5'] - FHIR version ('R3', 'R4', or 'R5')
16
+ */
17
+ constructor(jsonObj, fhirVersion = 'R5') {
18
+ super(jsonObj, fhirVersion);
19
+ // Convert to R5 format internally (modifies input for performance)
20
+ this.jsonObj = this._convertToR5(jsonObj, fhirVersion);
21
+ this.validate();
22
+ this.id = this.jsonObj.id;
23
+ }
24
+
25
+ /**
26
+ * Static factory method for convenience
27
+ * @param {string} jsonString - JSON string representation of TerminologyCapabilities
28
+ * @param {string} [version='R5'] - FHIR version ('R3', 'R4', or 'R5')
29
+ * @returns {TerminologyCapabilities} New TerminologyCapabilities instance
30
+ */
31
+ static fromJSON(jsonString, version = 'R5') {
32
+ return new TerminologyCapabilities(JSON.parse(jsonString), version);
33
+ }
34
+
35
+ /**
36
+ * Returns JSON string representation
37
+ * @param {string} [version='R5'] - Target FHIR version ('R3', 'R4', or 'R5')
38
+ * @returns {string} JSON string
39
+ */
40
+ toJSONString(version = 'R5') {
41
+ const outputObj = this._convertFromR5(this.jsonObj, version);
42
+ return JSON.stringify(outputObj);
43
+ }
44
+
45
+ /**
46
+ * Returns JSON object in target version format
47
+ * @param {string} [version='R5'] - Target FHIR version ('R3', 'R4', or 'R5')
48
+ * @returns {Object} JSON object
49
+ */
50
+ toJSON(version = 'R5') {
51
+ return this._convertFromR5(this.jsonObj, version);
52
+ }
53
+
54
+ /**
55
+ * Converts input TerminologyCapabilities to R5 format (modifies input object for performance)
56
+ * @param {Object} jsonObj - The input TerminologyCapabilities object
57
+ * @param {string} version - Source FHIR version
58
+ * @returns {Object} The same object, potentially modified to R5 format
59
+ * @private
60
+ */
61
+ _convertToR5(jsonObj, version) {
62
+ if (version === 'R5') {
63
+ return jsonObj; // Already R5, no conversion needed
64
+ }
65
+
66
+ if (version === 'R4') {
67
+ // R4 to R5: No major structural changes needed for TerminologyCapabilities
68
+ return jsonObj;
69
+ }
70
+
71
+ if (VersionUtilities.isR3Ver(version)) {
72
+ // R3: TerminologyCapabilities doesn't exist - it's a Parameters resource
73
+ // Convert from Parameters format to TerminologyCapabilities
74
+ return this._convertParametersToR5(jsonObj);
75
+ }
76
+
77
+ throw new Error(`Unsupported FHIR version: ${version}`);
78
+ }
79
+
80
+ /**
81
+ * Converts R3 Parameters format to R5 TerminologyCapabilities
82
+ * @param {Object} params - The Parameters resource
83
+ * @returns {Object} TerminologyCapabilities in R5 format
84
+ * @private
85
+ */
86
+ _convertParametersToR5(params) {
87
+ if (params.resourceType !== 'Parameters') {
88
+ throw new Error('R3 TerminologyCapabilities must be a Parameters resource');
89
+ }
90
+
91
+ const result = {
92
+ resourceType: 'TerminologyCapabilities',
93
+ id: params.id,
94
+ status: 'active', // Default, as Parameters doesn't carry this
95
+ kind: 'instance', // Default for terminology server capabilities
96
+ codeSystem: []
97
+ };
98
+
99
+ const parameters = params.parameter || [];
100
+ let currentSystem = null;
101
+
102
+ for (const param of parameters) {
103
+ switch (param.name) {
104
+ case 'url':
105
+ result.url = param.valueUri;
106
+ break;
107
+ case 'version':
108
+ if (currentSystem) {
109
+ // This is a code system version
110
+ if (param.valueCode) {
111
+ currentSystem.version = currentSystem.version || [];
112
+ currentSystem.version.push({ code: param.valueCode });
113
+ }
114
+ // Empty version parameter means no specific version
115
+ } else {
116
+ // This is the TerminologyCapabilities version
117
+ result.version = param.valueCode || param.valueString;
118
+ }
119
+ break;
120
+ case 'date':
121
+ result.date = param.valueDateTime;
122
+ break;
123
+ case 'system':
124
+ // Start a new code system
125
+ currentSystem = { uri: param.valueUri };
126
+ result.codeSystem.push(currentSystem);
127
+ break;
128
+ case 'expansion.parameter':
129
+ result.expansion = result.expansion || { parameter: [] };
130
+ result.expansion.parameter.push({ name: param.valueCode });
131
+ break;
132
+ }
133
+ }
134
+
135
+ return result;
136
+ }
137
+
138
+ /**
139
+ * Converts R5 TerminologyCapabilities to target version format (clones object first)
140
+ * @param {Object} r5Obj - The R5 format TerminologyCapabilities object
141
+ * @param {string} targetVersion - Target FHIR version
142
+ * @returns {Object} New object in target version format
143
+ * @private
144
+ */
145
+ _convertFromR5(r5Obj, targetVersion) {
146
+ if (VersionUtilities.isR5Ver(targetVersion)) {
147
+ return r5Obj; // No conversion needed
148
+ }
149
+
150
+ // Clone the object to avoid modifying the original
151
+ const cloned = JSON.parse(JSON.stringify(r5Obj));
152
+
153
+ if (VersionUtilities.isR4Ver(targetVersion)) {
154
+ return this._convertR5ToR4(cloned);
155
+ } else if (VersionUtilities.isR3Ver(targetVersion)) {
156
+ return this._convertR5ToR3(cloned);
157
+ }
158
+
159
+ throw new Error(`Unsupported target FHIR version: ${targetVersion}`);
160
+ }
161
+
162
+ /**
163
+ * Converts R5 TerminologyCapabilities to R4 format
164
+ * @param {Object} r5Obj - Cloned R5 TerminologyCapabilities object
165
+ * @returns {Object} R4 format TerminologyCapabilities
166
+ * @private
167
+ */
168
+ _convertR5ToR4(r5Obj) {
169
+ // Remove R5-specific elements
170
+ if (r5Obj.versionAlgorithmString) {
171
+ delete r5Obj.versionAlgorithmString;
172
+ }
173
+ if (r5Obj.versionAlgorithmCoding) {
174
+ delete r5Obj.versionAlgorithmCoding;
175
+ }
176
+
177
+ // Convert valueCanonical to valueUri throughout the object
178
+ this._convertCanonicalToUri(r5Obj);
179
+
180
+ return r5Obj;
181
+ }
182
+
183
+ /**
184
+ * Converts R5 TerminologyCapabilities to R3 format (Parameters resource)
185
+ * In R3, TerminologyCapabilities didn't exist - we represent it as a Parameters resource
186
+ * @param {Object} r5Obj - Cloned R5 TerminologyCapabilities object
187
+ * @returns {Object} R3 format Parameters resource
188
+ * @private
189
+ */
190
+ _convertR5ToR3(r5Obj) {
191
+ const params = {
192
+ resourceType: 'Parameters',
193
+ id: r5Obj.id,
194
+ parameter: []
195
+ };
196
+
197
+ // Add url parameter
198
+ if (r5Obj.url) {
199
+ params.parameter.push({
200
+ name: 'url',
201
+ valueUri: r5Obj.url
202
+ });
203
+ }
204
+
205
+ // Add version parameter
206
+ if (r5Obj.version) {
207
+ params.parameter.push({
208
+ name: 'version',
209
+ valueCode: r5Obj.version
210
+ });
211
+ }
212
+
213
+ // Add date parameter
214
+ if (r5Obj.date) {
215
+ params.parameter.push({
216
+ name: 'date',
217
+ valueDateTime: r5Obj.date
218
+ });
219
+ }
220
+
221
+ // Add code systems with their versions
222
+ for (const codeSystem of r5Obj.codeSystem || []) {
223
+ // Add system parameter
224
+ params.parameter.push({
225
+ name: 'system',
226
+ valueUri: codeSystem.uri
227
+ });
228
+
229
+ // Add version parameter(s) for this code system
230
+ if (codeSystem.version && codeSystem.version.length > 0) {
231
+ for (const ver of codeSystem.version) {
232
+ if (ver.code) {
233
+ params.parameter.push({
234
+ name: 'version',
235
+ valueCode: ver.code
236
+ });
237
+ } else {
238
+ // Empty version parameter when no specific version
239
+ params.parameter.push({
240
+ name: 'version'
241
+ });
242
+ }
243
+ }
244
+ } else {
245
+ // No version specified for this code system
246
+ params.parameter.push({
247
+ name: 'version'
248
+ });
249
+ }
250
+ }
251
+
252
+ // Add expansion parameters
253
+ if (r5Obj.expansion && r5Obj.expansion.parameter) {
254
+ for (const expParam of r5Obj.expansion.parameter) {
255
+ params.parameter.push({
256
+ name: 'expansion.parameter',
257
+ valueCode: expParam.name
258
+ });
259
+ }
260
+ }
261
+
262
+ return params;
263
+ }
264
+
265
+ /**
266
+ * Recursively converts valueCanonical to valueUri in an object
267
+ * R3/R4 doesn't have canonical type in the same way, so valueCanonical must become valueUri
268
+ * @param {Object} obj - Object to convert
269
+ * @private
270
+ */
271
+ _convertCanonicalToUri(obj) {
272
+ if (!obj || typeof obj !== 'object') {
273
+ return;
274
+ }
275
+
276
+ if (Array.isArray(obj)) {
277
+ obj.forEach(item => this._convertCanonicalToUri(item));
278
+ return;
279
+ }
280
+
281
+ // Convert valueCanonical to valueUri
282
+ if (obj.valueCanonical !== undefined) {
283
+ obj.valueUri = obj.valueCanonical;
284
+ delete obj.valueCanonical;
285
+ }
286
+
287
+ // Recurse into all properties
288
+ for (const key of Object.keys(obj)) {
289
+ if (typeof obj[key] === 'object') {
290
+ this._convertCanonicalToUri(obj[key]);
291
+ }
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Validates that this is a proper TerminologyCapabilities resource
297
+ * @throws {Error} If validation fails
298
+ */
299
+ validate() {
300
+ if (!this.jsonObj || typeof this.jsonObj !== 'object') {
301
+ throw new Error('Invalid TerminologyCapabilities: expected object');
302
+ }
303
+
304
+ if (this.jsonObj.resourceType !== 'TerminologyCapabilities') {
305
+ throw new Error(`Invalid TerminologyCapabilities: resourceType must be "TerminologyCapabilities", got "${this.jsonObj.resourceType}"`);
306
+ }
307
+
308
+ if (!this.jsonObj.status || typeof this.jsonObj.status !== 'string') {
309
+ throw new Error('Invalid TerminologyCapabilities: status is required and must be a string');
310
+ }
311
+
312
+ const validStatuses = ['draft', 'active', 'retired', 'unknown'];
313
+ if (!validStatuses.includes(this.jsonObj.status)) {
314
+ throw new Error(`Invalid TerminologyCapabilities: status must be one of ${validStatuses.join(', ')}, got "${this.jsonObj.status}"`);
315
+ }
316
+
317
+ if (!this.jsonObj.kind || typeof this.jsonObj.kind !== 'string') {
318
+ throw new Error('Invalid TerminologyCapabilities: kind is required and must be a string');
319
+ }
320
+
321
+ const validKinds = ['instance', 'capability', 'requirements'];
322
+ if (!validKinds.includes(this.jsonObj.kind)) {
323
+ throw new Error(`Invalid TerminologyCapabilities: kind must be one of ${validKinds.join(', ')}, got "${this.jsonObj.kind}"`);
324
+ }
325
+ }
326
+
327
+ /**
328
+ * Gets the code systems supported by this terminology server
329
+ * @returns {Object[]} Array of code system capability objects
330
+ */
331
+ getCodeSystems() {
332
+ return this.jsonObj.codeSystem || [];
333
+ }
334
+
335
+ /**
336
+ * Gets the expansion capabilities
337
+ * @returns {Object|undefined} Expansion capability object
338
+ */
339
+ getExpansion() {
340
+ return this.jsonObj.expansion;
341
+ }
342
+
343
+ /**
344
+ * Gets the validate-code capabilities
345
+ * @returns {Object|undefined} ValidateCode capability object
346
+ */
347
+ getValidateCode() {
348
+ return this.jsonObj.validateCode;
349
+ }
350
+
351
+ /**
352
+ * Gets the translation capabilities
353
+ * @returns {Object|undefined} Translation capability object
354
+ */
355
+ getTranslation() {
356
+ return this.jsonObj.translation;
357
+ }
358
+
359
+ /**
360
+ * Gets the closure capabilities
361
+ * @returns {Object|undefined} Closure capability object
362
+ */
363
+ getClosure() {
364
+ return this.jsonObj.closure;
365
+ }
366
+
367
+ /**
368
+ * Gets the list of supported expansion parameters
369
+ * @returns {string[]} Array of parameter names
370
+ */
371
+ getExpansionParameters() {
372
+ const expansion = this.getExpansion();
373
+ if (!expansion || !expansion.parameter) {
374
+ return [];
375
+ }
376
+ return expansion.parameter.map(p => p.name);
377
+ }
378
+
379
+ /**
380
+ * Checks if a specific code system is supported
381
+ * @param {string} uri - The code system URI to check
382
+ * @returns {boolean} True if the code system is supported
383
+ */
384
+ supportsCodeSystem(uri) {
385
+ return this.getCodeSystems().some(cs => cs.uri === uri);
386
+ }
387
+
388
+ /**
389
+ * Gets version information for a specific code system
390
+ * @param {string} uri - The code system URI
391
+ * @returns {Object[]|undefined} Array of version objects or undefined if not found
392
+ */
393
+ getCodeSystemVersions(uri) {
394
+ const codeSystem = this.getCodeSystems().find(cs => cs.uri === uri);
395
+ return codeSystem?.version;
396
+ }
397
+
398
+ /**
399
+ * Gets basic info about this terminology capabilities statement
400
+ * @returns {Object} Basic information object
401
+ */
402
+ getInfo() {
403
+ return {
404
+ resourceType: this.jsonObj.resourceType,
405
+ url: this.jsonObj.url,
406
+ version: this.jsonObj.version,
407
+ name: this.jsonObj.name,
408
+ title: this.jsonObj.title,
409
+ status: this.jsonObj.status,
410
+ kind: this.jsonObj.kind,
411
+ date: this.jsonObj.date,
412
+ codeSystemCount: this.getCodeSystems().length,
413
+ expansionParameters: this.getExpansionParameters()
414
+ };
415
+ }
416
+ }
417
+
418
+ module.exports = { TerminologyCapabilities };