fhirsmith 0.12.0 → 0.13.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 (56) hide show
  1. package/CHANGELOG.md +305 -0
  2. package/README.md +1 -1
  3. package/config-template.json +13 -0
  4. package/library/languages.js +191 -34
  5. package/library/path-safety.js +51 -0
  6. package/library/request-token.js +56 -0
  7. package/package.json +2 -2
  8. package/packages/packages.js +17 -118
  9. package/publisher/publisher.js +60 -30
  10. package/publisher/validation.js +15 -3
  11. package/server.js +12 -3
  12. package/translations/Messages.properties +1 -0
  13. package/tx/README.md +21 -0
  14. package/tx/cs/cs-api.js +30 -1
  15. package/tx/cs/cs-cs.js +1 -1
  16. package/tx/cs/cs-icd11.js +805 -0
  17. package/tx/cs/cs-lang.js +331 -85
  18. package/tx/cs/cs-loinc.js +45 -4
  19. package/tx/cs/cs-mimetypes.js +492 -21
  20. package/tx/cs/cs-snomed.js +38 -4
  21. package/tx/cs/cs-ucum.js +33 -3
  22. package/tx/cs/icd11-expressions.js +243 -0
  23. package/tx/importers/export-icd11-codesystem.js +823 -0
  24. package/tx/importers/icd11-schema.md +285 -0
  25. package/tx/importers/import-icd11.js +861 -0
  26. package/tx/importers/import-loinc.module.js +14 -7
  27. package/tx/importers/import-sct.module.js +10 -1
  28. package/tx/library/codesystem.js +21 -27
  29. package/tx/library/nesting-limit.js +79 -0
  30. package/tx/library/operation-outcome.js +97 -3
  31. package/tx/library/valueset.js +16 -20
  32. package/tx/library.js +23 -1
  33. package/tx/ocl/cache/cache-utils.cjs +5 -3
  34. package/tx/ocl/cs-ocl.cjs +73 -17
  35. package/tx/ocl/jobs/background-queue.cjs +6 -3
  36. package/tx/ocl/mappers/concept-mapper.cjs +9 -1
  37. package/tx/ocl/shared/patches.cjs +48 -1
  38. package/tx/ocl/vs-ocl.cjs +15 -13
  39. package/tx/sct/expressions.js +194 -17
  40. package/tx/tx.fhir.org.yml +2 -1
  41. package/tx/tx.js +15 -42
  42. package/tx/workers/batch-validate.js +6 -16
  43. package/tx/workers/batch.js +16 -28
  44. package/tx/workers/cache-control.js +6 -12
  45. package/tx/workers/closure.js +3 -8
  46. package/tx/workers/compare.js +6 -34
  47. package/tx/workers/expand.js +36 -45
  48. package/tx/workers/lookup.js +21 -39
  49. package/tx/workers/read.js +6 -40
  50. package/tx/workers/search.js +2 -8
  51. package/tx/workers/subsumes.js +58 -41
  52. package/tx/workers/translate.js +11 -17
  53. package/tx/workers/validate.js +76 -77
  54. package/tx/workers/worker.js +70 -1
  55. package/tx/xml/xml-base.js +243 -76
  56. package/tx/xversion/xv-valueset.js +39 -1
@@ -10,7 +10,7 @@
10
10
  const { TerminologyWorker } = require('./worker');
11
11
  const { TxParameters } = require('../params');
12
12
  const { Parameters } = require('../library/parameters');
13
- const { Issue, OperationOutcome } = require('../library/operation-outcome');
13
+ const { Issue, OperationOutcome, buildOperationOutcome, outcomeFromError } = require('../library/operation-outcome');
14
14
  const {ConceptMap} = require("../library/conceptmap");
15
15
  const {Extensions} = require("../library/extensions");
16
16
  const {VersionUtilities} = require("../../library/version-utilities");
@@ -62,8 +62,7 @@ class TranslateWorker extends TerminologyWorker {
62
62
  oo.addIssue(error);
63
63
  return res.status(error.statusCode || 500).json(oo.jsonObj);
64
64
  } else {
65
- return res.status(error.statusCode || 500).json(this.operationOutcome(
66
- 'error', error.issueCode || 'exception', error.message));
65
+ return res.status(error.statusCode || 500).json(outcomeFromError(error));
67
66
  }
68
67
  }
69
68
  }
@@ -85,8 +84,7 @@ class TranslateWorker extends TerminologyWorker {
85
84
  oo.addIssue(error);
86
85
  return res.status(error.statusCode || 500).json(oo.jsonObj);
87
86
  } else {
88
- return res.status(error.statusCode || 500).json(this.operationOutcome(
89
- 'error', error.issueCode || 'exception', error.message));
87
+ return res.status(error.statusCode || 500).json(outcomeFromError(error));
90
88
  }
91
89
  }
92
90
  }
@@ -1013,21 +1011,17 @@ class TranslateWorker extends TerminologyWorker {
1013
1011
  }
1014
1012
  }
1015
1013
  /**
1016
- * Build an OperationOutcome
1014
+ * Build an OperationOutcome. Delegates to the shared builder so that every outcome this
1015
+ * server emits has details.text and a tx-issue-type coding: diagnostics is stripped by
1016
+ * the test harness, so nothing a caller needs may live there.
1017
1017
  * @param {string} severity - error, warning, information
1018
- * @param {string} code - Issue code
1019
- * @param {string} message - Diagnostic message
1018
+ * @param {string} code - FHIR issue type
1019
+ * @param {string} message - the human readable account of the problem
1020
+ * @param {string} [txIssueType] - tx-issue-type; defaulted from code when not given
1020
1021
  * @returns {Object} OperationOutcome resource
1021
1022
  */
1022
- operationOutcome(severity, code, message) {
1023
- return {
1024
- resourceType: 'OperationOutcome',
1025
- issue: [{
1026
- severity,
1027
- code,
1028
- diagnostics: message
1029
- }]
1030
- };
1023
+ operationOutcome(severity, code, message, txIssueType = null) {
1024
+ return buildOperationOutcome(severity, code, message, txIssueType);
1031
1025
  }
1032
1026
 
1033
1027
  /**
@@ -11,12 +11,12 @@
11
11
  // POST /ValueSet/{id}/$validate-code
12
12
  //
13
13
 
14
- const { TerminologyWorker } = require('./worker');
14
+ const { TerminologyWorker, Unknown_Code_in_VersionSCT, SCTVersion } = require('./worker');
15
15
  const {Languages, Language} = require("../../library/languages");
16
16
  const {Extensions} = require("../library/extensions");
17
17
  const {validateParameter, isAbsoluteUrl, validateOptionalParameter, getValuePrimitive} = require("../../library/utilities");
18
18
  const {TxParameters} = require("../params");
19
- const {OperationOutcome, Issue} = require("../library/operation-outcome");
19
+ const { OperationOutcome, Issue, buildOperationOutcome, outcomeFromError } = require('../library/operation-outcome');
20
20
  const {Parameters} = require("../library/parameters");
21
21
  const {Designations, DisplayCheckingStyle, DisplayDifference, SearchFilterText} = require("../library/designations");
22
22
  const ValueSet = require("../library/valueset");
@@ -953,7 +953,7 @@ class ValueSetChecker {
953
953
  let msg = this.worker.i18n.translate('INACTIVE_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, coding.code]);
954
954
  messages.push(msg);
955
955
  op.addIssue(new Issue('warning', 'business-rule', path, 'INACTIVE_CONCEPT_FOUND', msg, 'code-comment'));
956
- } else if (vstatus.value.toLowerCase() === 'deprecated') {
956
+ } else if (vstatus.value && vstatus.value.toLowerCase() === 'deprecated') {
957
957
  result.addParamCode('status', vstatus.value);
958
958
  let msg = this.worker.i18n.translate('DEPRECATED_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, coding.code]);
959
959
  messages.push(msg);
@@ -1051,6 +1051,7 @@ class ValueSetChecker {
1051
1051
  this.checkCanonicalStatus(issuePath, op, this.valueSet.jsonObj, this.valueSet.jsonObj);
1052
1052
  let list = new Designations(this.worker.languages);
1053
1053
  let ok = false;
1054
+ let matchedCodings = new Set();
1054
1055
  let codelist = '';
1055
1056
  mt = [];
1056
1057
  let i = 0;
@@ -1082,6 +1083,9 @@ class ValueSetChecker {
1082
1083
  if (v === false) {
1083
1084
  cause.value = 'code-invalid';
1084
1085
  }
1086
+ if (v === true) {
1087
+ matchedCodings.add(i);
1088
+ }
1085
1089
  let ws;
1086
1090
  if (impliedSystem.value) {
1087
1091
  ws = impliedSystem.value;
@@ -1249,6 +1253,17 @@ class ValueSetChecker {
1249
1253
  c.version = prov.version();
1250
1254
  }
1251
1255
  await this.worker.listDisplaysFromCodeSystem(list, prov, ctxt.context);
1256
+ // the code resolved in the code system, so its status is known whether or not it
1257
+ // turns out to be in the value set. check() only picks the status up on the paths
1258
+ // where the code was found in the value set, so pick it up here for the rest
1259
+ if (!this.params.membershipOnly && !inactive.value && await prov.isInactive(ctxt.context)) {
1260
+ inactive.value = true;
1261
+ inactive.path = path;
1262
+ const st = await prov.getStatus(ctxt.context);
1263
+ if (st) {
1264
+ vstatus.value = st;
1265
+ }
1266
+ }
1252
1267
  let pd = list.preferredDisplay(this.params.workingLanguages());
1253
1268
  if (pd) {
1254
1269
  pdisp = pd;
@@ -1290,6 +1305,36 @@ class ValueSetChecker {
1290
1305
  }
1291
1306
  i++;
1292
1307
  }
1308
+
1309
+ // A required binding on a CodeableConcept is satisfied when ANY coding is in the value set, so
1310
+ // a coding whose code system could not be resolved must not veto a membership that another
1311
+ // coding has confirmed. It is still reported, but as a warning, and with a message that does
1312
+ // not read as though nothing could be validated (hapifhir/org.hl7.fhir.core#2272).
1313
+ if (issuePath === 'CodeableConcept' && matchedCodings.size > 0) {
1314
+ const notChecked = ['UNKNOWN_CODESYSTEM', 'UNKNOWN_CODESYSTEM_VERSION', 'UNKNOWN_CODESYSTEM_VERSION_NONE'];
1315
+ let j = 0;
1316
+ for (let c of code.coding || []) {
1317
+ if (!matchedCodings.has(j)) {
1318
+ let sysPath = issuePath + '.coding[' + j + '].system';
1319
+ for (let iss of op.jsonObj.issue || []) {
1320
+ let mid = (iss.extension || []).find(e => e.url === 'http://hl7.org/fhir/StructureDefinition/operationoutcome-message-id');
1321
+ if (iss.severity === 'error' && mid && notChecked.includes(mid.valueString) && (iss.expression || []).includes(sysPath)) {
1322
+ let was = iss.details.text;
1323
+ let now = this.worker.i18n.translate('UNKNOWN_CODESYSTEM_CODING_NOT_CHECKED', this.params.HTTPLanguages,
1324
+ [c.version ? c.system + '|' + c.version : c.system]);
1325
+ iss.severity = 'warning';
1326
+ iss.details.text = now;
1327
+ mid.valueString = 'UNKNOWN_CODESYSTEM_CODING_NOT_CHECKED';
1328
+ // the summary message is built from mt, so it has to say the same thing
1329
+ mt = mt.filter(t => t !== was);
1330
+ msg(now);
1331
+ }
1332
+ }
1333
+ }
1334
+ j++;
1335
+ }
1336
+ }
1337
+
1293
1338
  // for an internally defined value set (CodeSystem validation), the code-system-level
1294
1339
  // message is preferred - but if nothing produced an error, this is the only
1295
1340
  // explanation there will be, so it can't be suppressed
@@ -1323,7 +1368,10 @@ class ValueSetChecker {
1323
1368
  }
1324
1369
  }
1325
1370
 
1326
- result.addParamBool('result', ok === true && !op.hasErrors());
1371
+ // the answer, which is not the same as ok: a coding can be in the value set and still carry an
1372
+ // error of its own (an unknown version, say), and then the CodeableConcept is not valid
1373
+ let valid = ok === true && !op.hasErrors();
1374
+ result.addParamBool('result', valid);
1327
1375
  if (psys) {
1328
1376
  result.addParamUri('system', psys);
1329
1377
  } else if (ok === true && impliedSystem.value) {
@@ -1335,9 +1383,10 @@ class ValueSetChecker {
1335
1383
  for (let us of unknownSystems) {
1336
1384
  if (ok === false) {
1337
1385
  result.addParamCanonical('x-unknown-system', us);
1338
- } else {
1386
+ } else if (!valid) {
1339
1387
  result.addParamCanonical('x-caused-by-unknown-system', us);
1340
1388
  }
1389
+ // if the CodeableConcept is valid, the unknown system caused nothing: neither parameter applies
1341
1390
  }
1342
1391
  if (normalForm.value) {
1343
1392
  result.addParamCode('normalized-code', normalForm.value);
@@ -1535,7 +1584,7 @@ class ValueSetChecker {
1535
1584
  let msg = this.worker.i18n.translate('INACTIVE_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, code]);
1536
1585
  messages.push(msg);
1537
1586
  op.addIssue(new Issue('warning', 'business-rule', 'code', 'INACTIVE_CONCEPT_FOUND', msg, 'code-comment'));
1538
- } else if (vstatus.value.toLowerCase() === 'deprecated') {
1587
+ } else if (vstatus.value && vstatus.value.toLowerCase() === 'deprecated') {
1539
1588
  result.addParamCode('status', vstatus.value);
1540
1589
  let msg = this.worker.i18n.translate('DEPRECATED_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, code]);
1541
1590
  messages.push(msg);
@@ -1569,7 +1618,7 @@ class ValueSetChecker {
1569
1618
  let loc = await cs.locate(code);
1570
1619
  result = false;
1571
1620
  if (loc.context == null) {
1572
- this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" not found in ' + this.worker.renderer.displayCoded(cs)+": "+loc.mesage, this.indentCount);
1621
+ this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" not found in ' + this.worker.renderer.displayCoded(cs)+": "+loc.message, this.indentCount);
1573
1622
  if (!this.params.membershipOnly && role !== 'not in') {
1574
1623
  if (cs.contentMode() !== 'complete') {
1575
1624
  op.addIssue(new Issue('warning', 'code-invalid', addToPath(path, 'code'), 'UNKNOWN_CODE_IN_FRAGMENT', this.worker.i18n.translate('UNKNOWN_CODE_IN_FRAGMENT', this.params.HTTPLanguages, [code, cs.system(), cs.version()]), 'invalid-code'));
@@ -1745,6 +1794,19 @@ class ValueSetChecker {
1745
1794
  if (!vcc.coding) { vcc.coding = []}
1746
1795
  vcc.coding.push( { system : cs.system(), version: cs.version(), code: await cs.code(loc), display: displays.preferredDisplay(this.params.workingLanguages())});
1747
1796
  }
1797
+ if (role !== 'not in' && !inactive.value) {
1798
+ if (await cs.isInactive(loc)) {
1799
+ inactive.value = true;
1800
+ inactive.path = path;
1801
+ // only replace a status we already have with a real one - a filter context
1802
+ // doesn't always carry the status (SNOMED, LOINC), and the assembly reads
1803
+ // vstatus for the message wording as well as for the status parameter
1804
+ const st = await cs.getStatus(loc);
1805
+ if (st) {
1806
+ vstatus.value = st;
1807
+ }
1808
+ }
1809
+ }
1748
1810
  result = true;
1749
1811
  return result;
1750
1812
  }
@@ -1875,56 +1937,6 @@ function addToPath(path, name) {
1875
1937
  }
1876
1938
 
1877
1939
 
1878
- function Unknown_Code_in_VersionSCT(url, version) {
1879
- if (url === 'http://snomed.info/sct') {
1880
- return 'Unknown_Code_in_Version_SCT';
1881
- } else if (version) {
1882
- return 'Unknown_Code_in_Version';
1883
- } else {
1884
- return 'Unknown_Code_in';
1885
- }
1886
- }
1887
-
1888
- function SCTVersion(url, ver) {
1889
- if (url !== 'http://snomed.info/sct' || !ver) {
1890
- return '';
1891
- } else {
1892
- let result = 'unknown';
1893
- let s = ver.split('/');
1894
- if (s.length >= 5) {
1895
- if (s[4] === '900000000000207008') result = 'International Edition';
1896
- else if (s[4] === '449081005') result = 'International Spanish Edition';
1897
- else if (s[4] === '11000221109') result = 'Argentinian Edition';
1898
- else if (s[4] === '32506021000036107') result = 'Australian Edition (with drug extension)';
1899
- else if (s[4] === '11000234105') result = 'Austrian Edition';
1900
- else if (s[4] === '11000172109') result = 'Belgian Edition';
1901
- else if (s[4] === '20621000087109') result = 'Canadian English Edition';
1902
- else if (s[4] === '20611000087101') result = 'Canadian Canadian French Edition';
1903
- else if (s[4] === '11000279109') result = 'Czech Edition';
1904
- else if (s[4] === '554471000005108') result = 'Danish Edition';
1905
- else if (s[4] === '11000181102') result = 'Estonian Edition';
1906
- else if (s[4] === '11000229106') result = 'Finnish Edition';
1907
- else if (s[4] === '11000274103') result = 'German Edition';
1908
- else if (s[4] === '1121000189102') result = 'Indian Edition';
1909
- else if (s[4] === '827022005') result = 'IPS Terminology';
1910
- else if (s[4] === '11000220105') result = 'Irish Edition';
1911
- else if (s[4] === '11000146104') result = 'Netherlands Edition';
1912
- else if (s[4] === '21000210109') result = 'New Zealand Edition';
1913
- else if (s[4] === '51000202101') result = 'Norwegian Edition';
1914
- else if (s[4] === '11000267109') result = 'Republic of Korea Edition (South Korea)';
1915
- else if (s[4] === '900000001000122104') result = 'Spanish National Edition';
1916
- else if (s[4] === '45991000052106') result = 'Swedish Edition';
1917
- else if (s[4] === '2011000195101') result = 'Swiss Edition';
1918
- else if (s[4] === '83821000000107') result = 'UK Edition';
1919
- else if (s[4] === '999000021000000109') result = 'UK Clinical Edition';
1920
- else if (s[4] === '5631000179106') result = 'Uruguay Edition';
1921
- else if (s[4] === '21000325107') result = 'Chilean Edition';
1922
- else if (s[4] === '731000124108') result = 'US Edition';
1923
- else if (s[4] === '5991000124107') result = 'US Edition (with ICD-10-CM maps)';
1924
- }
1925
- return result;
1926
- }
1927
- }
1928
1940
 
1929
1941
 
1930
1942
  function toText(st, sep) {
@@ -1990,8 +2002,7 @@ class ValidateWorker extends TerminologyWorker {
1990
2002
  // this is actually handled in the inner method
1991
2003
  }
1992
2004
  } else {
1993
- return res.status(error.statusCode || 500).json(this.operationOutcome(
1994
- 'error', error.issueCode || 'exception', error.message));
2005
+ return res.status(error.statusCode || 500).json(outcomeFromError(error));
1995
2006
  }
1996
2007
 
1997
2008
  }
@@ -2099,8 +2110,7 @@ class ValidateWorker extends TerminologyWorker {
2099
2110
  } catch (error) {
2100
2111
  this.log.error(error);
2101
2112
  debugLog(error);
2102
- return res.status(error.statusCode || 500).json(this.operationOutcome(
2103
- 'error', error.issueCode || 'exception', error.message));
2113
+ return res.status(error.statusCode || 500).json(outcomeFromError(error));
2104
2114
  }
2105
2115
  }
2106
2116
 
@@ -2125,8 +2135,7 @@ class ValidateWorker extends TerminologyWorker {
2125
2135
  op.addIssue(error);
2126
2136
  return res.status(error.statusCode || 500).json(op.jsonObj);
2127
2137
  } else {
2128
- return res.status(error.statusCode || 500).json(this.operationOutcome(
2129
- 'error', error.issueCode || 'exception', error.message));
2138
+ return res.status(error.statusCode || 500).json(outcomeFromError(error));
2130
2139
  }
2131
2140
  }
2132
2141
  }
@@ -2200,8 +2209,7 @@ class ValidateWorker extends TerminologyWorker {
2200
2209
  } catch (error) {
2201
2210
  this.log.error(error);
2202
2211
  debugLog(error);
2203
- return res.status(error.statusCode || 500).json(this.operationOutcome(
2204
- 'error', error.issueCode || 'exception', error.message));
2212
+ return res.status(error.statusCode || 500).json(outcomeFromError(error));
2205
2213
  }
2206
2214
  }
2207
2215
 
@@ -2541,18 +2549,9 @@ class ValidateWorker extends TerminologyWorker {
2541
2549
  /**
2542
2550
  * Build an OperationOutcome
2543
2551
  */
2544
- operationOutcome(severity, code, message) {
2545
- return {
2546
- resourceType: 'OperationOutcome',
2547
- issue: [{
2548
- severity,
2549
- code,
2550
- details: {
2551
- text: message
2552
- },
2553
- diagnostics: message
2554
- }]
2555
- };
2552
+ operationOutcome(severity, code, message, txIssueType = null) {
2553
+ // the shared builder, so that every outcome has details.text and a tx-issue-type coding
2554
+ return buildOperationOutcome(severity, code, message, txIssueType);
2556
2555
  }
2557
2556
 
2558
2557
 
@@ -1062,8 +1062,77 @@ class TerminologyWorker {
1062
1062
  }
1063
1063
  }
1064
1064
 
1065
+
1066
+ /**
1067
+ * Choose the message id to use when reporting an unknown code, based on the
1068
+ * code system and whether a version is known. SNOMED CT gets its own message
1069
+ * because the edition is named in the message (see SCTVersion below)
1070
+ * @param {string} url - code system url
1071
+ * @param {string} version - code system version (may be null)
1072
+ * @returns {string} message id
1073
+ */
1074
+ function Unknown_Code_in_VersionSCT(url, version) {
1075
+ if (url === 'http://snomed.info/sct') {
1076
+ return 'Unknown_Code_in_Version_SCT';
1077
+ } else if (version) {
1078
+ return 'Unknown_Code_in_Version';
1079
+ } else {
1080
+ return 'Unknown_Code_in';
1081
+ }
1082
+ }
1083
+
1084
+ /**
1085
+ * Human readable name for the SNOMED CT edition in a SNOMED CT version URI.
1086
+ * Returns '' for anything that isn't a versioned SNOMED CT reference
1087
+ * @param {string} url - code system url
1088
+ * @param {string} ver - code system version
1089
+ * @returns {string} edition name, or ''
1090
+ */
1091
+ function SCTVersion(url, ver) {
1092
+ if (url !== 'http://snomed.info/sct' || !ver) {
1093
+ return '';
1094
+ } else {
1095
+ let result = 'unknown';
1096
+ let s = ver.split('/');
1097
+ if (s.length >= 5) {
1098
+ if (s[4] === '900000000000207008') result = 'International Edition';
1099
+ else if (s[4] === '449081005') result = 'International Spanish Edition';
1100
+ else if (s[4] === '11000221109') result = 'Argentinian Edition';
1101
+ else if (s[4] === '32506021000036107') result = 'Australian Edition (with drug extension)';
1102
+ else if (s[4] === '11000234105') result = 'Austrian Edition';
1103
+ else if (s[4] === '11000172109') result = 'Belgian Edition';
1104
+ else if (s[4] === '20621000087109') result = 'Canadian English Edition';
1105
+ else if (s[4] === '20611000087101') result = 'Canadian Canadian French Edition';
1106
+ else if (s[4] === '11000279109') result = 'Czech Edition';
1107
+ else if (s[4] === '554471000005108') result = 'Danish Edition';
1108
+ else if (s[4] === '11000181102') result = 'Estonian Edition';
1109
+ else if (s[4] === '11000229106') result = 'Finnish Edition';
1110
+ else if (s[4] === '11000274103') result = 'German Edition';
1111
+ else if (s[4] === '1121000189102') result = 'Indian Edition';
1112
+ else if (s[4] === '827022005') result = 'IPS Terminology';
1113
+ else if (s[4] === '11000220105') result = 'Irish Edition';
1114
+ else if (s[4] === '11000146104') result = 'Netherlands Edition';
1115
+ else if (s[4] === '21000210109') result = 'New Zealand Edition';
1116
+ else if (s[4] === '51000202101') result = 'Norwegian Edition';
1117
+ else if (s[4] === '11000267109') result = 'Republic of Korea Edition (South Korea)';
1118
+ else if (s[4] === '900000001000122104') result = 'Spanish National Edition';
1119
+ else if (s[4] === '45991000052106') result = 'Swedish Edition';
1120
+ else if (s[4] === '2011000195101') result = 'Swiss Edition';
1121
+ else if (s[4] === '83821000000107') result = 'UK Edition';
1122
+ else if (s[4] === '999000021000000109') result = 'UK Clinical Edition';
1123
+ else if (s[4] === '5631000179106') result = 'Uruguay Edition';
1124
+ else if (s[4] === '21000325107') result = 'Chilean Edition';
1125
+ else if (s[4] === '731000124108') result = 'US Edition';
1126
+ else if (s[4] === '5991000124107') result = 'US Edition (with ICD-10-CM maps)';
1127
+ }
1128
+ return result;
1129
+ }
1130
+ }
1131
+
1065
1132
  module.exports = {
1066
1133
  TerminologyWorker,
1067
1134
  TerminologySetupError,
1068
- CACHE_ID_HEADER
1135
+ CACHE_ID_HEADER,
1136
+ Unknown_Code_in_VersionSCT,
1137
+ SCTVersion
1069
1138
  };