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,1102 @@
1
+ const { CodeSystemProvider, CodeSystemContentMode, Designation, CodeSystemFactoryProvider} = require('./cs-api');
2
+ const {
3
+ SnomedStrings, SnomedWords, SnomedStems, SnomedReferences,
4
+ SnomedDescriptions, SnomedDescriptionIndex, SnomedConceptList,
5
+ SnomedRelationshipList, SnomedReferenceSetMembers, SnomedReferenceSetIndex,
6
+ SnomedFileReader
7
+ } = require('../sct/structures');
8
+ const {
9
+ SnomedExpressionServices, SnomedExpression, SnomedConcept,
10
+ SnomedExpressionParser, NO_REFERENCE, SnomedServicesRenderOption
11
+ } = require('../sct/expressions');
12
+
13
+ // Context kinds matching Pascal enum
14
+ const SnomedProviderContextKind = {
15
+ CODE: 0,
16
+ EXPRESSION: 1
17
+ };
18
+
19
+ /**
20
+ * SNOMED Expression Context - represents either a simple concept or complex expression
21
+ */
22
+ class SnomedExpressionContext {
23
+ constructor(source = '', expression = null) {
24
+ this.source = source;
25
+ this.expression = expression;
26
+ }
27
+
28
+ static fromReference(reference) {
29
+ const expression = new SnomedExpression();
30
+ expression.concepts.push(new SnomedConcept(reference));
31
+ return new SnomedExpressionContext('', expression);
32
+ }
33
+
34
+ static fromCode(code, reference) {
35
+ const expression = new SnomedExpression();
36
+ const concept = new SnomedConcept(reference);
37
+ concept.code = code;
38
+ expression.concepts.push(concept);
39
+ return new SnomedExpressionContext(code, expression);
40
+ }
41
+
42
+ static fromExpression(source, expression) {
43
+ return new SnomedExpressionContext(source, expression);
44
+ }
45
+
46
+ isComplex() {
47
+ return this.expression && this.expression.isComplex();
48
+ }
49
+
50
+ isSimple() {
51
+ return this.expression && this.expression.isSimple();
52
+ }
53
+
54
+ getReference() {
55
+ return this.expression && this.expression.concepts.length > 0
56
+ ? this.expression.concepts[0].reference
57
+ : NO_REFERENCE;
58
+ }
59
+
60
+ getCode() {
61
+ if (this.source) return this.source;
62
+ return this.expression && this.expression.concepts.length > 0
63
+ ? this.expression.concepts[0].code
64
+ : '';
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Filter context for SNOMED filtering operations
70
+ */
71
+ class SnomedFilterContext {
72
+ constructor() {
73
+ this.ndx = 0;
74
+ this.cursor = 0;
75
+ this.matches = [];
76
+ this.members = [];
77
+ this.descendants = [];
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Core SNOMED services providing access to structures and expression processing
83
+ */
84
+ class SnomedServices {
85
+ constructor(sharedData) {
86
+ // Core data structures
87
+ this.strings = new SnomedStrings(sharedData.strings);
88
+ this.words = new SnomedWords(sharedData.words);
89
+ this.stems = new SnomedStems(sharedData.stems);
90
+ this.refs = new SnomedReferences(sharedData.refs);
91
+ this.descriptions = new SnomedDescriptions(sharedData.desc);
92
+ this.descriptionIndex = new SnomedDescriptionIndex(sharedData.descRef);
93
+ this.concepts = new SnomedConceptList(sharedData.concept);
94
+ this.relationships = new SnomedRelationshipList(sharedData.rel);
95
+ this.refSetIndex = new SnomedReferenceSetIndex(sharedData.refSetIndex, sharedData.hasLangs);
96
+ this.refSetMembers = new SnomedReferenceSetMembers(sharedData.refSetMembers);
97
+
98
+ // Metadata
99
+ this.versionUri = sharedData.versionUri;
100
+ this.versionDate = sharedData.versionDate;
101
+ this.edition = sharedData.edition;
102
+ this.version = sharedData.version;
103
+ this.totalCount = this.concepts.count();
104
+
105
+ // Indexes and roots
106
+ this.isAIndex = sharedData.isAIndex;
107
+ this.activeRoots = sharedData.activeRoots;
108
+ this.inactiveRoots = sharedData.inactiveRoots;
109
+ this.defaultLanguage = sharedData.defaultLanguage;
110
+ this.isTesting = sharedData.isTesting;
111
+
112
+ // Expression services
113
+ this.expressionServices = new SnomedExpressionServices({
114
+ strings: this.strings,
115
+ words: this.words,
116
+ stems: this.stems,
117
+ refs: this.refs,
118
+ descriptions: this.descriptions,
119
+ descriptionIndex: this.descriptionIndex,
120
+ concepts: this.concepts,
121
+ relationships: this.relationships,
122
+ refSetMembers: this.refSetMembers,
123
+ refSetIndex: this.refSetIndex
124
+ }, this.isAIndex);
125
+
126
+ }
127
+
128
+ close() {
129
+ // Cleanup if needed
130
+ }
131
+
132
+ getSystemUri() {
133
+ return 'http://snomed.info/sct';
134
+ }
135
+
136
+ getVersion() {
137
+ return this.versionUri;
138
+ }
139
+
140
+ getDescription() {
141
+ return `SNOMED CT ${getEditionName(this.edition)}`;
142
+ }
143
+
144
+ name() {
145
+ return `SCT ${getEditionCode(this.edition)}`;
146
+ }
147
+
148
+ stringToIdOrZero(str) {
149
+ try {
150
+ if (!str) return 0n;
151
+ return BigInt(str);
152
+ } catch {
153
+ return 0n;
154
+ }
155
+ }
156
+
157
+ stringToId(str) {
158
+ return BigInt(str);
159
+ }
160
+
161
+ getConceptId(reference) {
162
+ try {
163
+ const concept = this.concepts.getConcept(reference);
164
+ return concept.identity.toString();
165
+ } catch (error) {
166
+ return reference.toString();
167
+ }
168
+ }
169
+
170
+ conceptExists(conceptId) {
171
+ const id = this.stringToIdOrZero(conceptId);
172
+ if (id === 0n) return false;
173
+
174
+ const result = this.concepts.findConcept(id);
175
+ return result.found;
176
+ }
177
+
178
+ isActive(reference) {
179
+ try {
180
+ const concept = this.concepts.getConcept(reference);
181
+ // Check status flags - active concepts typically have status 0
182
+ return (concept.flags & 0x0F) === 0;
183
+ } catch (error) {
184
+ return false;
185
+ }
186
+ }
187
+
188
+ isPrimitive(reference) {
189
+ try {
190
+ const concept = this.concepts.getConcept(reference);
191
+ // Check primitive flag
192
+ return (concept.flags & 0x10) !== 0;
193
+ } catch (error) {
194
+ return true; // Assume primitive if can't read
195
+ }
196
+ }
197
+
198
+ subsumes(parentRef, childRef) {
199
+ if (parentRef === childRef) {
200
+ return true;
201
+ }
202
+
203
+ try {
204
+ // Get the closure (all descendants) for parent concept
205
+ const closureRef = this.concepts.getAllDesc(parentRef);
206
+
207
+ if (closureRef === 0 || closureRef === 0xFFFFFFFF) {
208
+ return false;
209
+ }
210
+
211
+ const descendants = this.refs.getReferences(closureRef);
212
+ return descendants && descendants.includes(childRef);
213
+ } catch (error) {
214
+ return false;
215
+ }
216
+ }
217
+
218
+ getDisplayName(reference = 0) {
219
+ try {
220
+ const concept = this.concepts.getConcept(reference);
221
+ const descriptionsRef = concept.descriptions;
222
+
223
+ if (descriptionsRef === 0) {
224
+ return '';
225
+ }
226
+
227
+ const descriptionIndices = this.refs.getReferences(descriptionsRef);
228
+
229
+ // Look for preferred term, then any active description
230
+ for (const descIndex of descriptionIndices) {
231
+ const description = this.descriptions.getDescription(descIndex);
232
+ if (description.active) {
233
+ const term = this.strings.getEntry(description.iDesc);
234
+ return term.trim();
235
+ }
236
+ }
237
+
238
+ return '';
239
+ } catch (error) {
240
+ return '';
241
+ }
242
+ }
243
+
244
+ getConceptDescendants(reference) {
245
+ try {
246
+ const allDescRef = this.concepts.getAllDesc(reference);
247
+ if (allDescRef === 0 || allDescRef === 0xFFFFFFFF) {
248
+ return [];
249
+ }
250
+ return this.refs.getReferences(allDescRef) || [];
251
+ } catch (error) {
252
+ return [];
253
+ }
254
+ }
255
+
256
+ getConceptChildren(reference) {
257
+ try {
258
+ const concept = this.concepts.getConcept(reference);
259
+ const inboundsRef = concept.inbounds;
260
+
261
+ if (inboundsRef === 0) return [];
262
+
263
+ const inbounds = this.refs.getReferences(inboundsRef);
264
+ const children = [];
265
+
266
+ for (const relIndex of inbounds) {
267
+ const rel = this.relationships.getRelationship(relIndex);
268
+ if (rel.active && rel.relType === this.isAIndex && rel.group === 0) {
269
+ children.push(rel.source);
270
+ }
271
+ }
272
+
273
+ return children;
274
+ } catch (error) {
275
+ return [];
276
+ }
277
+ }
278
+
279
+ getConceptParents(reference) {
280
+ try {
281
+ const concept = this.concepts.getConcept(reference);
282
+ const parentsRef = concept.parents;
283
+
284
+ if (parentsRef === 0) return [];
285
+
286
+ return this.refs.getReferences(parentsRef) || [];
287
+ } catch (error) {
288
+ return [];
289
+ }
290
+ }
291
+
292
+ getConceptRefSet(conceptIndex, byName = false) {
293
+ for (let i = 0; i < this.refSetIndex.count(); i++) {
294
+ const refSet = this.refSetIndex.getReferenceSet(i);
295
+ if (refSet.definition === conceptIndex) {
296
+ return byName ? refSet.membersByName : refSet.membersByRef;
297
+ }
298
+ }
299
+ return 0;
300
+ }
301
+
302
+ // Filter support methods
303
+ filterEquals(id) {
304
+ const result = new SnomedFilterContext();
305
+ const conceptResult = this.concepts.findConcept(id);
306
+
307
+ if (!conceptResult.found) {
308
+ throw new Error(`The SNOMED CT Concept ${id} is not known`);
309
+ }
310
+
311
+ result.descendants = [conceptResult.index];
312
+ return result;
313
+ }
314
+
315
+ filterIsA(id, includeBase = true) {
316
+ const result = new SnomedFilterContext();
317
+ const conceptResult = this.concepts.findConcept(id);
318
+
319
+ if (!conceptResult.found) {
320
+ throw new Error(`The SNOMED CT Concept ${id} is not known`);
321
+ }
322
+
323
+ const descendants = this.getConceptDescendants(conceptResult.index);
324
+
325
+ if (includeBase) {
326
+ result.descendants = [conceptResult.index, ...descendants];
327
+ } else {
328
+ result.descendants = descendants;
329
+ }
330
+
331
+ return result;
332
+ }
333
+
334
+ filterIn(id) {
335
+ const result = new SnomedFilterContext();
336
+ const conceptResult = this.concepts.findConcept(id);
337
+
338
+ if (!conceptResult.found) {
339
+ throw new Error(`The SNOMED CT Concept ${id} is not known`);
340
+ }
341
+
342
+ const refSetIndex = this.getConceptRefSet(conceptResult.index, false);
343
+ if (refSetIndex === 0) {
344
+ throw new Error(`The SNOMED CT Concept ${id} is not a reference set`);
345
+ }
346
+
347
+ result.members = this.refSetMembers.getMembers(refSetIndex) || [];
348
+ return result;
349
+ }
350
+
351
+ searchFilter(searchText, includeInactive = false, exactMatch = false) {
352
+ const result = new SnomedFilterContext();
353
+
354
+ // Simplified search - in full implementation would use stemming and word indexes
355
+ const searchTerms = searchText.toLowerCase().split(/\s+/);
356
+ const matches = [];
357
+
358
+ // Search through all concepts
359
+ for (let i = 0; i < this.concepts.count(); i++) {
360
+ const conceptIndex = i * this.concepts.constructor.CONCEPT_SIZE;
361
+
362
+ try {
363
+ const concept = this.concepts.getConcept(conceptIndex);
364
+ if (!includeInactive && !this.isActive(conceptIndex)) {
365
+ continue;
366
+ }
367
+
368
+ const descriptionsRef = concept.descriptions;
369
+ if (descriptionsRef === 0) continue;
370
+
371
+ const descriptionIndices = this.refs.getReferences(descriptionsRef);
372
+ let matchFound = false;
373
+ let priority = 0;
374
+
375
+ for (const descIndex of descriptionIndices) {
376
+ const description = this.descriptions.getDescription(descIndex);
377
+ if (description.active) {
378
+ const term = this.strings.getEntry(description.iDesc).toLowerCase();
379
+
380
+ if (exactMatch) {
381
+ // All search terms must be present
382
+ matchFound = searchTerms.every(searchTerm => term.includes(searchTerm));
383
+ } else {
384
+ // Any search term can match
385
+ matchFound = searchTerms.some(searchTerm => term.includes(searchTerm));
386
+ }
387
+
388
+ if (matchFound) {
389
+ // Calculate priority based on match quality
390
+ if (term === searchText.toLowerCase()) {
391
+ priority = 100; // Exact match
392
+ } else if (term.startsWith(searchText.toLowerCase())) {
393
+ priority = 50; // Prefix match
394
+ } else {
395
+ priority = 10; // Contains match
396
+ }
397
+ break;
398
+ }
399
+ }
400
+ }
401
+
402
+ if (matchFound) {
403
+ matches.push({
404
+ index: conceptIndex,
405
+ term: concept.identity,
406
+ priority: priority
407
+ });
408
+ }
409
+ } catch (error) {
410
+ // Skip problematic concepts
411
+ continue;
412
+ }
413
+ }
414
+
415
+ // Sort by priority (descending)
416
+ matches.sort((a, b) => b.priority - a.priority);
417
+
418
+ result.matches = matches;
419
+ return result;
420
+ }
421
+ }
422
+
423
+ /**
424
+ * SNOMED CT Code System Provider
425
+ */
426
+ class SnomedProvider extends CodeSystemProvider {
427
+ constructor(opContext, supplements, snomedServices) {
428
+ super(opContext, supplements);
429
+ this.sct = snomedServices;
430
+ }
431
+
432
+ // Metadata methods
433
+ system() {
434
+ return this.sct.getSystemUri();
435
+ }
436
+
437
+ version() {
438
+ return this.sct.getVersion();
439
+ }
440
+
441
+
442
+ /**
443
+ * @param {string} checkVersion - first version
444
+ * @param {string} actualVersion - second version
445
+ * @returns {boolean} True if actualVersion is more detailed than checkVersion (for SCT)
446
+ */
447
+ versionIsMoreDetailed(checkVersion, actualVersion) {
448
+ return actualVersion && actualVersion.startsWith(checkVersion);
449
+ }
450
+
451
+ description() {
452
+ return this.sct.getDescription();
453
+ }
454
+
455
+ totalCount() {
456
+ return this.sct.totalCount;
457
+ }
458
+
459
+ contentMode() {
460
+ return CodeSystemContentMode.Complete;
461
+ }
462
+
463
+ hasParents() {
464
+ return true;
465
+ }
466
+
467
+ hasAnyDisplays(languages) {
468
+ const langs = this._ensureLanguages(languages);
469
+
470
+ // Check supplements first
471
+ if (this._hasAnySupplementDisplays(langs)) {
472
+ return true;
473
+ }
474
+
475
+ // SNOMED has displays for English and other languages
476
+ return langs.isEnglishOrNothing();
477
+ }
478
+
479
+ // Core concept methods
480
+ async code(context) {
481
+
482
+ const ctxt = await this.#ensureContext(context);
483
+
484
+ if (!ctxt) return null;
485
+
486
+ if (ctxt.isComplex()) {
487
+ return this.sct.expressionServices.renderExpression(ctxt.expression, SnomedServicesRenderOption.Minimal);
488
+ } else {
489
+ return ctxt.getCode() || this.sct.getConceptId(ctxt.getReference());
490
+ }
491
+ }
492
+
493
+ async display(context) {
494
+
495
+ const ctxt = await this.#ensureContext(context);
496
+
497
+ if (!ctxt) return null;
498
+
499
+ // Check supplements first
500
+ let disp = this._displayFromSupplements(ctxt.getCode());
501
+ if (disp) return disp;
502
+
503
+ if (ctxt.isComplex()) {
504
+ return this.sct.expressionServices.displayExpression(ctxt.expression);
505
+ } else {
506
+ return this.sct.getDisplayName(ctxt.getReference(), this.sct.defaultLanguage);
507
+ }
508
+ }
509
+
510
+ async definition(context) {
511
+ await this.#ensureContext(context);
512
+ return null; // SNOMED doesn't provide definitions in this sense
513
+ }
514
+
515
+ async isAbstract(context) {
516
+ await this.#ensureContext(context);
517
+ return false; // SNOMED concepts are not abstract
518
+ }
519
+
520
+ async isInactive(context) {
521
+
522
+ const ctxt = await this.#ensureContext(context);
523
+
524
+ if (!ctxt || ctxt.isComplex()) return false;
525
+
526
+ return !this.sct.isActive(ctxt.getReference());
527
+ }
528
+
529
+ async isDeprecated(context) {
530
+ await this.#ensureContext(context);
531
+
532
+ return false; // Handle via status if needed
533
+ }
534
+
535
+ async getStatus(context) {
536
+
537
+ const ctxt = await this.#ensureContext(context);
538
+
539
+ if (!ctxt || ctxt.isComplex()) return null;
540
+
541
+ return this.sct.isActive(ctxt.getReference()) ? 'active' : 'inactive';
542
+ }
543
+
544
+ async designations(context, displays) {
545
+
546
+ const ctxt = await this.#ensureContext(context);
547
+
548
+ if (ctxt) {
549
+
550
+
551
+ if (ctxt.isComplex()) {
552
+ // For complex expressions, just add the display
553
+ const display = await this.display(context);
554
+ if (display) {
555
+ displays.addDesignation(true, 'active', new Designation('en-US', null, display));
556
+ }
557
+ } else {
558
+ // Get all designations for the concept
559
+ try {
560
+ const concept = this.sct.concepts.getConcept(ctxt.getReference());
561
+ const descriptionsRef = concept.descriptions;
562
+
563
+ if (descriptionsRef !== 0) {
564
+ const descriptionIndices = this.sct.refs.getReferences(descriptionsRef);
565
+
566
+ for (const descIndex of descriptionIndices) {
567
+ const description = this.sct.descriptions.getDescription(descIndex);
568
+ const term = this.sct.strings.getEntry(description.iDesc).trim();
569
+ const langCode = this.getLanguageCode(description.lang);
570
+ const kind = this.sct.concepts.getConcept(description.kind);
571
+ const kid = String(kind.identity);
572
+ const kdesc = this.sct.getDisplayName(description.kind);
573
+ let use = { system: 'http://snomed.info/sct', code: kid, display : kdesc};
574
+
575
+ displays.addDesignation(false, description.active ? 'active' : 'inactive', langCode, use, term);
576
+ }
577
+ }
578
+ } catch (error) {
579
+ // Add basic designation if we can't read detailed descriptions
580
+ const display = this.sct.getDisplayName(ctxt.getReference());
581
+ if (display) {
582
+ displays.addDesignation(true, 'active','en-US', null, display);
583
+ }
584
+ }
585
+
586
+ // Add supplement designations
587
+ this._listSupplementDesignations(ctxt.getCode(), displays);
588
+ }
589
+ }
590
+ }
591
+
592
+ getLanguageCode(langIndex) {
593
+ const languageMap = {
594
+ 1: 'en',
595
+ 2: 'en-GB',
596
+ 3: 'es',
597
+ 4: 'fr',
598
+ 5: 'de'
599
+ };
600
+ return languageMap[langIndex] || 'en';
601
+ }
602
+
603
+ // Lookup methods
604
+ async locate(code) {
605
+
606
+
607
+ if (!code) return { context: null, message: 'Empty code' };
608
+
609
+ const conceptId = this.sct.stringToIdOrZero(code);
610
+
611
+ if (conceptId === 0n) {
612
+ // Try parsing as expression
613
+ try {
614
+ const expression = new SnomedExpressionParser().parse(code);
615
+ this.sct.expressionServices.checkExpression(expression);
616
+ return {
617
+ context: SnomedExpressionContext.fromExpression(code, expression),
618
+ message: null
619
+ };
620
+ } catch (error) {
621
+ return {
622
+ context: null,
623
+ message: `Code ${code} is not a valid SNOMED CT Term, and could not be parsed as an expression (${error.message})`
624
+ };
625
+ }
626
+ } else {
627
+ const result = this.sct.concepts.findConcept(conceptId);
628
+ if (result.found) {
629
+ return {
630
+ context: SnomedExpressionContext.fromCode(code, result.index),
631
+ message: null
632
+ };
633
+ } else {
634
+ return {
635
+ context: null,
636
+ message: undefined
637
+ };
638
+ }
639
+ }
640
+ }
641
+
642
+ async locateIsA(code, parent, disallowParent = false) {
643
+
644
+
645
+ const childId = this.sct.stringToIdOrZero(code);
646
+ const parentId = this.sct.stringToIdOrZero(parent);
647
+
648
+ if (childId === 0n || parentId === 0n) {
649
+ return { context: null, message: 'Invalid concept ID' };
650
+ }
651
+
652
+ const childResult = this.sct.concepts.findConcept(childId);
653
+ const parentResult = this.sct.concepts.findConcept(parentId);
654
+
655
+ if (!childResult.found || !parentResult.found) {
656
+ return { context: null, message: 'Concept not found' };
657
+ }
658
+
659
+ const subsumes = this.sct.subsumes(parentResult.index, childResult.index);
660
+ const allowedByParent = !disallowParent || (childResult.index !== parentResult.index);
661
+
662
+ if (subsumes && allowedByParent) {
663
+ return {
664
+ context: SnomedExpressionContext.fromCode(code, childResult.index),
665
+ message: null
666
+ };
667
+ } else {
668
+ return { context: null, message: 'Concept is not subsumed by parent' };
669
+ }
670
+ }
671
+
672
+ // Iterator methods
673
+ async iterator(context) {
674
+
675
+
676
+ if (!context) {
677
+ // Iterate all active root concepts
678
+ return {
679
+ context: null,
680
+ keys: this.sct.activeRoots.slice(),
681
+ current: 0,
682
+ total: this.sct.activeRoots.length
683
+ };
684
+ } else {
685
+ const ctxt = await this.#ensureContext(context);
686
+ if (!ctxt || ctxt.isComplex()) {
687
+ return { context: ctxt, keys: [], current: 0, total: 0 };
688
+ }
689
+
690
+ // Get children of this concept
691
+ const children = this.sct.getConceptChildren(ctxt.getReference());
692
+ return {
693
+ context: ctxt,
694
+ keys: children,
695
+ current: 0,
696
+ total: children.length
697
+ };
698
+ }
699
+ }
700
+
701
+ async nextContext(iteratorContext) {
702
+
703
+
704
+ if (iteratorContext.current >= iteratorContext.total) {
705
+ return null;
706
+ }
707
+
708
+ const key = iteratorContext.keys[iteratorContext.current];
709
+ iteratorContext.current++;
710
+
711
+ return SnomedExpressionContext.fromReference(key);
712
+ }
713
+
714
+ // Filter support
715
+ async doesFilter(prop, op, value) {
716
+
717
+
718
+ if (prop === 'concept') {
719
+ const id = this.sct.stringToIdOrZero(value);
720
+ if (id !== 0n && ['=', 'is-a', 'descendent-of', 'in'].includes(op)) {
721
+ return this.sct.conceptExists(value);
722
+ }
723
+ }
724
+
725
+ return false;
726
+ }
727
+
728
+ // eslint-disable-next-line no-unused-vars
729
+ async getPrepContext(iterate) {
730
+
731
+ return {}; // Simple filter context
732
+ }
733
+
734
+ async filter(filterContext, prop, op, value) {
735
+
736
+
737
+ if (prop === 'concept') {
738
+ const id = this.sct.stringToIdOrZero(value);
739
+ if (id === 0n) {
740
+ throw new Error(`Invalid concept ID: ${value}`);
741
+ }
742
+
743
+ switch (op) {
744
+ case '=':
745
+ return this.sct.filterEquals(id);
746
+ case 'is-a':
747
+ return this.sct.filterIsA(id, true);
748
+ case 'descendent-of':
749
+ return this.sct.filterIsA(id, false);
750
+ case 'in':
751
+ return this.sct.filterIn(id);
752
+ default:
753
+ throw new Error(`Unsupported filter operation: ${op}`);
754
+ }
755
+ }
756
+
757
+ throw new Error(`Unsupported filter property: ${prop}`);
758
+ }
759
+
760
+ async executeFilters(filterContext) {
761
+
762
+ return [filterContext];
763
+ }
764
+
765
+ async filterSize(filterContext, set) {
766
+
767
+
768
+ if (set.matches && set.matches.length > 0) {
769
+ return set.matches.length;
770
+ } else if (set.members && set.members.length > 0) {
771
+ return set.members.length;
772
+ } else if (set.descendants && set.descendants.length > 0) {
773
+ return set.descendants.length;
774
+ }
775
+
776
+ return 0;
777
+ }
778
+
779
+ async filterMore(filterContext, set) {
780
+
781
+ set.cursor = set.cursor || 0;
782
+
783
+ const size = await this.filterSize(filterContext, set);
784
+ return set.cursor < size;
785
+ }
786
+
787
+ async filterConcept(filterContext, set) {
788
+
789
+
790
+ const size = await this.filterSize(filterContext, set);
791
+ if (set.cursor >= size) {
792
+ return null;
793
+ }
794
+
795
+ let key;
796
+ if (set.matches && set.matches.length > 0) {
797
+ key = set.matches[set.cursor].index;
798
+ } else if (set.members && set.members.length > 0) {
799
+ key = set.members[set.cursor].ref;
800
+ } else if (set.descendants && set.descendants.length > 0) {
801
+ key = set.descendants[set.cursor];
802
+ } else {
803
+ return null;
804
+ }
805
+
806
+ set.cursor++;
807
+ return SnomedExpressionContext.fromReference(key);
808
+ }
809
+
810
+ async filterLocate(filterContext, set, code) {
811
+
812
+
813
+ const conceptResult = await this.locate(code);
814
+ if (!conceptResult.context) {
815
+ return conceptResult.message;
816
+ }
817
+
818
+ const ctxt = conceptResult.context;
819
+ if (ctxt.isComplex()) {
820
+ return 'Complex expressions not supported in filters';
821
+ }
822
+
823
+ const reference = ctxt.getReference();
824
+ let found = false;
825
+
826
+ if (set.matches && set.matches.length > 0) {
827
+ found = set.matches.some(m => m.index === reference);
828
+ } else if (set.members && set.members.length > 0) {
829
+ found = set.members.some(m => m.ref === reference);
830
+ } else if (set.descendants && set.descendants.length > 0) {
831
+ found = set.descendants.includes(reference);
832
+ }
833
+
834
+ if (found) {
835
+ return ctxt;
836
+ } else {
837
+ return `Code ${code} is not in the specified filter`;
838
+ }
839
+ }
840
+
841
+ async filterCheck(filterContext, set, concept) {
842
+
843
+
844
+ if (!(concept instanceof SnomedExpressionContext)) {
845
+ return false;
846
+ }
847
+
848
+ if (concept.isComplex()) {
849
+ return false;
850
+ }
851
+
852
+ const reference = concept.getReference();
853
+
854
+ if (set.matches && set.matches.length > 0) {
855
+ return set.matches.some(m => m.index === reference);
856
+ } else if (set.members && set.members.length > 0) {
857
+ return set.members.some(m => m.ref === reference);
858
+ } else if (set.descendants && set.descendants.length > 0) {
859
+ return set.descendants.includes(reference);
860
+ }
861
+
862
+ return false;
863
+ }
864
+
865
+
866
+ // Search filter
867
+ async searchFilter(filterContext, filter, sort) {
868
+ return this.sct.searchFilter(filter, false, sort);
869
+ }
870
+
871
+ // Subsumption testing
872
+ async subsumesTest(codeA, codeB) {
873
+
874
+
875
+ try {
876
+ const exprA = new SnomedExpressionParser(this.sct.concepts).parse(codeA);
877
+ const exprB = new SnomedExpressionParser(this.sct.concepts).parse(codeB);
878
+
879
+ if (exprA.isSimple() && exprB.isSimple()) {
880
+ const refA = exprA.concepts[0].reference;
881
+ const refB = exprB.concepts[0].reference;
882
+
883
+ if (refA === refB) {
884
+ return 'equivalent';
885
+ } else if (this.sct.subsumes(refA, refB)) {
886
+ return 'subsumes';
887
+ } else if (this.sct.subsumes(refB, refA)) {
888
+ return 'subsumed-by';
889
+ } else {
890
+ return 'not-subsumed';
891
+ }
892
+ } else {
893
+ const b1 = this.sct.expressionServices.expressionSubsumes(exprA, exprB);
894
+ const b2 = this.sct.expressionServices.expressionSubsumes(exprB, exprA);
895
+
896
+ if (b1 && b2) {
897
+ return 'equivalent';
898
+ } else if (b1) {
899
+ return 'subsumes';
900
+ } else if (b2) {
901
+ return 'subsumed-by';
902
+ } else {
903
+ return 'not-subsumed';
904
+ }
905
+ }
906
+ } catch (error) {
907
+ throw new Error(`Error in subsumption test: ${error.message}`);
908
+ }
909
+ }
910
+
911
+ // Helper methods
912
+ async #ensureContext(context) {
913
+ if (!context) {
914
+ return null;
915
+ }
916
+
917
+ if (typeof context === 'string') {
918
+ const result = await this.locate(context);
919
+ if (!result.context) {
920
+ throw new Error(result.message);
921
+ }
922
+ return result.context;
923
+ }
924
+
925
+ if (context instanceof SnomedExpressionContext) {
926
+ return context;
927
+ }
928
+
929
+ throw new Error(`Unknown type at #ensureContext: ${typeof context}`);
930
+ }
931
+
932
+ versionAlgorithm() {
933
+ return 'url';
934
+ }
935
+
936
+ isNotClosed() {
937
+ return true;
938
+ }
939
+
940
+ isDisplay(cd) {
941
+ return cd.use.system === this.system() &&
942
+ (cd.use.code === '900000000000013009' || cd.use.code === '900000000000003001');
943
+ }
944
+
945
+ }
946
+
947
+ /**
948
+ * Factory for creating SNOMED services and providers
949
+ */
950
+ class SnomedServicesFactory extends CodeSystemFactoryProvider {
951
+ constructor(i18n, filePath) {
952
+ super(i18n);
953
+ this.filePath = filePath;
954
+ this.uses = 0;
955
+ this._loaded = false;
956
+ this._sharedData = null;
957
+ }
958
+
959
+ system() {
960
+ return 'http://snomed.info/sct';
961
+ }
962
+
963
+ version() {
964
+ return this._sharedData.versionUri;
965
+ }
966
+
967
+ getPartialVersion() {
968
+ let ver = this.version();
969
+ if (ver.includes("/version")) {
970
+ return ver.substring(0, ver.indexOf("/version"));
971
+ } else {
972
+ return null;
973
+ }
974
+ }
975
+ // eslint-disable-next-line no-unused-vars
976
+ async buildKnownValueSet(url, version) {
977
+ return null;
978
+ }
979
+
980
+ async #ensureLoaded() {
981
+ if (!this._loaded) {
982
+ await this.load();
983
+ }
984
+ }
985
+
986
+ async load() {
987
+ const reader = new SnomedFileReader(this.filePath);
988
+ this._sharedData = await reader.loadSnomedData();
989
+ this.snomedServices = new SnomedServices(this._sharedData);
990
+ this._loaded = true;
991
+ }
992
+
993
+ defaultVersion() {
994
+ return this._sharedData?.version || 'unknown';
995
+ }
996
+
997
+ async build(opContext, supplements = []) {
998
+ await this.#ensureLoaded();
999
+ this.recordUse();
1000
+ return new SnomedProvider(opContext, supplements, this.snomedServices);
1001
+ }
1002
+
1003
+ useCount() {
1004
+ return this.uses;
1005
+ }
1006
+
1007
+ recordUse() {
1008
+ this.uses++;
1009
+ }
1010
+
1011
+
1012
+ name() {
1013
+ return `SCT ${getEditionCode(this._sharedData.edition)}`;
1014
+ }
1015
+
1016
+ id() {
1017
+ return "SCT"+this.version();
1018
+ }
1019
+ }
1020
+
1021
+
1022
+ function getEditionName(edition) {
1023
+ const editionMap = {
1024
+ '900000000000207008': 'International Edition',
1025
+ '449081005': 'International Spanish Edition',
1026
+ '11000221109': 'Argentinian Edition',
1027
+ '32506021000036107': 'Australian Edition (with drug extension)',
1028
+ '11000234105': 'Austrian Edition',
1029
+ '11000172109': 'Belgian Edition',
1030
+ '20621000087109': 'Canadian English Edition',
1031
+ '20611000087101': 'Canadian Canadian French Edition',
1032
+ '554471000005108': 'Danish Edition',
1033
+ '11000279109': 'Czech Edition',
1034
+ '11000181102': 'Estonian Edition',
1035
+ '11000229106': 'Finnish Edition',
1036
+ '11000274103': 'German Edition',
1037
+ '1121000189102': 'Indian Edition',
1038
+ '827022005': 'IPS Terminology',
1039
+ '11000220105': 'Irish Edition',
1040
+ '11000146104': 'Netherlands Edition',
1041
+ '21000210109': 'New Zealand Edition',
1042
+ '51000202101': 'Norwegian Edition',
1043
+ '11000267109': 'Republic of Korea Edition (South Korea)',
1044
+ '900000001000122104': 'Spanish National Edition',
1045
+ '45991000052106': 'Swedish Edition',
1046
+ '2011000195101': 'Swiss Edition',
1047
+ '83821000000107': 'UK Edition',
1048
+ '999000021000000109': 'UK Clinical Edition',
1049
+ '5631000179106': 'Uruguay Edition',
1050
+ '731000124108': 'US Edition',
1051
+ '21000325107': 'Chilean Edition',
1052
+ '5991000124107': 'US Edition (with ICD-10-CM maps)'
1053
+ };
1054
+
1055
+ return editionMap[edition] || 'Unknown Edition';
1056
+ }
1057
+
1058
+ function getEditionCode(edition) {
1059
+ const editionMap = {
1060
+ '900000000000207008': 'Intl',
1061
+ '449081005': 'es',
1062
+ '11000221109': 'AR-es',
1063
+ '32506021000036107': 'AU+',
1064
+ '11000234105': 'AT',
1065
+ '11000172109': 'BE',
1066
+ '20621000087109': 'CA-en',
1067
+ '20611000087101': 'CA-fr',
1068
+ '554471000005108': 'DK',
1069
+ '11000279109': 'CZ',
1070
+ '11000181102': 'ES',
1071
+ '11000229106': 'FI',
1072
+ '11000274103': 'DE',
1073
+ '1121000189102': 'IN',
1074
+ '827022005': 'IPS',
1075
+ '11000220105': 'IE',
1076
+ '11000146104': 'NL',
1077
+ '21000210109': 'NZ',
1078
+ '51000202101': 'NO',
1079
+ '11000267109': 'KR',
1080
+ '900000001000122104': 'ES-es',
1081
+ '45991000052106': 'SW',
1082
+ '2011000195101': 'CH',
1083
+ '83821000000107': 'UK',
1084
+ '999000021000000109': 'UK-Clinical',
1085
+ '5631000179106': 'UR',
1086
+ '731000124108': 'US',
1087
+ '21000325107': 'CL',
1088
+ '5991000124107': 'US+)'
1089
+ };
1090
+
1091
+ return editionMap[edition] || 'Unknown Edition';
1092
+ }
1093
+
1094
+
1095
+ module.exports = {
1096
+ SnomedProvider,
1097
+ SnomedServicesFactory,
1098
+ SnomedExpressionContext,
1099
+ SnomedServices,
1100
+ SnomedFilterContext,
1101
+ SnomedProviderContextKind
1102
+ };