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
package/tx/cs/cs-cs.js ADDED
@@ -0,0 +1,1579 @@
1
+ const { CodeSystem} = require("../library/codesystem");
2
+ const { CodeSystemFactoryProvider, CodeSystemProvider, FilterExecutionContext } = require( "./cs-api");
3
+ const { VersionUtilities } = require("../../library/version-utilities");
4
+ const { Language } = require ("../../library/languages");
5
+ const { validateOptionalParameter, getValuePrimitive, validateArrayParameter} = require("../../library/utilities");
6
+ const {Issue} = require("../library/operation-outcome");
7
+ const {Extensions} = require("../library/extensions");
8
+
9
+ /**
10
+ * Context class for FHIR CodeSystem provider concepts
11
+ */
12
+ class FhirCodeSystemProviderContext {
13
+ constructor(code, concept) {
14
+ this.code = code;
15
+ this.concept = concept;
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Context class for FHIR CodeSystem provider filter results
21
+ */
22
+ class FhirCodeSystemProviderFilterContext {
23
+ constructor() {
24
+ this.concepts = []; // Array of {concept, rating} objects
25
+ this.currentIndex = -1;
26
+ this.include = true; // Whether this is an include or exclude filter
27
+ }
28
+
29
+ /**
30
+ * Add a concept to the filter results
31
+ * @param {Object} concept - The concept object
32
+ * @param {number} rating - Search relevance rating (higher = more relevant)
33
+ */
34
+ add(concept, rating = 0) {
35
+ this.concepts.push({ concept, rating });
36
+ }
37
+
38
+ /**
39
+ * Sort concepts by rating (highest first)
40
+ */
41
+ sort() {
42
+ this.concepts.sort((a, b) => b.rating - a.rating);
43
+ }
44
+
45
+ /**
46
+ * Get the total number of concepts in the filter
47
+ * @returns {number} Number of concepts
48
+ */
49
+ size() {
50
+ return this.concepts.length;
51
+ }
52
+
53
+ /**
54
+ * Check if there are more concepts to iterate
55
+ * @returns {boolean} True if more concepts available
56
+ */
57
+ hasMore() {
58
+ return this.currentIndex + 1 < this.concepts.length;
59
+ }
60
+
61
+ /**
62
+ * Move to next concept and return it
63
+ * @returns {Object|null} Next concept or null if exhausted
64
+ */
65
+ next() {
66
+ if (this.hasMore()) {
67
+ this.currentIndex++;
68
+ return this.concepts[this.currentIndex].concept;
69
+ }
70
+ return null;
71
+ }
72
+
73
+ /**
74
+ * Reset iterator to beginning
75
+ */
76
+ reset() {
77
+ this.currentIndex = -1;
78
+ }
79
+
80
+ /**
81
+ * Find a concept by code in the filter results
82
+ * @param {string} code - The code to find
83
+ * @returns {Object|null} The concept if found, null otherwise
84
+ */
85
+ findConceptByCode(code) {
86
+ for (const item of this.concepts) {
87
+ if (item.concept.code === code) {
88
+ return item.concept;
89
+ }
90
+ }
91
+ return null;
92
+ }
93
+
94
+ /**
95
+ * Check if a concept is in the filter results
96
+ * @param {Object} concept - The concept to check
97
+ * @returns {boolean} True if concept is in results
98
+ */
99
+ containsConcept(concept) {
100
+ return this.concepts.some(item => item.concept === concept);
101
+ }
102
+ }
103
+
104
+ class FhirCodeSystemProvider extends CodeSystemProvider {
105
+ /**
106
+ * @param {CodeSystem} codeSystem - The primary CodeSystem
107
+ * @param {CodeSystem[]} supplements - Array of supplement CodeSystems
108
+ */
109
+ constructor(opContext, codeSystem, supplements) {
110
+ super(opContext, supplements);
111
+
112
+ if (codeSystem.content == 'supplements') {
113
+ throw new Issue('error', 'invalid', null, 'CODESYSTEM_CS_NO_SUPPLEMENT', opContext.i18n.translate('CODESYSTEM_CS_NO_SUPPLEMENT', opContext.langs, codeSystem.vurl));
114
+ }
115
+ this.codeSystem = codeSystem;
116
+ this.hasHierarchyFlag = codeSystem.hasHierarchy();
117
+
118
+ // Parse the default language if specified
119
+ this.defaultLanguage = codeSystem.langCode();
120
+ }
121
+
122
+ // ============ Metadata Methods ============
123
+
124
+ /**
125
+ * @returns {string} URI and version identifier for the code system
126
+ */
127
+ name() {
128
+ return this.codeSystem.jsonObj.name || '';
129
+ }
130
+
131
+ /**
132
+ * @returns {string} URI for the code system
133
+ */
134
+ system() {
135
+ return this.codeSystem.jsonObj.url || '';
136
+ }
137
+
138
+ /**
139
+ * @returns {string|null} Version for the code system
140
+ */
141
+ version() {
142
+ return this.codeSystem.jsonObj.version || null;
143
+ }
144
+
145
+ /**
146
+ * @returns {string|null} valueset for the code system
147
+ */
148
+ valueSet() {
149
+ return this.codeSystem.jsonObj.valueSet || null;
150
+ }
151
+
152
+ /**
153
+ * @returns {string} Default language for the code system
154
+ */
155
+ defLang() {
156
+ return this.defaultLanguage?.toString() || 'en';
157
+ }
158
+
159
+ /**
160
+ * @returns {string} Content mode for the CodeSystem
161
+ */
162
+ contentMode() {
163
+ return this.codeSystem.content;
164
+ }
165
+
166
+ /**
167
+ * @returns {string} Description for the code system
168
+ */
169
+ description() {
170
+ return this.codeSystem.jsonObj.description || this.codeSystem.jsonObj.title || this.codeSystem.jsonObj.name || '';
171
+ }
172
+
173
+ /**
174
+ * @returns {string|null} Source package for the code system, if known
175
+ */
176
+ sourcePackage() {
177
+ return this.codeSystem.sourcePackage;
178
+ }
179
+
180
+ /**
181
+ * @returns {number} Total number of concepts in the code system
182
+ */
183
+ totalCount() {
184
+ return this.codeSystem.codeMap.size;
185
+ }
186
+
187
+ /**
188
+ * @returns {Object[]|null} Defined properties for the code system
189
+ */
190
+ propertyDefinitions() {
191
+ return this.codeSystem.jsonObj.property || null;
192
+ }
193
+
194
+ /**
195
+ * @param {Languages} languages - Language specification
196
+ * @returns {boolean} Whether any displays are available for the languages
197
+ */
198
+ hasAnyDisplays(languages) {
199
+ const langs = this._ensureLanguages(languages);
200
+
201
+ // Check supplements first
202
+ if (this._hasAnySupplementDisplays(langs)) {
203
+ return true;
204
+ }
205
+
206
+ // Check if we have English or if no specific languages requested
207
+ if (langs.isEnglishOrNothing()) {
208
+ return true; // We always have displays for concepts
209
+ }
210
+
211
+ // Check if the CodeSystem's language matches requested languages
212
+ if (this.defaultLanguage) {
213
+ for (const requestedLang of langs) {
214
+ if (this.defaultLanguage.matchesForDisplay(requestedLang)) {
215
+ return true;
216
+ }
217
+ }
218
+ }
219
+
220
+ // Check concept designations for matching languages
221
+ for (const concept of this.codeSystem.getAllConcepts()) {
222
+ if (concept.designation && Array.isArray(concept.designation)) {
223
+ for (const designation of concept.designation) {
224
+ if (designation.language) {
225
+ const designationLang = new Language(designation.language);
226
+ for (const requestedLang of langs) {
227
+ if (designationLang.matchesForDisplay(requestedLang)) {
228
+ return true;
229
+ }
230
+ }
231
+ }
232
+ }
233
+ }
234
+ }
235
+
236
+ return false;
237
+ }
238
+
239
+ /**
240
+ * @returns {boolean} True if there's a hierarchy
241
+ */
242
+ hasParents() {
243
+ return this.hasHierarchyFlag;
244
+ }
245
+
246
+ /**
247
+ * @param {string} checkVersion - First version
248
+ * @param {string} actualVersion - Second version
249
+ * @returns {boolean} True if v1 is more detailed than v2
250
+ */
251
+ versionIsMoreDetailed(checkVersion, actualVersion) {
252
+ return VersionUtilities.versionMatchesByAlgorithm(checkVersion, actualVersion, this.versionAlgorithm());
253
+ }
254
+
255
+ /**
256
+ * @returns {{status: string, standardsStatus: string, experimental: boolean}|null} Status information
257
+ */
258
+ status() {
259
+ const cs = this.codeSystem.jsonObj;
260
+ if (!cs.status) return {};
261
+
262
+ return {
263
+ status: cs.status,
264
+ standardsStatus: cs.extension?.find(ext =>
265
+ ext.url === 'http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status'
266
+ )?.valueCode || '',
267
+ experimental: cs.experimental || false
268
+ };
269
+ }
270
+
271
+ /**
272
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
273
+ * @returns {Promise<string|null>} The correct code for the concept
274
+ */
275
+ async code(context) {
276
+
277
+ const ctxt = await this.#ensureContext(context);
278
+ return ctxt ? ctxt.code : null;
279
+ }
280
+
281
+ /**
282
+ * @param {string} code - The code to locate
283
+ * @returns {Promise<{context: FhirCodeSystemProviderContext|null, message: string|null}>} Locate result
284
+ */
285
+ async locate(code) {
286
+
287
+
288
+ if (!code || typeof code !== 'string') {
289
+ return { context: null, message: 'Empty or invalid code' };
290
+ }
291
+
292
+ const concept = this.codeSystem.getConceptByCode(code);
293
+ if (concept) {
294
+ return {
295
+ context: new FhirCodeSystemProviderContext(concept.code, concept),
296
+ message: null
297
+ };
298
+ }
299
+
300
+ return {
301
+ context: null,
302
+ message: undefined
303
+ };
304
+ }
305
+
306
+ /**
307
+ * Helper method to ensure we have a proper context object
308
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
309
+ * @returns {Promise<FhirCodeSystemProviderContext|null>} Resolved context
310
+ * @private
311
+ */
312
+ async #ensureContext(context) {
313
+ if (!context) {
314
+ return null;
315
+ }
316
+
317
+ if (typeof context === 'string') {
318
+ const result = await this.locate(context);
319
+ if (!result.context) {
320
+ throw new Error(result.message ? result.message : `Code '${context}' not found in CodeSystem '${this.system()}'`);
321
+ }
322
+ return result.context;
323
+ }
324
+
325
+ if (context instanceof FhirCodeSystemProviderContext) {
326
+ return context;
327
+ }
328
+
329
+ throw new Error("Unknown Type at #ensureContext: " + (typeof context));
330
+ }
331
+ /**
332
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
333
+ * @returns {Promise<string|null>} The best display given the languages in the operation context
334
+ */
335
+ async display(context) {
336
+
337
+ const ctxt = await this.#ensureContext(context);
338
+ if (!ctxt) {
339
+ return null;
340
+ }
341
+
342
+ // Check supplements first
343
+ const supplementDisplay = this._displayFromSupplements(ctxt.code);
344
+ if (supplementDisplay) {
345
+ return supplementDisplay;
346
+ }
347
+
348
+ // Use language-aware display logic
349
+ if (this.opContext.langs && !this.opContext.langs.isEnglishOrNothing()) {
350
+ // Try to find exact language match in designations
351
+ if (ctxt.concept.designation && Array.isArray(ctxt.concept.designation)) {
352
+ for (const lang of this.opContext.langs.languages) {
353
+ for (const designation of ctxt.concept.designation) {
354
+ if (designation.language) {
355
+ const designationLang = new Language(designation.language);
356
+ if (designationLang.matchesForDisplay(lang)) {
357
+ return designation.value.trim();
358
+ }
359
+ }
360
+ }
361
+ }
362
+ }
363
+
364
+ // Check if the CodeSystem's language matches requested languages
365
+ if (this.defaultLanguage) {
366
+ for (const requestedLang of this.opContext.langs.languages) {
367
+ if (this.defaultLanguage.matchesForDisplay(requestedLang)) {
368
+ return ctxt.concept.display?.trim() || '';
369
+ }
370
+ }
371
+ }
372
+ }
373
+
374
+ // Default to the concept's display
375
+ return ctxt.concept.display?.trim() || '';
376
+ }
377
+
378
+ /**
379
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
380
+ * @returns {Promise<string|null>} The definition for the concept (if available)
381
+ */
382
+ async definition(context) {
383
+
384
+ const ctxt = await this.#ensureContext(context);
385
+ return ctxt ? (ctxt.concept.definition || null) : null;
386
+ }
387
+
388
+ /**
389
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
390
+ * @returns {Promise<boolean>} If the concept is abstract
391
+ */
392
+ async isAbstract(context) {
393
+
394
+ const ctxt = await this.#ensureContext(context);
395
+ if (!ctxt) {
396
+ return false;
397
+ }
398
+
399
+ // Check for abstract property
400
+ if (ctxt.concept.property && Array.isArray(ctxt.concept.property)) {
401
+ const abstractProp = ctxt.concept.property.find(p =>
402
+ p.code === 'abstract' ||
403
+ p.code === 'not-selectable' ||
404
+ p.code === 'notSelectable' ||
405
+ p.uri === 'http://hl7.org/fhir/concept-properties#notSelectable'
406
+ );
407
+ if (abstractProp && abstractProp.valueBoolean) {
408
+ return true;
409
+ }
410
+ }
411
+
412
+ return false;
413
+ }
414
+
415
+ /**
416
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
417
+ * @returns {Promise<boolean>} If the concept is inactive
418
+ */
419
+ async isInactive(context) {
420
+
421
+ const ctxt = await this.#ensureContext(context);
422
+ if (!ctxt) {
423
+ return false;
424
+ }
425
+
426
+ if (ctxt.concept.property && Array.isArray(ctxt.concept.property)) {
427
+ for (const p of ctxt.concept.property) {
428
+ // Check inactive property with boolean value
429
+ if (p.code === 'inactive' && p.valueBoolean === true) {
430
+ return true;
431
+ }
432
+ // Check inactive property with code value 'true'
433
+ if (p.code === 'inactive' && p.valueCode === 'true') {
434
+ return true;
435
+ }
436
+ // Check status property for inactive or retired
437
+ if (p.code === 'status') {
438
+ const value = p.valueCode || p.valueString || (p.value && p.value.toString());
439
+ if (value === 'inactive' || value === 'retired') {
440
+ return true;
441
+ }
442
+ }
443
+ }
444
+ }
445
+
446
+ // Check standards-status extension for withdrawn
447
+ if (ctxt.concept.extension && Array.isArray(ctxt.concept.extension)) {
448
+ const standardsStatus = ctxt.concept.extension.find(e =>
449
+ e.url === 'http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status'
450
+ );
451
+ if (standardsStatus) {
452
+ const value = standardsStatus.valueCode || standardsStatus.valueString || '';
453
+ if (value.toLowerCase() === 'withdrawn') {
454
+ return true;
455
+ }
456
+ }
457
+ }
458
+ return false;
459
+ }
460
+
461
+ /**
462
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
463
+ * @returns {Promise<boolean>} If the concept is deprecated
464
+ */
465
+ async isDeprecated(context) {
466
+
467
+ const ctxt = await this.#ensureContext(context);
468
+ if (!ctxt) {
469
+ return false;
470
+ }
471
+
472
+ // Check for deprecated property or status
473
+ if (ctxt.concept.property && Array.isArray(ctxt.concept.property)) {
474
+ const deprecatedProp = ctxt.concept.property.find(p =>
475
+ p.code === 'deprecated' ||
476
+ p.uri === 'http://hl7.org/fhir/concept-properties#deprecated'
477
+ );
478
+ if (deprecatedProp && deprecatedProp.valueBoolean) {
479
+ return true;
480
+ }
481
+
482
+ // Check status property
483
+ const statusProp = ctxt.concept.property.find(p =>
484
+ p.code === 'status' ||
485
+ p.uri === 'http://hl7.org/fhir/concept-properties#status'
486
+ );
487
+ if (statusProp && (statusProp.valueCode === 'deprecated' || statusProp.valueCode === 'retired')) {
488
+ return true;
489
+ }
490
+ }
491
+
492
+ return false;
493
+ }
494
+
495
+ /**
496
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
497
+ * @returns {Promise<string|null>} Status
498
+ */
499
+ async getStatus(context) {
500
+
501
+ const ctxt = await this.#ensureContext(context);
502
+ if (!ctxt) {
503
+ return null;
504
+ }
505
+
506
+ for (let cp of ctxt.concept.property || []) {
507
+ if (cp.code === 'status' || cp.uri === 'http://hl7.org/fhir/concept-properties#status') {
508
+ return getValuePrimitive(cp);
509
+ }
510
+ }
511
+
512
+ // Second pass: check various deprecation/inactive/retired patterns
513
+ for (let cp of ctxt.concept.property || []) {
514
+ if (cp.code === 'deprecated') {
515
+ if (cp.valueBoolean === true) return 'deprecated';
516
+ if (getValuePrimitive(cp) === 'true') return 'deprecated';
517
+ }
518
+ if (cp.code === 'deprecationDate' && cp.valueDateTime) {
519
+ if (new Date(cp.valueDateTime) < new Date()) return 'deprecated';
520
+ }
521
+ if (cp.code === 'inactive') {
522
+ if (cp.valueBoolean === true) return 'inactive';
523
+ if (getValuePrimitive(cp) === 'true') return 'inactive';
524
+ }
525
+ if (cp.code === 'retired') {
526
+ if (cp.valueBoolean === true) return 'retired';
527
+ if (getValuePrimitive(cp) === 'true') return 'retired';
528
+ }
529
+ }
530
+ const ext = (ctxt.concept.extension || []).find(
531
+ e => e.url === 'http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status'
532
+ );
533
+ if (ext) {
534
+ return ext.valueCode || ext.valueString || '';
535
+ }
536
+
537
+ return null;
538
+ }
539
+
540
+ /**
541
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
542
+ * @returns {Promise<string|null>} Assigned itemWeight - if there is one
543
+ */
544
+ async itemWeight(context) {
545
+
546
+ const ctxt = await this.#ensureContext(context);
547
+ if (!ctxt) {
548
+ return null;
549
+ }
550
+
551
+ // Check for itemWeight extension
552
+ if (ctxt.concept.extension && Array.isArray(ctxt.concept.extension)) {
553
+ const itemWeightExt = ctxt.concept.extension.find(ext =>
554
+ ext.url === 'http://hl7.org/fhir/StructureDefinition/itemWeight'
555
+ );
556
+ if (itemWeightExt && itemWeightExt.valueDecimal !== undefined) {
557
+ return itemWeightExt.valueDecimal.toString();
558
+ }
559
+ }
560
+
561
+ // Check in supplements
562
+ if (this.supplements) {
563
+ for (const supplement of this.supplements) {
564
+ const supplementConcept = supplement.getConceptByCode(ctxt.code);
565
+ if (supplementConcept && supplementConcept.extension && Array.isArray(supplementConcept.extension)) {
566
+ const itemWeightExt = supplementConcept.extension.find(ext =>
567
+ ext.url === 'http://hl7.org/fhir/StructureDefinition/itemWeight'
568
+ );
569
+ if (itemWeightExt && itemWeightExt.valueDecimal !== undefined) {
570
+ return itemWeightExt.valueDecimal;
571
+ }
572
+ }
573
+ }
574
+ }
575
+
576
+ return null;
577
+ }
578
+
579
+ /**
580
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
581
+ * @param {ConceptDesignations} designation list
582
+ * @returns {Promise<Designation[]|null>} Whatever designations exist (in all languages)
583
+ */
584
+ async designations(context, displays) {
585
+
586
+ const ctxt = await this.#ensureContext(context);
587
+ if (!ctxt) {
588
+ return null;
589
+ }
590
+
591
+ // Add main display as a designation
592
+ if (ctxt.concept.display) {
593
+ const displayLang = this.defaultLanguage ? this.defaultLanguage.toString() : null; // 'en';
594
+ displays.addDesignation(true, 'active', displayLang, CodeSystem.makeUseForDisplay(), ctxt.concept.display);
595
+ }
596
+
597
+ // Add concept designations
598
+ if (ctxt.concept.designation && Array.isArray(ctxt.concept.designation)) {
599
+ for (const designation of ctxt.concept.designation) {
600
+ let status = Extensions.readString(designation, "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status");
601
+ displays.addDesignation(false, status || 'active',
602
+ designation.language || '',
603
+ designation.use || null,
604
+ designation.value,
605
+ designation.extension?.length > 0 ? designation.extension : []
606
+ );
607
+ }
608
+ }
609
+
610
+ // Add supplement designations
611
+ this._listSupplementDesignations(ctxt.code, displays);
612
+ }
613
+
614
+ /**
615
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
616
+ * @returns {Promise<Object[]|null>} Extensions, if any
617
+ */
618
+ async extensions(context) {
619
+
620
+ const ctxt = await this.#ensureContext(context);
621
+ if (!ctxt) {
622
+ return null;
623
+ }
624
+
625
+ const extensions = [];
626
+
627
+ // Add extensions from main concept
628
+ if (ctxt.concept.extension && Array.isArray(ctxt.concept.extension)) {
629
+ extensions.push(...ctxt.concept.extension);
630
+ }
631
+
632
+ // Add extensions from supplements
633
+ if (this.supplements) {
634
+ for (const supplement of this.supplements) {
635
+ const supplementConcept = supplement.getConceptByCode(ctxt.code);
636
+ if (supplementConcept && supplementConcept.extension && Array.isArray(supplementConcept.extension)) {
637
+ extensions.push(...supplementConcept.extension);
638
+ }
639
+ }
640
+ }
641
+
642
+ return extensions.length > 0 ? extensions : null;
643
+ }
644
+
645
+ /**
646
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
647
+ * @returns {Promise<Object[]|null>} Properties, if any
648
+ */
649
+ async properties(context) {
650
+
651
+ const ctxt = await this.#ensureContext(context);
652
+ if (!ctxt) {
653
+ return [];
654
+ }
655
+
656
+ const properties = [];
657
+
658
+ // Add properties from main concept
659
+ if (ctxt.concept.property && Array.isArray(ctxt.concept.property)) {
660
+ properties.push(...ctxt.concept.property);
661
+ }
662
+
663
+ // Add properties from supplements
664
+ if (this.supplements) {
665
+ for (const supplement of this.supplements) {
666
+ const supplementConcept = supplement.getConceptByCode(ctxt.code);
667
+ if (supplementConcept && supplementConcept.property && Array.isArray(supplementConcept.property)) {
668
+ properties.push(...supplementConcept.property);
669
+ }
670
+ }
671
+ }
672
+
673
+ return properties;
674
+ }
675
+
676
+ /**
677
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context
678
+ * @returns {Promise<string|null>} Parent, if there is one
679
+ */
680
+ async parent(context) {
681
+
682
+ const ctxt = await this.#ensureContext(context);
683
+ if (!ctxt) {
684
+ return null;
685
+ }
686
+
687
+ // Get parents from CodeSystem hierarchy maps
688
+ const parents = this.codeSystem.getParents(ctxt.code);
689
+ return parents.length > 0 ? parents[0] : null;
690
+ }
691
+
692
+ /**
693
+ * @param {string|FhirCodeSystemProviderContext} a - First code or context
694
+ * @param {string|FhirCodeSystemProviderContext} b - Second code or context
695
+ * @returns {Promise<boolean>} True if they're the same
696
+ */
697
+ async sameConcept(a, b) {
698
+
699
+
700
+ const ctxtA = await this.#ensureContext(a);
701
+ const ctxtB = await this.#ensureContext(b);
702
+
703
+ if (!ctxtA || !ctxtB) {
704
+ return false;
705
+ }
706
+
707
+ return ctxtA.code === ctxtB.code;
708
+ }
709
+
710
+ /**
711
+ * @param {string} code - The code to locate
712
+ * @param {string} parent - The parent code
713
+ * @param {boolean} disallowSelf - Whether to disallow the code being the same as parent
714
+ * @returns {Promise<{context: FhirCodeSystemProviderContext|null, message: string|null}>} Locate result
715
+ */
716
+ async locateIsA(code, parent, disallowSelf = false) {
717
+
718
+
719
+ if (!this.hasParents()) {
720
+ return {
721
+ context: null,
722
+ message: `The CodeSystem ${this.name()} does not have parents`
723
+ };
724
+ }
725
+
726
+ // First check if both codes exist
727
+ const codeResult = await this.locate(code);
728
+ if (!codeResult.context) {
729
+ return codeResult;
730
+ }
731
+
732
+ const parentResult = await this.locate(parent);
733
+ if (!parentResult.context) {
734
+ return {
735
+ context: null,
736
+ message: `Parent code '${parent}' not found in CodeSystem '${this.system()}'`
737
+ };
738
+ }
739
+
740
+ // Check if code is same as parent
741
+ if (code === parent) {
742
+ if (disallowSelf) {
743
+ return {
744
+ context: null,
745
+ message: `Code '${code}' cannot be the same as its parent`
746
+ };
747
+ } else {
748
+ return codeResult; // Return the code itself
749
+ }
750
+ }
751
+
752
+ // Check if code is a descendant of parent
753
+ const ancestors = this.codeSystem.getAncestors(code);
754
+ if (ancestors.includes(parent)) {
755
+ return codeResult;
756
+ }
757
+
758
+ return {
759
+ context: null,
760
+ message: `Code '${code}' is not a descendant of '${parent}'`
761
+ };
762
+ }
763
+
764
+ /**
765
+ * @param {string} codeA - First code
766
+ * @param {string} codeB - Second code
767
+ * @returns {Promise<string>} 'subsumes', 'subsumed-by', 'equivalent', or 'not-subsumed'
768
+ */
769
+ async subsumesTest(codeA, codeB) {
770
+
771
+
772
+ // Check if both codes exist
773
+ const resultA = await this.locate(codeA);
774
+ if (!resultA.context) {
775
+ throw new Error(`Unknown Code "${codeA}"`);
776
+ }
777
+
778
+ const resultB = await this.locate(codeB);
779
+ if (!resultB.context) {
780
+ throw new Error(`Unknown Code "${codeB}"`);
781
+ }
782
+
783
+ // Check if they're the same
784
+ if (codeA === codeB) {
785
+ return 'equivalent';
786
+ }
787
+
788
+ // If no hierarchy, codes can't subsume each other
789
+ if (!this.hasParents()) {
790
+ return 'not-subsumed';
791
+ }
792
+
793
+ // Check if A subsumes B (B is descendant of A)
794
+ if (this.codeSystem.isDescendantOf(codeB, codeA)) {
795
+ return 'subsumes';
796
+ }
797
+
798
+ // Check if B subsumes A (A is descendant of B)
799
+ if (this.codeSystem.isDescendantOf(codeA, codeB)) {
800
+ return 'subsumed-by';
801
+ }
802
+
803
+ return 'not-subsumed';
804
+ }
805
+
806
+ /**
807
+ * @param {string|FhirCodeSystemProviderContext} context - Code or context to iterate from
808
+ * @returns {Promise<Object|null>} A handle that can be passed to nextContext (or null if can't be iterated)
809
+ */
810
+ async iterator(context) {
811
+
812
+
813
+ if (!context) {
814
+ const allCodes = this.codeSystem.getRootConcepts();
815
+ return {
816
+ type: 'all',
817
+ codes: allCodes,
818
+ current: 0,
819
+ total: allCodes.length
820
+ };
821
+ } else {
822
+ const ctxt = await this.#ensureContext(context);
823
+ if (!ctxt) {
824
+ return null;
825
+ }
826
+
827
+ // Iterate children of the specified concept
828
+ const children = this.codeSystem.getChildren(ctxt.code);
829
+ return {
830
+ type: 'children',
831
+ parentCode: ctxt.code,
832
+ codes: children,
833
+ current: 0,
834
+ total: children.length
835
+ };
836
+ }
837
+ }
838
+
839
+ /**
840
+ * @returns {Promise<Object|null>} A handle that can be passed to nextContext (or null if can't be iterated)
841
+ */
842
+ async iteratorAll() {
843
+ const allCodes = this.codeSystem.getAllCodes();
844
+ return {
845
+ type: 'all',
846
+ codes: allCodes,
847
+ current: 0,
848
+ total: allCodes.length
849
+ };
850
+ }
851
+
852
+ /**
853
+ * @param {Object} iteratorContext - Iterator context from iterator()
854
+ * @returns {Promise<FhirCodeSystemProviderContext|null>} The next concept, or null
855
+ */
856
+ async nextContext(iteratorContext) {
857
+
858
+
859
+ if (!iteratorContext || iteratorContext.current >= iteratorContext.total) {
860
+ return null;
861
+ }
862
+
863
+ const code = iteratorContext.codes[iteratorContext.current];
864
+ iteratorContext.current++;
865
+
866
+ // Get the concept for this code
867
+ const concept = this.codeSystem.getConceptByCode(code);
868
+ if (!concept) {
869
+ return null;
870
+ }
871
+
872
+ return new FhirCodeSystemProviderContext(code, concept);
873
+ }
874
+
875
+ /**
876
+ * @param {FhirCodeSystemProviderContext} ctxt - The context to add properties for
877
+ * @param {string[]} props - The properties requested
878
+ * @param {Object} params - The parameters response to add to
879
+ */
880
+ async extendLookup(ctxt, props, params) {
881
+ validateArrayParameter(props, 'props', String);
882
+ validateArrayParameter(params, 'params', Object);
883
+
884
+
885
+ if (!ctxt || !(ctxt instanceof FhirCodeSystemProviderContext)) {
886
+ return;
887
+ }
888
+
889
+ // Set abstract status
890
+ if (!params.find(p => p.name == "abstract") && await this.isAbstract(ctxt)) {
891
+ params.push({ name: 'property', part: [ { name: 'code', valueCode: 'abstract' }, { name: 'value', valueBoolean: true } ]});
892
+ }
893
+ // Add properties if requested (or by default)
894
+ if (!props || props.length === 0 || props.includes('*') || props.includes('property')) {
895
+ const properties = await this.properties(ctxt);
896
+ if (properties) {
897
+ for (const property of properties) {
898
+ let parts = [];
899
+ parts.push({ name: 'code', valueCode: property.code });
900
+
901
+ // Add the appropriate value based on the property type
902
+ if (property.valueCode) {
903
+ parts.push({ name: 'value', valueCode: property.valueCode });
904
+ } else if (property.valueString) {
905
+ parts.push({ name: 'value', valueString: property.valueString });
906
+ } else if (property.valueInteger !== undefined) {
907
+ parts.push({ name: 'value', valueInteger: property.valueInteger });
908
+ } else if (property.valueBoolean !== undefined) {
909
+ parts.push({ name: 'value', valueBoolean: property.valueBoolean });
910
+ } else if (property.valueDateTime) {
911
+ parts.push({ name: 'value', valueDateTime: property.valueDateTime });
912
+ } else if (property.valueDecimal !== undefined) {
913
+ parts.push({ name: 'value', valueDecimal: property.valueDecimal });
914
+ } else if (property.valueCoding) {
915
+ parts.push({ name: 'value', valueCoding: property.valueCoding });
916
+ }
917
+ params.push({ name: 'property', part: [...parts]});
918
+ }
919
+ }
920
+ }
921
+
922
+ // Add parent if requested and exists
923
+ if (!props || props.length === 0 || props.includes('*') || props.includes('parent')) {
924
+ const parentCode = await this.parent(ctxt);
925
+ if (parentCode) {
926
+ let parts = [];
927
+ parts.push({ name: 'code', valueCode: 'parent' });
928
+ parts.push({ name: 'value', valueCode: parentCode });
929
+ parts.push({ name: 'description', valueString: await this.display(parentCode) });
930
+ params.push({ name: 'property', part : [...parts]});
931
+ }
932
+ }
933
+
934
+ // Add children if requested
935
+ if (!props || props.length === 0 || props.includes('*') || props.includes('child')) {
936
+ const children = this.codeSystem.getChildren(ctxt.code);
937
+ if (children.length > 0) {
938
+ for (const childCode of children) {
939
+ let parts = [];
940
+ parts.push({ name: 'code', valueCode: 'child' });
941
+ parts.push({ name: 'value', valueCode: childCode });
942
+ parts.push({ name: 'description', valueString: await this.display(childCode) });
943
+ params.push({ name: 'property', part : [...parts]});
944
+ }
945
+ }
946
+ }
947
+ }
948
+
949
+ /**
950
+ * @param {boolean} iterate - True if results will be iterated
951
+ * @returns {FilterExecutionContext} Filter context
952
+ */
953
+ async getPrepContext(iterate) {
954
+
955
+ return new FilterExecutionContext(iterate);
956
+ }
957
+
958
+ /**
959
+ * @param {FilterExecutionContext} filterContext - Filter context
960
+ * @returns {boolean} True if filters are not closed (infinite results possible)
961
+ */
962
+ // eslint-disable-next-line no-unused-vars
963
+ async filtersNotClosed(filterContext) {
964
+
965
+ return false; // FHIR CodeSystems are typically closed/finite
966
+ }
967
+
968
+ /**
969
+ * Determines if a specific filter is supported
970
+ * @param {string} prop - Property name
971
+ * @param {string} op - Filter operator (=, is-a, descendent-of, etc.)
972
+ * @param {string} value - Filter value
973
+ * @returns {Promise<boolean>} True if filter is supported
974
+ */
975
+ async doesFilter(prop, op, value) {
976
+ validateOptionalParameter(value, "value", String);
977
+ if (!value) {
978
+ return false;
979
+ }
980
+ // Supported hierarchy filters
981
+ if ((prop === 'concept' || prop === 'code') &&
982
+ ['is-a', 'descendent-of', 'is-not-a', 'in', '=', 'regex'].includes(op)) {
983
+ return true;
984
+ }
985
+
986
+ // Child existence filter
987
+ if (prop === 'child' && op === 'exists') {
988
+ return true;
989
+ }
990
+
991
+ // Property-based filters
992
+ const propertyDefs = this.propertyDefinitions();
993
+ if (propertyDefs) {
994
+ const hasProperty = propertyDefs.some(p => p.code === prop);
995
+ if (hasProperty && ['=', 'in', 'not-in', 'regex'].includes(op)) {
996
+ return true;
997
+ }
998
+ }
999
+
1000
+ // Known special properties
1001
+ const knownProperties = ['notSelectable', 'status', 'inactive', 'deprecated'];
1002
+ if (knownProperties.includes(prop) && ['=', 'in', 'not-in'].includes(op)) {
1003
+ return true;
1004
+ }
1005
+
1006
+ return false;
1007
+ }
1008
+
1009
+ /**
1010
+ * Execute filter preparation - returns array of filter contexts
1011
+ * @param {FilterExecutionContext} filterContext - Filter context
1012
+ * @returns {Promise<Array>} Array of filter result sets
1013
+ */
1014
+ async executeFilters(filterContext) {
1015
+
1016
+
1017
+ // Return the accumulated filters from the context
1018
+ return filterContext.filters || [];
1019
+ }
1020
+
1021
+ /**
1022
+ * Get the size of a filter result set
1023
+ * @param {FilterExecutionContext} filterContext - Filter context
1024
+ * @param {FhirCodeSystemProviderFilterContext} set - Filter result set
1025
+ * @returns {Promise<number>} Number of concepts in the set
1026
+ */
1027
+ async filterSize(filterContext, set) {
1028
+
1029
+ return set ? set.size() : 0;
1030
+ }
1031
+
1032
+ /**
1033
+ * Check if there are more results in the filter set iterator
1034
+ * @param {FilterExecutionContext} filterContext - Filter context
1035
+ * @param {FhirCodeSystemProviderFilterContext} set - Filter result set
1036
+ * @returns {Promise<boolean>} True if more results available
1037
+ */
1038
+ async filterMore(filterContext, set) {
1039
+
1040
+ if (!set) return false;
1041
+ return set.hasMore();
1042
+ }
1043
+
1044
+ /**
1045
+ * Get the current concept from the filter set iterator
1046
+ * @param {FilterExecutionContext} filterContext - Filter context
1047
+ * @param {FhirCodeSystemProviderFilterContext} set - Filter result set
1048
+ * @returns {Promise<FhirCodeSystemProviderContext|null>} Current concept context
1049
+ */
1050
+ async filterConcept(filterContext, set) {
1051
+
1052
+ if (!set) return null;
1053
+
1054
+ const concept = set.next();
1055
+ return concept ? new FhirCodeSystemProviderContext(concept.code, concept) : null;
1056
+ }
1057
+
1058
+ /**
1059
+ * Find a specific code in the filter results
1060
+ * @param {FilterExecutionContext} filterContext - Filter context
1061
+ * @param {FhirCodeSystemProviderFilterContext} set - Filter result set
1062
+ * @param {string} code - Code to find
1063
+ * @returns {Promise<FhirCodeSystemProviderContext|string>} Context if found, error message if not
1064
+ */
1065
+ async filterLocate(filterContext, set, code) {
1066
+
1067
+ if (!set) {
1068
+ return `Code '${code}' not found: no filter results`;
1069
+ }
1070
+
1071
+ const concept = set.findConceptByCode(code);
1072
+ if (concept) {
1073
+ return new FhirCodeSystemProviderContext(code, concept);
1074
+ }
1075
+
1076
+ return null; // `Code '${code}' not found in filter results`;
1077
+ }
1078
+
1079
+ /**
1080
+ * Check if a concept is in the filter results
1081
+ * @param {FilterExecutionContext} filterContext - Filter context
1082
+ * @param {FhirCodeSystemProviderFilterContext} set - Filter result set
1083
+ * @param {FhirCodeSystemProviderContext} concept - Concept to check
1084
+ * @returns {Promise<boolean|string>} True if found, error message if not
1085
+ */
1086
+ async filterCheck(filterContext, set, concept) {
1087
+
1088
+ if (!set || !concept) {
1089
+ return 'Invalid filter set or concept';
1090
+ }
1091
+
1092
+ const found = set.containsConcept(concept.concept);
1093
+ return found ? true : `Concept '${concept.code}' not found in filter results`;
1094
+ }
1095
+
1096
+ /**
1097
+ * Clean up filter resources
1098
+ * @param {FilterExecutionContext} filterContext - Filter context
1099
+ */
1100
+ async filterFinish(filterContext) {
1101
+
1102
+ // Clear any cached data
1103
+ if (filterContext.filters) {
1104
+ filterContext.filters.forEach(filter => {
1105
+ if (filter.reset) {
1106
+ filter.reset();
1107
+ }
1108
+ });
1109
+ filterContext.filters.length = 0;
1110
+ }
1111
+ }
1112
+ /**
1113
+ * Execute text-based search filter
1114
+ * @param {FilterExecutionContext} filterContext - Filter context
1115
+ * @param {string} filter - Search text
1116
+ * @param {boolean} sort - Whether to sort results by relevance
1117
+ * @returns {Promise<FhirCodeSystemProviderFilterContext>} Filter results
1118
+ */
1119
+ async searchFilter(filterContext, filter, sort) {
1120
+
1121
+
1122
+ const results = new FhirCodeSystemProviderFilterContext();
1123
+ const searchTerm = filter.toLowerCase();
1124
+
1125
+ // Search through all concepts
1126
+ const allConcepts = this.codeSystem.getAllConcepts();
1127
+
1128
+ for (const concept of allConcepts) {
1129
+ const rating = this._calculateSearchRating(concept, searchTerm);
1130
+ if (rating > 0) {
1131
+ results.add(concept, rating);
1132
+ }
1133
+ }
1134
+
1135
+ if (sort) {
1136
+ results.sort();
1137
+ }
1138
+
1139
+ // Add to filter context
1140
+ if (!filterContext.filters) {
1141
+ filterContext.filters = [];
1142
+ }
1143
+ filterContext.filters.push(results);
1144
+
1145
+ return results;
1146
+ }
1147
+
1148
+ /**
1149
+ * Calculate search relevance rating for a concept
1150
+ * @param {Object} concept - The concept to rate
1151
+ * @param {string} searchTerm - The search term (lowercase)
1152
+ * @returns {number} Rating (0 = no match, higher = better match)
1153
+ * @private
1154
+ */
1155
+ _calculateSearchRating(concept, searchTerm) {
1156
+ let rating = 0;
1157
+
1158
+ // Exact matches get highest rating
1159
+ if (concept.code.toLowerCase() === searchTerm) {
1160
+ rating = 100;
1161
+ } else if (concept.display && concept.display.toLowerCase() === searchTerm) {
1162
+ rating = 100;
1163
+ }
1164
+ // Code starts with search term
1165
+ else if (concept.code.toLowerCase().startsWith(searchTerm)) {
1166
+ rating = 90;
1167
+ }
1168
+ // Display starts with search term
1169
+ else if (concept.display && concept.display.toLowerCase().startsWith(searchTerm)) {
1170
+ const lengthRatio = searchTerm.length / concept.display.length;
1171
+ rating = 80 + (10 * lengthRatio);
1172
+ }
1173
+ // Code contains search term
1174
+ else if (concept.code.toLowerCase().includes(searchTerm)) {
1175
+ rating = 60;
1176
+ }
1177
+ // Display contains search term
1178
+ else if (concept.display && concept.display.toLowerCase().includes(searchTerm)) {
1179
+ rating = 50;
1180
+ }
1181
+ // Definition contains search term
1182
+ else if (concept.definition && concept.definition.toLowerCase().includes(searchTerm)) {
1183
+ rating = 30;
1184
+ }
1185
+ // Check designations
1186
+ else if (concept.designation && Array.isArray(concept.designation)) {
1187
+ for (const designation of concept.designation) {
1188
+ if (designation.value && designation.value.toLowerCase().includes(searchTerm)) {
1189
+ rating = 40;
1190
+ break;
1191
+ }
1192
+ }
1193
+ }
1194
+
1195
+ return rating;
1196
+ }
1197
+
1198
+ /**
1199
+ * Execute a value set filter
1200
+ * @param {FilterExecutionContext} filterContext - Filter context
1201
+ * @param {string} prop - Property name to filter on
1202
+ * @param {string} op - Filter operator
1203
+ * @param {string} value - Filter value
1204
+ * @returns {Promise<FhirCodeSystemProviderFilterContext>} Filter results
1205
+ */
1206
+ async filter(filterContext, prop, op, value) {
1207
+
1208
+
1209
+ let results = null;
1210
+
1211
+ // Handle concept/code hierarchy filters
1212
+ if ((prop === 'concept' || prop === 'code')) {
1213
+ results = await this._handleConceptFilter(filterContext, op, value);
1214
+ }
1215
+
1216
+ // Handle child existence filter
1217
+ if (prop === 'child' && op === 'exists') {
1218
+ results = await this._handleChildExistsFilter(filterContext, value);
1219
+ }
1220
+
1221
+ // Handle property-based filters
1222
+ const propertyDefs = this.propertyDefinitions();
1223
+ if (propertyDefs) {
1224
+ const propertyDef = propertyDefs.find(p => p.code === prop);
1225
+ if (propertyDef) {
1226
+ results = await this._handlePropertyFilter(filterContext, propertyDef, op, value);
1227
+ }
1228
+ }
1229
+
1230
+ // Handle known special properties
1231
+ const knownProperties = ['notSelectable', 'status', 'inactive', 'deprecated'];
1232
+ if (knownProperties.includes(prop)) {
1233
+ results = await this._handleKnownPropertyFilter(filterContext, prop, op, value);
1234
+ }
1235
+
1236
+ if (!results) {
1237
+ throw new Error(`The filter ${prop} ${op} ${value} was not understood`)
1238
+ }
1239
+ // Add to filter context
1240
+ if (!filterContext.filters) {
1241
+ filterContext.filters = [];
1242
+ }
1243
+ filterContext.filters.push(results);
1244
+
1245
+ return results;
1246
+ }
1247
+
1248
+ /**
1249
+ * Handle concept/code filters (is-a, descendent-of, etc.)
1250
+ * @param {FilterExecutionContext} filterContext - Filter context
1251
+ * @param {string} op - Filter operator
1252
+ * @param {string} value - Filter value (code)
1253
+ * @returns {Promise<FhirCodeSystemProviderFilterContext>} Filter results
1254
+ * @private
1255
+ */
1256
+ async _handleConceptFilter(filterContext, op, value) {
1257
+ const results = new FhirCodeSystemProviderFilterContext();
1258
+
1259
+ if (op === 'is-a' || op === 'descendent-of') {
1260
+ // Find all descendants of the specified code
1261
+ const includeRoot = (op === 'is-a');
1262
+ await this._addDescendants(results, value, includeRoot);
1263
+ }
1264
+ else if (op === 'is-not-a') {
1265
+ // Find all concepts that are NOT descendants of the specified code
1266
+ const excludeDescendants = this.codeSystem.getDescendants(value);
1267
+ const excludeSet = new Set([value, ...excludeDescendants]);
1268
+
1269
+ const allCodes = this.codeSystem.getAllCodes();
1270
+ for (const code of allCodes) {
1271
+ if (!excludeSet.has(code)) {
1272
+ const concept = this.codeSystem.getConceptByCode(code);
1273
+ if (concept) {
1274
+ results.add(concept, 0);
1275
+ }
1276
+ }
1277
+ }
1278
+ }
1279
+ else if (op === 'in') {
1280
+ // Value is comma-separated list of codes
1281
+ const codes = value.split(',').map(c => c.trim());
1282
+ for (const code of codes) {
1283
+ const concept = this.codeSystem.getConceptByCode(code);
1284
+ if (concept) {
1285
+ results.add(concept, 0);
1286
+ }
1287
+ }
1288
+ }
1289
+ else if (op === '=') {
1290
+ // Exact match
1291
+ const concept = this.codeSystem.getConceptByCode(value);
1292
+ if (concept) {
1293
+ results.add(concept, 0);
1294
+ }
1295
+ }
1296
+ else if (op === 'regex') {
1297
+ // Regular expression match
1298
+ try {
1299
+ const regex = new RegExp('^' + value + '$');
1300
+ const allCodes = this.codeSystem.getAllCodes();
1301
+ for (const code of allCodes) {
1302
+ if (regex.test(code)) {
1303
+ const concept = this.codeSystem.getConceptByCode(code);
1304
+ if (concept) {
1305
+ results.add(concept, 0);
1306
+ }
1307
+ }
1308
+ }
1309
+ } catch (error) {
1310
+ throw new Error(`Invalid regex pattern: ${value}`);
1311
+ }
1312
+ }
1313
+
1314
+ return results;
1315
+ }
1316
+
1317
+ /**
1318
+ * Add descendants of a code to the results
1319
+ * @param {FhirCodeSystemProviderFilterContext} results - Results to add to
1320
+ * @param {string} ancestorCode - The ancestor code
1321
+ * @param {boolean} includeRoot - Whether to include the root code itself
1322
+ * @private
1323
+ */
1324
+ async _addDescendants(results, ancestorCode, includeRoot) {
1325
+ const concept = this.codeSystem.getConceptByCode(ancestorCode);
1326
+ if (concept) {
1327
+ if (includeRoot) {
1328
+ results.add(concept, 0);
1329
+ }
1330
+ const descendants = this.codeSystem.getDescendants(ancestorCode);
1331
+ for (const code of descendants) {
1332
+ if (code !== ancestorCode) {
1333
+ const concept = this.codeSystem.getConceptByCode(code);
1334
+ if (concept) {
1335
+ results.add(concept, 0);
1336
+ }
1337
+ }
1338
+ }
1339
+ }
1340
+ }
1341
+
1342
+ /**
1343
+ * Handle child exists filter
1344
+ * @param {FilterExecutionContext} filterContext - Filter context
1345
+ * @param {string} value - 'true' or 'false'
1346
+ * @returns {Promise<FhirCodeSystemProviderFilterContext>} Filter results
1347
+ * @private
1348
+ */
1349
+ async _handleChildExistsFilter(filterContext, value) {
1350
+ const results = new FhirCodeSystemProviderFilterContext();
1351
+ const wantChildren = (value === 'true');
1352
+
1353
+ const allCodes = this.codeSystem.getAllCodes();
1354
+ for (const code of allCodes) {
1355
+ const hasChildren = this.codeSystem.getChildren(code).length > 0;
1356
+ if (hasChildren === wantChildren) {
1357
+ const concept = this.codeSystem.getConceptByCode(code);
1358
+ if (concept) {
1359
+ results.add(concept, 0);
1360
+ }
1361
+ }
1362
+ }
1363
+
1364
+ return results;
1365
+ }
1366
+
1367
+ /**
1368
+ * Handle property-based filter
1369
+ * @param {FilterExecutionContext} filterContext - Filter context
1370
+ * @param {Object} propertyDef - Property definition
1371
+ * @param {string} op - Filter operator
1372
+ * @param {string} value - Filter value
1373
+ * @returns {Promise<FhirCodeSystemProviderFilterContext>} Filter results
1374
+ * @private
1375
+ */
1376
+ async _handlePropertyFilter(filterContext, propertyDef, op, value) {
1377
+ const results = new FhirCodeSystemProviderFilterContext();
1378
+ const allConcepts = this.codeSystem.getAllConcepts();
1379
+
1380
+ for (const concept of allConcepts) {
1381
+ if (this._conceptMatchesPropertyFilter(concept, propertyDef, op, value)) {
1382
+ results.add(concept, 0);
1383
+ }
1384
+ }
1385
+
1386
+ return results;
1387
+ }
1388
+
1389
+ /**
1390
+ * Check if concept matches property filter
1391
+ * @param {Object} concept - The concept to check
1392
+ * @param {Object} propertyDef - Property definition
1393
+ * @param {string} op - Filter operator
1394
+ * @param {string} value - Filter value
1395
+ * @returns {boolean} True if concept matches filter
1396
+ * @private
1397
+ */
1398
+ _conceptMatchesPropertyFilter(concept, propertyDef, op, value) {
1399
+ if (!concept.property || !Array.isArray(concept.property)) {
1400
+ return false;
1401
+ }
1402
+
1403
+ const properties = concept.property.filter(p => p.code === propertyDef.code);
1404
+
1405
+ if (op === '=') {
1406
+ return properties.some(p => this._getPropertyValue(p) === value);
1407
+ }
1408
+ else if (op === 'in') {
1409
+ const values = value.split(',').map(v => v.trim());
1410
+ return properties.some(p => values.includes(this._getPropertyValue(p)));
1411
+ }
1412
+ else if (op === 'not-in') {
1413
+ const values = value.split(',').map(v => v.trim());
1414
+ return !properties.some(p => values.includes(this._getPropertyValue(p)));
1415
+ }
1416
+ else if (op === 'regex') {
1417
+ try {
1418
+ const regex = new RegExp('^' + value + '$');
1419
+ return properties.some(p => regex.test(this._getPropertyValue(p)));
1420
+ } catch (error) {
1421
+ return false;
1422
+ }
1423
+ }
1424
+
1425
+ return false;
1426
+ }
1427
+
1428
+ /**
1429
+ * Get property value as string
1430
+ * @param {Object} property - The property object
1431
+ * @returns {string} Property value
1432
+ * @private
1433
+ */
1434
+ _getPropertyValue(property) {
1435
+ if (property.valueCode) return property.valueCode;
1436
+ if (property.valueString) return property.valueString;
1437
+ if (property.valueInteger !== undefined) return property.valueInteger.toString();
1438
+ if (property.valueBoolean !== undefined) return property.valueBoolean.toString();
1439
+ if (property.valueDecimal !== undefined) return property.valueDecimal.toString();
1440
+ if (property.valueDateTime) return property.valueDateTime;
1441
+ if (property.valueCoding) return property.valueCoding.code || '';
1442
+
1443
+ return '';
1444
+ }
1445
+
1446
+ /**
1447
+ * Handle known property filters (notSelectable, status, etc.)
1448
+ * @param {FilterExecutionContext} filterContext - Filter context
1449
+ * @param {string} prop - Property name
1450
+ * @param {string} op - Filter operator
1451
+ * @param {string} value - Filter value
1452
+ * @returns {Promise<FhirCodeSystemProviderFilterContext>} Filter results
1453
+ * @private
1454
+ */
1455
+ async _handleKnownPropertyFilter(filterContext, prop, op, value) {
1456
+ const results = new FhirCodeSystemProviderFilterContext();
1457
+ const allConcepts = this.codeSystem.getAllConcepts();
1458
+
1459
+ for (const concept of allConcepts) {
1460
+ let matches = false;
1461
+
1462
+ if (prop === 'notSelectable') {
1463
+ const abstractProp = (concept.property || []).find(p => p.code === 'abstract' || p.code === 'notSelectable' || p.uri === 'http://hl7.org/fhir/concept-properties#notSelectable');
1464
+ let vv = abstractProp ? String(getValuePrimitive(abstractProp)) : null;
1465
+ if (op === '=') {
1466
+ matches = (vv === value);
1467
+ } else if (op === 'in') {
1468
+ const values = value.split(',').map(v => v.trim());
1469
+ matches = values.includes(vv);
1470
+ } else if (op === 'not-in') {
1471
+ const values = value.split(',').map(v => v.trim());
1472
+ matches = !values.includes(vv);
1473
+ }
1474
+ }
1475
+ else if (prop === 'status') {
1476
+ const status = await this.getStatus(new FhirCodeSystemProviderContext(concept.code, concept));
1477
+ if (op === '=') {
1478
+ matches = (status === value);
1479
+ } else if (op === 'in') {
1480
+ const values = value.split(',').map(v => v.trim());
1481
+ matches = values.includes(status);
1482
+ } else if (op === 'not-in') {
1483
+ const values = value.split(',').map(v => v.trim());
1484
+ matches = !values.includes(status);
1485
+ }
1486
+ }
1487
+ else if (prop === 'inactive') {
1488
+ const isInactive = await this.isInactive(new FhirCodeSystemProviderContext(concept.code, concept));
1489
+ const expectedValue = (value === 'true');
1490
+ matches = (isInactive === expectedValue);
1491
+ }
1492
+ else if (prop === 'deprecated') {
1493
+ const isDeprecated = await this.isDeprecated(new FhirCodeSystemProviderContext(concept.code, concept));
1494
+ const expectedValue = (value === 'true');
1495
+ matches = (isDeprecated === expectedValue);
1496
+ }
1497
+
1498
+ if (matches) {
1499
+ results.add(concept, 0);
1500
+ }
1501
+ }
1502
+
1503
+ return results;
1504
+ }
1505
+
1506
+ versionAlgorithm() {
1507
+ return this.codeSystem.versionAlgorithm();
1508
+ }
1509
+
1510
+ versionNeeded() {
1511
+ return this.codeSystem.jsonObj.versionNeeded;
1512
+ }
1513
+
1514
+ }
1515
+
1516
+ class FhirCodeSystemFactory extends CodeSystemFactoryProvider {
1517
+ constructor(i18n) {
1518
+ super(i18n);
1519
+ }
1520
+
1521
+ defaultVersion() {
1522
+ return 'unknown'; // No default version for FHIR CodeSystems
1523
+ }
1524
+
1525
+ /**
1526
+ * Build a FHIR CodeSystem provider
1527
+ * @param {CodeSystem} codeSystem - The FHIR CodeSystem to wrap
1528
+ * @param {CodeSystem[]} supplements - Array of supplement CodeSystems
1529
+ * @returns {FhirCodeSystemProvider} New provider instance
1530
+ */
1531
+ build(opContext, supplements, codeSystem) {
1532
+ this.recordUse();
1533
+
1534
+ // Validate parameters
1535
+ if (!codeSystem || typeof codeSystem !== 'object') {
1536
+ throw new Error('codeSystem parameter is required and must be a CodeSystem object');
1537
+ }
1538
+
1539
+ if (codeSystem.jsonObj?.resourceType !== 'CodeSystem') {
1540
+ throw new Error('codeSystem must be a FHIR CodeSystem resource');
1541
+ }
1542
+
1543
+ // Validate supplements array
1544
+ if (supplements && !Array.isArray(supplements)) {
1545
+ throw new Error('supplements must be an array');
1546
+ }
1547
+
1548
+ if (supplements) {
1549
+ supplements.forEach((supplement, index) => {
1550
+ if (!supplement || typeof supplement !== 'object' || supplement.jsonObj?.resourceType !== 'CodeSystem') {
1551
+ throw new Error(`Supplement ${index} must be a FHIR CodeSystem resource`);
1552
+ }
1553
+ });
1554
+ }
1555
+
1556
+ return new FhirCodeSystemProvider(opContext, codeSystem, supplements);
1557
+ }
1558
+
1559
+ // eslint-disable-next-line no-unused-vars
1560
+ async buildKnownValueSet(url, version) {
1561
+ return null;
1562
+ }
1563
+
1564
+ name() {
1565
+ return "CodeSystem";
1566
+ }
1567
+
1568
+ id() {
1569
+ return "cs";
1570
+ }
1571
+
1572
+ }
1573
+
1574
+ module.exports = {
1575
+ FhirCodeSystemFactory,
1576
+ FhirCodeSystemProvider,
1577
+ FhirCodeSystemProviderContext,
1578
+ FhirCodeSystemProviderFilterContext
1579
+ };