fhirsmith 0.4.2 → 0.5.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 (92) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/library/cron-utilities.js +136 -0
  4. package/library/html-server.js +13 -29
  5. package/library/html.js +3 -8
  6. package/library/languages.js +160 -37
  7. package/library/package-manager.js +48 -1
  8. package/library/utilities.js +100 -19
  9. package/package.json +2 -2
  10. package/packages/package-crawler.js +6 -1
  11. package/packages/packages.js +38 -54
  12. package/publisher/publisher.js +19 -27
  13. package/registry/api.js +11 -10
  14. package/registry/crawler.js +31 -29
  15. package/registry/model.js +5 -26
  16. package/registry/registry.js +32 -41
  17. package/server.js +53 -5
  18. package/shl/shl.js +0 -18
  19. package/static/assets/js/statuspage.js +1 -9
  20. package/stats.js +39 -1
  21. package/token/token.js +14 -9
  22. package/translations/Messages.properties +2 -1
  23. package/tx/README.md +17 -6
  24. package/tx/cs/cs-api.js +19 -1
  25. package/tx/cs/cs-base.js +77 -0
  26. package/tx/cs/cs-country.js +46 -0
  27. package/tx/cs/cs-cpt.js +9 -5
  28. package/tx/cs/cs-cs.js +27 -13
  29. package/tx/cs/cs-lang.js +60 -22
  30. package/tx/cs/cs-loinc.js +69 -98
  31. package/tx/cs/cs-mimetypes.js +4 -0
  32. package/tx/cs/cs-ndc.js +6 -0
  33. package/tx/cs/cs-omop.js +16 -15
  34. package/tx/cs/cs-rxnorm.js +23 -1
  35. package/tx/cs/cs-snomed.js +283 -40
  36. package/tx/cs/cs-ucum.js +90 -70
  37. package/tx/importers/import-sct.module.js +371 -35
  38. package/tx/importers/readme.md +117 -7
  39. package/tx/library/bundle.js +5 -0
  40. package/tx/library/capabilitystatement.js +3 -142
  41. package/tx/library/codesystem.js +19 -173
  42. package/tx/library/conceptmap.js +4 -218
  43. package/tx/library/designations.js +14 -1
  44. package/tx/library/extensions.js +7 -0
  45. package/tx/library/namingsystem.js +3 -89
  46. package/tx/library/operation-outcome.js +8 -3
  47. package/tx/library/parameters.js +3 -2
  48. package/tx/library/renderer.js +10 -6
  49. package/tx/library/terminologycapabilities.js +3 -243
  50. package/tx/library/valueset.js +3 -235
  51. package/tx/library.js +100 -13
  52. package/tx/operation-context.js +23 -4
  53. package/tx/params.js +35 -38
  54. package/tx/provider.js +6 -5
  55. package/tx/sct/expressions.js +12 -3
  56. package/tx/tx-html.js +80 -89
  57. package/tx/tx.fhir.org.yml +6 -5
  58. package/tx/tx.js +163 -13
  59. package/tx/vs/vs-database.js +56 -39
  60. package/tx/vs/vs-package.js +21 -2
  61. package/tx/vs/vs-vsac.js +175 -39
  62. package/tx/workers/batch-validate.js +2 -0
  63. package/tx/workers/batch.js +2 -0
  64. package/tx/workers/expand.js +132 -112
  65. package/tx/workers/lookup.js +33 -14
  66. package/tx/workers/metadata.js +2 -2
  67. package/tx/workers/read.js +3 -2
  68. package/tx/workers/related.js +574 -0
  69. package/tx/workers/search.js +46 -9
  70. package/tx/workers/subsumes.js +13 -3
  71. package/tx/workers/translate.js +7 -3
  72. package/tx/workers/validate.js +258 -285
  73. package/tx/workers/worker.js +43 -39
  74. package/tx/xml/bundle-xml.js +237 -0
  75. package/tx/xml/xml-base.js +215 -64
  76. package/tx/xversion/xv-bundle.js +71 -0
  77. package/tx/xversion/xv-capabiliityStatement.js +137 -0
  78. package/tx/xversion/xv-codesystem.js +169 -0
  79. package/tx/xversion/xv-conceptmap.js +224 -0
  80. package/tx/xversion/xv-namingsystem.js +88 -0
  81. package/tx/xversion/xv-operationoutcome.js +27 -0
  82. package/tx/xversion/xv-parameters.js +87 -0
  83. package/tx/xversion/xv-resource.js +45 -0
  84. package/tx/xversion/xv-terminologyCapabilities.js +214 -0
  85. package/tx/xversion/xv-valueset.js +234 -0
  86. package/utilities/dev-proxy-server.js +126 -0
  87. package/utilities/explode-results.js +58 -0
  88. package/utilities/split-by-system.js +198 -0
  89. package/utilities/vsac-cs-fetcher.js +0 -0
  90. package/{windows-install.js → utilities/windows-install.js} +2 -0
  91. package/vcl/vcl.js +0 -18
  92. package/xig/xig.js +108 -99
package/tx/cs/cs-ucum.js CHANGED
@@ -3,12 +3,13 @@
3
3
  * Implementation of CodeSystemProvider for UCUM (Unified Code for Units of Measure)
4
4
  */
5
5
 
6
- const { CodeSystemProvider, FilterExecutionContext, CodeSystemFactoryProvider} = require('./cs-api');
7
- const { CodeSystem } = require("../library/codesystem");
6
+ const { FilterExecutionContext, CodeSystemFactoryProvider} = require('./cs-api');
8
7
  const ValueSet = require("../library/valueset");
9
8
  const assert = require('assert');
10
9
  const {UcumService} = require("../library/ucum-service");
11
- const {validateArrayParameter} = require("../../library/utilities");
10
+ const {validateArrayParameter, validateParameter, validateOptionalParameter} = require("../../library/utilities");
11
+ const {DesignationUse} = require("../library/designations");
12
+ const {BaseCSServices} = require("./cs-base");
12
13
 
13
14
  /**
14
15
  * UCUM provider context for concepts
@@ -21,13 +22,13 @@ class UcumContext {
21
22
  }
22
23
 
23
24
  /**
24
- * Filter context for UCUM canonical unit filters
25
+ * UCUM canonical unit filters
25
26
  */
26
- class UcumFilterContext {
27
+ class UcumFilter {
27
28
  constructor(canonical = '') {
28
29
  this.canonical = canonical;
29
30
  this.cursor = -1; // Used for iteration
30
- this.filters = [];
31
+ this.codes = undefined;
31
32
  }
32
33
  }
33
34
 
@@ -35,29 +36,19 @@ class UcumFilterContext {
35
36
  * UCUM CodeSystem Provider
36
37
  * Provides validation and lookup for UCUM unit expressions
37
38
  */
38
- class UcumCodeSystemProvider extends CodeSystemProvider {
39
+ class UcumCodeSystemProvider extends BaseCSServices {
40
+ ucumService;
41
+ commonUnits;
42
+
39
43
  constructor(opContext, supplements, ucumService, commonUnits = null) {
40
44
  super(opContext, supplements);
41
45
  assert(ucumService != null && ucumService instanceof UcumService, 'ucumService must be a UcumService');
42
- assert(!commonUnits || commonUnits instanceof ValueSet, 'if provided, commonUnits must be a ValueSet');
46
+ validateOptionalParameter(commonUnits, 'commonUnits', Object);
43
47
 
44
48
  this.ucumService = ucumService;
45
- this.commonUnits = commonUnits; // ValueSet for common units
46
- this.commonUnitList = null;
47
-
48
- this._setupCommonUnits();
49
+ this.commonUnits = commonUnits;
49
50
  }
50
51
 
51
- _setupCommonUnits() {
52
- if (this.commonUnits) {
53
- // Extract concept list from common units ValueSet
54
- // This would depend on your ValueSet implementation
55
- // For now, assuming it has a getConcepts() method
56
- // if (typeof this.commonUnits.getConcepts === 'function') {
57
- // this.commonUnitList = this.commonUnits.getConcepts();
58
- // }
59
- }
60
- }
61
52
 
62
53
  // ========== Metadata Methods ==========
63
54
 
@@ -129,8 +120,8 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
129
120
 
130
121
  if (this.opContext.langs.isEnglishOrNothing()) {
131
122
  // Check for common units display first
132
- if (this.commonUnitList) {
133
- for (const concept of this.commonUnitList) {
123
+ if (this.commonUnits) {
124
+ for (const concept of this.commonUnits.units) {
134
125
  if (concept.code === ctxt.code && concept.display) {
135
126
  return concept.display.trim();
136
127
  }
@@ -153,8 +144,8 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
153
144
  return supplementDisplay;
154
145
  }
155
146
 
156
- // Fall back to analysis
157
- return this.ucumService.analyse(ctxt.code);
147
+ // Fall back to code per THO advice
148
+ return ctxt.code;
158
149
  }
159
150
 
160
151
  async definition(code) {
@@ -187,15 +178,16 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
187
178
 
188
179
  // Primary display (analysis)
189
180
  const analysis = this.ucumService.analyse(ctxt.code);
190
- displays.addDesignation(true, 'active', 'en', CodeSystem.makeUseForDisplay(), analysis);
181
+ displays.addDesignation(true, 'active', 'en', DesignationUse.DISPLAY, ctxt.code);
182
+ displays.addDesignation(true, 'active', 'en', DesignationUse.SYNONYM, analysis);
191
183
 
192
184
  // Common unit display if available
193
- if (this.commonUnitList) {
194
- for (const concept of this.commonUnitList) {
185
+ if (this.commonUnits) {
186
+ for (const concept of this.commonUnits.units) {
195
187
  if (concept.code === ctxt.code && concept.display) {
196
188
  const display = concept.display.trim();
197
- if (display !== analysis) {
198
- displays.addDesignation(false, 'active', 'en', CodeSystem.makeUseForDisplay(), display);
189
+ if (display !== ctxt.code) {
190
+ displays.addDesignation(false, 'active', 'en', DesignationUse.SYNONYM, display);
199
191
  }
200
192
  }
201
193
  }
@@ -250,7 +242,7 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
250
242
  assert(value != null && typeof value === 'string', 'value must be a non-null string');
251
243
 
252
244
  // Support canonical unit filters
253
- return (prop === 'canonical' && op === 'equals');
245
+ return (prop === 'canonical' && op === '=');
254
246
  }
255
247
 
256
248
  async searchFilter(filterContext, filter, sort) {
@@ -274,7 +266,6 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
274
266
  }
275
267
 
276
268
  async filter(filterContext, prop, op, value) {
277
-
278
269
  assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
279
270
  assert(prop != null && typeof prop === 'string', 'prop must be a non-null string');
280
271
  assert(op != null && typeof op === 'string', 'op must be a non-null string');
@@ -284,67 +275,66 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
284
275
  throw new Error(`Unsupported filter property: ${prop}`);
285
276
  }
286
277
 
287
- if (op !== 'equals') {
278
+ if (op !== '=') {
288
279
  throw new Error(`Unsupported filter operator for canonical: ${op}`);
289
280
  }
290
281
 
291
- const ucumFilter = new UcumFilterContext(value);
282
+ const ucumFilter = new UcumFilter(value);
292
283
  filterContext.filters.push(ucumFilter);
284
+ if (filterContext.forIterate) {
285
+ if (!this.commonUnits) {
286
+ throw new Error(`Cannot expand a UCUM filter unless the common units value set is available`);
287
+ }
288
+ let set = [];
289
+ for (let concept of this.commonUnits.units) {
290
+ try {
291
+ if (concept.canonical === value) {
292
+ set.push(concept);
293
+ }
294
+ } catch (error) {
295
+ // nothing
296
+ }
297
+ }
298
+ ucumFilter.codes = set;
299
+ }
293
300
  }
294
301
 
295
302
  async executeFilters(filterContext) {
296
-
297
303
  assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
298
304
  return filterContext.filters;
299
305
  }
300
306
 
301
307
  async filterSize(filterContext, set) {
302
-
303
308
  assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
304
- assert(set && set instanceof UcumFilterContext, 'set must be a UcumFilterContext');
309
+ assert(set && set instanceof UcumFilter, 'set must be a UcumFilter');
305
310
 
306
- if (!set.canonical && this.commonUnitList) {
307
- return this.commonUnitList.length;
308
- }
309
- throw new Error('UCUM filter sets cannot be sized as they are based on a grammar');
311
+ return set.codes.length;
310
312
  }
311
313
 
312
314
  async filtersNotClosed(filterContext) {
313
-
314
315
  assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
315
- return true; // Grammar-based system is not closed
316
+ return true; // Grammar-based system is never closed
316
317
  }
317
318
 
318
319
  async filterMore(filterContext, set) {
319
320
 
320
321
  assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
321
- assert(set && set instanceof UcumFilterContext, 'set must be a UcumFilterContext');
322
+ assert(set && set instanceof UcumFilter, 'set must be a UcumFilter');
322
323
 
323
- if (!set.canonical && this.commonUnitList) {
324
- // Iterating common units
325
- set.cursor++;
326
- return set.cursor < this.commonUnitList.length;
327
- }
328
- throw new Error('UCUM filter sets cannot be iterated as they are based on a grammar');
324
+ set.cursor++;
325
+ return set.cursor < set.codes.length;
329
326
  }
330
327
 
331
328
  async filterConcept(filterContext, set) {
332
-
333
329
  assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
334
- assert(set && set instanceof UcumFilterContext, 'set must be a UcumFilterContext');
335
-
336
- if (!set.canonical && this.commonUnitList) {
337
- // Return current common unit
338
- const concept = this.commonUnitList[set.cursor];
339
- return new UcumContext(concept.code);
340
- }
341
- throw new Error('UCUM filter sets cannot be iterated as they are based on a grammar');
330
+ assert(set && set instanceof UcumFilter, 'set must be a UcumFilter');
331
+ return new UcumContext(set.codes[set.cursor].code);
342
332
  }
343
333
 
344
334
  async filterLocate(filterContext, set, code) {
345
335
 
346
336
  assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
347
- assert(set && set instanceof UcumFilterContext, 'set must be a UcumFilterContext');
337
+ assert(set && set instanceof UcumFilter, 'set must be a UcumFilter');
348
338
  assert(typeof code === 'string', 'code must be non-null string');
349
339
 
350
340
  // Validate the code first
@@ -355,15 +345,16 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
355
345
 
356
346
  if (!set.canonical) {
357
347
  // Special enumeration case - check if in common units
358
- if (this.commonUnitList) {
359
- const found = this.commonUnitList.find(concept => concept.code === code);
348
+ if (this.commonUnits) {
349
+ const found = this.commonUnits.units.find(concept => concept.code == code);
360
350
  if (found) {
361
351
  return new UcumContext(code);
362
352
  } else {
363
353
  return `Code ${code} is not in the common units enumeration`;
364
354
  }
355
+ } else {
356
+ return new UcumContext(code); // Valid code
365
357
  }
366
- return new UcumContext(code); // Valid code
367
358
  } else {
368
359
  // Check canonical units
369
360
  try {
@@ -382,7 +373,7 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
382
373
  async filterCheck(filterContext, set, concept) {
383
374
 
384
375
  assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
385
- assert(set && set instanceof UcumFilterContext, 'set must be a UcumFilterContext');
376
+ assert(set && set instanceof UcumFilter, 'set must be a UcumFilter');
386
377
 
387
378
  const ctxt = await this.#ensureContext(concept);
388
379
 
@@ -427,7 +418,7 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
427
418
  validateArrayParameter(params, 'params', Object);
428
419
 
429
420
 
430
- if (props.includes('canonical')) {
421
+ if (this._hasProp(props, 'canonical', true)) {
431
422
  try {
432
423
  const canonical = this.ucumService.getCanonicalUnits(ctxt.code);
433
424
  // Add canonical property to params - implementation depends on your Parameters class
@@ -448,19 +439,48 @@ class UcumCodeSystemProvider extends CodeSystemProvider {
448
439
  isNotClosed() {
449
440
  return true;
450
441
  }
442
+
443
+ makeUseForSynonym() {
444
+ return ;
445
+ }
451
446
  }
452
447
 
453
448
  /**
454
449
  * Factory for creating UCUM CodeSystem providers
455
450
  */
456
451
  class UcumCodeSystemFactory extends CodeSystemFactoryProvider {
457
- constructor(i18n, ucumService, commonUnits = null) {
452
+ constructor(i18n, ucumService, commonUnitVS = null) {
458
453
  super(i18n);
459
454
  assert(ucumService != null && ucumService instanceof UcumService, 'ucumService must be a UcumService');
460
- assert(!commonUnits || commonUnits instanceof ValueSet, 'if provided, commonUnits must be a ValueSet');
455
+ assert(!commonUnitVS || commonUnitVS instanceof ValueSet, 'if provided, commonUnits must be a ValueSet');
461
456
  this.ucumService = ucumService;
462
- this.commonUnits = commonUnits;
463
457
  this.uses = 0;
458
+
459
+ if (commonUnitVS) {
460
+ this.processCommonUnits(commonUnitVS);
461
+ }
462
+ }
463
+
464
+ processCommonUnits(vs) {
465
+ validateParameter(vs, 'vs', ValueSet);
466
+ if (vs) {
467
+ this.commonUnits = { units : [] };
468
+ this.commonUnits.url = vs.url;
469
+ for (let c of vs.jsonObj.compose.include[0].concept) {
470
+ let concept = { code: c.code, display : c.display };
471
+ try {
472
+ let canonical = this.ucumService.getCanonicalUnits(c.code);
473
+ if (canonical) {
474
+ concept.canonical = canonical;
475
+ }
476
+ } catch (err) {
477
+ // nothing
478
+ }
479
+ this.commonUnits.units.push(concept);
480
+ }
481
+ } else {
482
+ this.commonUnits = null;
483
+ }
464
484
  }
465
485
 
466
486
  system() {
@@ -510,5 +530,5 @@ module.exports = {
510
530
  UcumCodeSystemProvider,
511
531
  UcumCodeSystemFactory,
512
532
  UcumContext,
513
- UcumFilterContext
533
+ UcumFilter
514
534
  };