fhirsmith 0.7.6 → 0.8.2

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 (57) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +5 -1
  3. package/library/languages.js +10 -0
  4. package/package.json +1 -1
  5. package/packages/package-crawler.js +2 -2
  6. package/publisher/publisher.js +1 -1
  7. package/registry/registry.js +2 -2
  8. package/root-bare-template.html +1 -2
  9. package/security.md +3 -0
  10. package/server.js +100 -70
  11. package/stats.js +37 -6
  12. package/tx/cs/cs-api.js +8 -4
  13. package/tx/cs/cs-loinc.js +14 -2
  14. package/tx/cs/cs-omop.js +5 -3
  15. package/tx/cs/cs-rxnorm.js +18 -16
  16. package/tx/cs/cs-snomed.js +279 -6
  17. package/tx/data/cpt-fragment.db +0 -0
  18. package/tx/data/cs-de.json +186 -0
  19. package/tx/data/cs-extensions.json +92 -0
  20. package/tx/data/cs-simple.json +130 -0
  21. package/tx/data/cs-supplement.json +78 -0
  22. package/tx/data/lang.dat +49180 -0
  23. package/tx/data/languages.csv +191 -0
  24. package/tx/data/loinc-subset.txt +75 -0
  25. package/tx/data/omop-fragment.db +0 -0
  26. package/tx/data/readme.md +43 -0
  27. package/tx/data/regions.csv +273 -0
  28. package/tx/data/rxnorm-subset.txt +22 -0
  29. package/tx/data/snomed-subset.txt +47 -0
  30. package/tx/data/ucum-essence.xml +2059 -0
  31. package/tx/html/dash-metrics.liquid +147 -0
  32. package/tx/importers/import-rxnorm.module.js +4 -30
  33. package/tx/library/canonical-resource.js +8 -0
  34. package/tx/library/conceptmap.js +29 -1
  35. package/tx/library/designations.js +4 -8
  36. package/tx/library/extensions.js +4 -3
  37. package/tx/library/renderer.js +9 -9
  38. package/tx/ocl/cm-ocl.cjs +185 -65
  39. package/tx/ocl/cs-ocl.cjs +69 -50
  40. package/tx/ocl/jobs/background-queue.cjs +0 -8
  41. package/tx/ocl/mappers/concept-mapper.cjs +13 -3
  42. package/tx/ocl/shared/patches.cjs +1 -0
  43. package/tx/ocl/vs-ocl.cjs +137 -157
  44. package/tx/operation-context.js +3 -3
  45. package/tx/params.js +2 -2
  46. package/tx/provider.js +6 -3
  47. package/tx/sct/structures.js +6 -1
  48. package/tx/tx.fhir.org.yml +1 -1
  49. package/tx/vs/vs-database.js +107 -23
  50. package/tx/vs/vs-vsac.js +66 -19
  51. package/tx/workers/expand.js +10 -10
  52. package/tx/workers/related.js +2 -2
  53. package/tx/workers/search.js +2 -1
  54. package/tx/workers/translate.js +222 -33
  55. package/tx/workers/validate.js +13 -13
  56. package/tx/xversion/xv-parameters.js +54 -1
  57. package/xig/xig.js +171 -9
@@ -331,20 +331,20 @@ class RxNormServices extends CodeSystemProvider {
331
331
  async doesFilter(prop, op, value) {
332
332
 
333
333
 
334
- prop = prop.toUpperCase();
334
+ let propUC = prop.toUpperCase();
335
335
 
336
336
  // TTY filters
337
- if (prop === 'TTY' && ['=', 'in'].includes(op)) {
337
+ if (propUC === 'TTY' && ['=', 'in'].includes(op)) {
338
338
  return true;
339
339
  }
340
340
 
341
341
  // STY filter
342
- if (prop === 'STY' && op === '=') {
342
+ if (propUC === 'STY' && op === '=') {
343
343
  return true;
344
344
  }
345
345
 
346
346
  // SAB filter
347
- if (prop === 'SAB' && op === '=') {
347
+ if (propUC === 'SAB' && op === '=') {
348
348
  return true;
349
349
  }
350
350
 
@@ -370,12 +370,12 @@ class RxNormServices extends CodeSystemProvider {
370
370
 
371
371
 
372
372
  const filter = new RxNormFilterHolder();
373
- prop = prop.toUpperCase();
373
+ let propUC = prop.toUpperCase();
374
374
 
375
375
  let sql = '';
376
376
  let params = {};
377
377
 
378
- if (op === 'in' && prop === 'TTY') {
378
+ if (op === 'in' && propUC === 'TTY') {
379
379
  const values = value.split(',').map(v => v.trim()).filter(v => v);
380
380
  const placeholders = values.map((_, i) => `$tty${i}`).join(',');
381
381
  sql = `AND TTY IN (${placeholders})`;
@@ -383,36 +383,36 @@ class RxNormServices extends CodeSystemProvider {
383
383
  params[`tty${i}`] = this.#sqlWrapString(val);
384
384
  });
385
385
  } else if (op === '=') {
386
- if (prop === 'STY') {
386
+ if (propUC === 'STY') {
387
387
  sql = `AND ${this.getCodeField()} IN (SELECT RXCUI FROM rxnsty WHERE TUI = $sty)`;
388
388
  params.sty = this.#sqlWrapString(value);
389
- } else if (prop === 'SAB') {
389
+ } else if (propUC === 'SAB') {
390
390
  sql = `AND ${this.getCodeField()} IN (SELECT ${this.getCodeField()} FROM rxnconso WHERE SAB = $sab)`;
391
391
  params.sab = this.#sqlWrapString(value);
392
- } else if (prop === 'TTY') {
392
+ } else if (propUC === 'TTY') {
393
393
  sql = `AND TTY = $tty`;
394
394
  params.tty = this.#sqlWrapString(value);
395
395
  } else if (this.rels.includes(prop)) {
396
396
  if (value.startsWith('CUI:')) {
397
397
  const cui = value.substring(4);
398
- sql = `AND (${this.getCodeField()} IN (SELECT ${this.getCodeField()} FROM rxnconso WHERE RXCUI IN (SELECT RXCUI1 FROM rxnrel WHERE REL = $rel AND RXCUI2 = $cui2)))`;
398
+ sql = `AND (${this.getCodeField()} IN (SELECT ${this.getCodeField()} FROM rxnconso WHERE RXCUI IN (SELECT RXCUI2 FROM rxnrel WHERE REL = $rel AND RXCUI1 = $cui2)))`;
399
399
  params.rel = this.#sqlWrapString(prop);
400
400
  params.cui2 = this.#sqlWrapString(cui);
401
401
  } else if (value.startsWith('AUI:')) {
402
402
  const aui = value.substring(4);
403
- sql = `AND (${this.getCodeField()} IN (SELECT ${this.getCodeField()} FROM rxnconso WHERE RXAUI IN (SELECT RXAUI1 FROM rxnrel WHERE REL = $rel AND RXAUI2 = $aui2)))`;
403
+ sql = `AND (${this.getCodeField()} IN (SELECT ${this.getCodeField()} FROM rxnconso WHERE RXAUI IN (SELECT RXAUI2 FROM rxnrel WHERE REL = $rel AND RXAUI1 = $aui2)))`;
404
404
  params.rel = this.#sqlWrapString(prop);
405
405
  params.aui2 = this.#sqlWrapString(aui);
406
406
  }
407
407
  } else if (this.reltypes.includes(prop)) {
408
408
  if (value.startsWith('CUI:')) {
409
409
  const cui = value.substring(4);
410
- sql = `AND (${this.getCodeField()} IN (SELECT ${this.getCodeField()} FROM rxnconso WHERE RXCUI IN (SELECT RXCUI1 FROM rxnrel WHERE RELA = $rela AND RXCUI2 = $cui2)))`;
410
+ sql = `AND (${this.getCodeField()} IN (SELECT ${this.getCodeField()} FROM rxnconso WHERE RXCUI IN (SELECT RXCUI2 FROM rxnrel WHERE RELA = $rela AND RXCUI1 = $cui2)))`;
411
411
  params.rela = this.#sqlWrapString(prop);
412
412
  params.cui2 = this.#sqlWrapString(cui);
413
413
  } else if (value.startsWith('AUI:')) {
414
414
  const aui = value.substring(4);
415
- sql = `AND (${this.getCodeField()} IN (SELECT ${this.getCodeField()} FROM rxnconso WHERE RXAUI IN (SELECT RXAUI1 FROM rxnrel WHERE RELA = $rela AND RXAUI2 = $aui2)))`;
415
+ sql = `AND (${this.getCodeField()} IN (SELECT ${this.getCodeField()} FROM rxnconso WHERE RXAUI IN (SELECT RXAUI2 FROM rxnrel WHERE RELA = $rela AND RXAUI1 = $aui2)))`;
416
416
  params.rela = this.#sqlWrapString(prop);
417
417
  params.aui2 = this.#sqlWrapString(aui);
418
418
  }
@@ -429,7 +429,6 @@ class RxNormServices extends CodeSystemProvider {
429
429
  }
430
430
 
431
431
  async searchFilter(filterContext, filter, sort) {
432
-
433
432
 
434
433
  if (!filter || !filter.stems || filter.stems.length === 0) {
435
434
  throw new Error('Invalid search filter');
@@ -499,8 +498,6 @@ class RxNormServices extends CodeSystemProvider {
499
498
  }
500
499
 
501
500
  async filterSize(filterContext, set) {
502
-
503
-
504
501
  if (!set.executed) {
505
502
  await this.#executeFilter(set);
506
503
  }
@@ -709,6 +706,11 @@ class RxNormTypeServicesFactory extends CodeSystemFactoryProvider {
709
706
  const db = new sqlite3.Database(this.dbPath);
710
707
 
711
708
  try {
709
+ await new Promise((resolve, reject) => {
710
+ db.run(`CREATE INDEX IF NOT EXISTS idx_rxnstems_cui_stem ON RXNSTEMS(CUI, stem)`,
711
+ err => err ? reject(err) : resolve());
712
+ });
713
+
712
714
  this._sharedData = {
713
715
  version: '',
714
716
  rels: [],
@@ -12,6 +12,7 @@ const {
12
12
  const {DesignationUse} = require("../library/designations");
13
13
  const {BaseCSServices} = require("./cs-base");
14
14
  const {formatDateMMDDYYYY} = require("../../library/utilities");
15
+ const {ConceptMap} = require("../library/conceptmap");
15
16
 
16
17
  // Context kinds matching Pascal enum
17
18
  const SnomedProviderContextKind = {
@@ -371,6 +372,29 @@ class SnomedServices {
371
372
  return result;
372
373
  }
373
374
 
375
+ filterInactive(state) {
376
+ const result = new SnomedFilterContext();
377
+ result.inactive = state;
378
+ return result;
379
+ }
380
+
381
+ filterModuleId(id) {
382
+ const result = new SnomedFilterContext();
383
+ let concept = this.concepts.findConcept(id);
384
+ result.moduleId = concept.index;
385
+ return result;
386
+ }
387
+
388
+ filterByProperty(prop, value) {
389
+ const result = new SnomedFilterContext();
390
+ let p = this.concepts.findConcept(prop);
391
+ let v = this.concepts.findConcept(value);
392
+ result.propProp = p.index;
393
+ result.propValue = v.index;
394
+ return result;
395
+
396
+ }
397
+
374
398
  searchFilter(searchText, includeInactive = false, exactMatch = false) {
375
399
  const result = new SnomedFilterContext();
376
400
 
@@ -765,6 +789,12 @@ class SnomedProvider extends BaseCSServices {
765
789
  this._addCodeProperty(params, 'property', 'child', code, null, description);
766
790
  }
767
791
 
792
+ const moduleId = this.sct.concepts.getModuleId(ctxt.getReference());
793
+ if (moduleId) {
794
+ const code = this.sct.getConceptId(moduleId);
795
+ this._addCodeProperty(params, 'property', 'module', code, null, null);
796
+ }
797
+
768
798
  const relationships = this.sct.getConceptRelationships(ctxt.getReference());
769
799
  let set = new Set();
770
800
  for (let relationshipRef of relationships) {
@@ -812,10 +842,25 @@ class SnomedProvider extends BaseCSServices {
812
842
  return this.sct.conceptExists(value);
813
843
  }
814
844
  }
845
+ if (prop === 'inactive') {
846
+ return op === '=' && ['true', 'false'].includes(value);
847
+ }
848
+
849
+ if (prop === 'moduleId') {
850
+ const id = this.sct.stringToIdOrZero(value);
851
+ return id !== 0n && op === '=';
852
+ }
853
+
815
854
  if (prop == 'expressions' && op == '=' && ['true', 'false'].includes(value)) {
816
855
  return true;
817
856
  }
818
857
 
858
+ const cid = this.sct.stringToIdOrZero(prop);
859
+ if (cid != 0) {
860
+ const id = this.sct.stringToIdOrZero(value);
861
+ return id !== 0n && op === '=';
862
+ }
863
+
819
864
  return false;
820
865
  }
821
866
 
@@ -851,7 +896,38 @@ class SnomedProvider extends BaseCSServices {
851
896
  return null;
852
897
  }
853
898
  default:
854
- throw new Error(`Unsupported filter operation: ${op}`);
899
+ throw new Error(`Unsupported filter operation: concept ${op} ${value}`);
900
+ }
901
+ }
902
+
903
+ if (prop === 'inactive') {
904
+ if (value !== 'true' && value !== 'false') {
905
+ throw new Error(`Invalid filter value: ${value}`);
906
+ }
907
+
908
+ switch (op) {
909
+ case '=': {
910
+ filterContext.filters.push(this.sct.filterInactive(value === 'true'));
911
+ return null;
912
+ }
913
+ default:
914
+ throw new Error(`Unsupported filter operation: inactive ${op} ${value}`);
915
+ }
916
+ }
917
+
918
+ if (prop === 'moduleId') {
919
+ const id = this.sct.stringToIdOrZero(value);
920
+ if (id === 0n) {
921
+ throw new Error(`Invalid concept ID: ${value}`);
922
+ }
923
+
924
+ switch (op) {
925
+ case '=': {
926
+ filterContext.filters.push(this.sct.filterModuleId(id));
927
+ return null;
928
+ }
929
+ default:
930
+ throw new Error(`Unsupported filter operation: moduleId ${op} ${value}`);
855
931
  }
856
932
  }
857
933
 
@@ -862,6 +938,24 @@ class SnomedProvider extends BaseCSServices {
862
938
  return null;
863
939
  }
864
940
 
941
+ const cid = this.sct.stringToIdOrZero(prop);
942
+ if (cid != 0) {
943
+
944
+ const id = this.sct.stringToIdOrZero(value);
945
+ if (id === 0n) {
946
+ throw new Error(`Invalid concept ID: ${value}`);
947
+ }
948
+
949
+ switch (op) {
950
+ case '=': {
951
+ filterContext.filters.push(this.sct.filterByProperty(cid, id));
952
+ return null;
953
+ }
954
+ default:
955
+ throw new Error(`Unsupported filter operation: ${prop} ${op} ${value}`);
956
+ }
957
+ }
958
+
865
959
  throw new Error(`Unsupported filter property: ${prop}`);
866
960
  }
867
961
 
@@ -893,7 +987,7 @@ class SnomedProvider extends BaseCSServices {
893
987
 
894
988
  async filterMore(filterContext, set) {
895
989
  set.cursor = set.cursor || 0;
896
-
990
+ this.#ensurePopulated(set);
897
991
  const size = await this.filterSize(filterContext, set);
898
992
  return set.cursor < size;
899
993
  }
@@ -927,12 +1021,27 @@ class SnomedProvider extends BaseCSServices {
927
1021
  }
928
1022
 
929
1023
  const ctxt = conceptResult.context;
930
-
931
-
932
1024
  const reference = ctxt.getReference();
933
1025
  let found = false;
934
1026
 
935
- if (set.matches && set.matches.length > 0) {
1027
+ if (set.inactive !== undefined) {
1028
+ let concept = this.sct.concepts.getConcept(reference);
1029
+ let active = (concept.flags & 0x0F) === 0;
1030
+ found = active !== set.inactive
1031
+ } else if (set.moduleId) {
1032
+ let concept = this.sct.concepts.getConcept(reference);
1033
+ let moduleId = this.sct.concepts.getModuleId(concept.index);
1034
+ found = moduleId === set.moduleId;
1035
+ } else if (set.propProp || set.propValue) {
1036
+ found = false;
1037
+ const relationships = this.sct.getConceptRelationships(reference);
1038
+ for (let relationshipRef of relationships) {
1039
+ const relationship = this.sct.relationships.getRelationship(relationshipRef);
1040
+ if (set.propProp === relationship.relType && set.propValue === relationship.target) {
1041
+ found = true;
1042
+ }
1043
+ }
1044
+ } else if (set.matches && set.matches.length > 0) {
936
1045
  found = set.matches.some(m => m.index === reference);
937
1046
  } else if (set.members && set.members.length > 0) {
938
1047
  found = set.members.some(m => m.ref === reference);
@@ -958,6 +1067,23 @@ class SnomedProvider extends BaseCSServices {
958
1067
  }
959
1068
 
960
1069
  const reference = concept.getReference();
1070
+ if (set.inactive !== undefined) {
1071
+ return this.sct.isActive(reference) !== set.inactive;
1072
+ }
1073
+
1074
+ if (set.moduleId) {
1075
+ return this.sct.concepts.getModuleId(reference) === set.moduleId;
1076
+ }
1077
+
1078
+ if (set.propProp || set.propValue) {
1079
+ const relationships = this.sct.getConceptRelationships(reference);
1080
+ for (let relationshipRef of relationships) {
1081
+ const relationship = this.sct.relationships.getRelationship(relationshipRef);
1082
+ if (set.propProp === relationship.relType && set.propValue === relationship.target) {
1083
+ return true;
1084
+ }
1085
+ }
1086
+ }
961
1087
 
962
1088
  if (set.matches && set.matches.length > 0) {
963
1089
  return set.matches.some(m => m.index === reference);
@@ -970,6 +1096,42 @@ class SnomedProvider extends BaseCSServices {
970
1096
  return false;
971
1097
  }
972
1098
 
1099
+ #ensurePopulated(set) {
1100
+ if (set.populationDone) {
1101
+ return;
1102
+ }
1103
+ if (set.inactive !== undefined && set.descendants.length === 0) {
1104
+ for (let i = 0; i < this.sct.concepts.count(); i++) {
1105
+ let concept = this.sct.concepts.getConceptByCount(i);
1106
+ let active = (concept.flags & 0x0F) === 0;
1107
+ if (active !== set.inactive) {
1108
+ set.descendants.push(concept.index);
1109
+ }
1110
+ }
1111
+ }
1112
+ if (set.moduleId) {
1113
+ for (let i = 0; i < this.sct.concepts.count(); i++) {
1114
+ let concept = this.sct.concepts.getConceptByCount(i);
1115
+ let moduleId = this.sct.concepts.getModuleId(concept.index);
1116
+ if (moduleId === set.moduleId) {
1117
+ set.descendants.push(concept.index);
1118
+ }
1119
+ }
1120
+ }
1121
+ if (set.propProp || set.propValue) {
1122
+ for (let i = 0; i < this.sct.concepts.count(); i++) {
1123
+ let concept = this.sct.concepts.getConceptByCount(i);
1124
+ const relationships = this.sct.getConceptRelationships(concept.getReference());
1125
+ for (let relationshipRef of relationships) {
1126
+ const relationship = this.sct.relationships.getRelationship(relationshipRef);
1127
+ if (set.propProp === relationship.relType && set.propValue === relationship.target) {
1128
+ set.descendants.push(concept.index);
1129
+ }
1130
+ }
1131
+ }
1132
+ }
1133
+ set.populationDone = true;
1134
+ }
973
1135
 
974
1136
  // Search filter
975
1137
  async searchFilter(filterContext, filter, sort) {
@@ -1052,6 +1214,64 @@ class SnomedProvider extends BaseCSServices {
1052
1214
  (cd.use.code === '900000000000013009' || cd.use.code === '900000000000003001');
1053
1215
  }
1054
1216
 
1217
+ async getTranslations(map, coding, target, reverse) {
1218
+ if (!map || (target && target !== this.system()) || reverse) {
1219
+ return [];
1220
+ }
1221
+ let ref = this.sct.concepts.findConcept(map.id);
1222
+ if (!ref.found) {
1223
+ return [];
1224
+ }
1225
+ let rref = this.sct.refSetIndex.getRefSetByConcept(ref.index);
1226
+ if (rref == -1) {
1227
+ return [];
1228
+ }
1229
+ let refSetRecord = this.sct.refSetIndex.getReferenceSet(rref);
1230
+ let members = this.sct.refSetMembers.getMembers(refSetRecord.membersByRef);
1231
+ let srcConcept = this.sct.concepts.findConcept(coding.code);
1232
+ if (!srcConcept.found) {
1233
+ return [];
1234
+ }
1235
+
1236
+ let result = [];
1237
+ let L = 0;
1238
+ let H = members.length - 1;
1239
+ while (L <= H) {
1240
+ const I = Math.floor((L + H) / 2);
1241
+ const ref = members[I].ref;
1242
+ if (ref < srcConcept.index) {
1243
+ L = I + 1;
1244
+ } else if (ref > srcConcept.index) {
1245
+ H = I - 1;
1246
+ } else {
1247
+ // Found — but scan left for first match in case of duplicates
1248
+ let first = I;
1249
+ while (first > 0 && members[first - 1].ref === srcConcept.index) {
1250
+ first--;
1251
+ }
1252
+ // Process all matching members
1253
+ for (let i = first; i < members.length && members[i].ref === srcConcept.index; i++) {
1254
+ let values = this.sct.refs.getReferences(members[i].values);
1255
+ if (values && values.length >= 1) {
1256
+ let tgtId = String(this.sct.concepts.getConceptId(values[0]));
1257
+ let ct = {
1258
+ map: map.vurl,
1259
+ code: tgtId,
1260
+ system: this.system(),
1261
+ version : this.version(),
1262
+ display: await this.display(tgtId),
1263
+ relationship: map.jsonObj.relationship
1264
+ }
1265
+ result.push(ct);
1266
+ }
1267
+ }
1268
+ break;
1269
+ }
1270
+ }
1271
+
1272
+ return result;
1273
+ }
1274
+
1055
1275
  }
1056
1276
 
1057
1277
  /**
@@ -1178,7 +1398,7 @@ class SnomedServicesFactory extends CodeSystemFactoryProvider {
1178
1398
  return null;
1179
1399
  }
1180
1400
  let rref = this.snomedServices.refSetIndex.getRefSetByConcept(ref.index);
1181
- if (rref == 0) {
1401
+ if (rref == -1) {
1182
1402
  return null;
1183
1403
  }
1184
1404
  return {
@@ -1287,6 +1507,59 @@ class SnomedServicesFactory extends CodeSystemFactoryProvider {
1287
1507
 
1288
1508
  return edition + ' ' + formatDateMMDDYYYY(match[2].substring(4, 6) + match[2].substring(6, 8) + match[2].substring(0, 4));
1289
1509
  }
1510
+
1511
+ async findImplicitConceptMap(url, version) {
1512
+ if (version && (version !== this.version())) {
1513
+ return null;
1514
+ }
1515
+ if (!url || !url.startsWith(this.system()+"?fhir_cm=")) {
1516
+ return null;
1517
+ }
1518
+ let id = url.substring(url.indexOf("=")+1);
1519
+ if (['900000000000523009', '900000000000526001', '900000000000527005', '900000000000530003'].includes(id)) {
1520
+ let name = '';
1521
+ let relationship = '';
1522
+ switch (id) {
1523
+ case '900000000000523009':
1524
+ name = 'POSSIBLY EQUIVALENT TO';
1525
+ relationship = 'inexact';
1526
+ break;
1527
+ case '900000000000526001':
1528
+ name = 'REPLACED BY';
1529
+ relationship = 'equivalent';
1530
+ break;
1531
+ case '900000000000527005':
1532
+ name = 'SAME AS';
1533
+ relationship = 'equal';
1534
+ break;
1535
+ case '900000000000530003':
1536
+ name = 'ALTERNATIVE';
1537
+ relationship = 'inexact';
1538
+ break;
1539
+ }
1540
+ let cm = {
1541
+ resourceType: 'ConceptMap',
1542
+ internalSource : this,
1543
+ relationship: relationship,
1544
+ id : id,
1545
+ url: `${this.system}?fhir_cm=${id}`,
1546
+ version: this.version(),
1547
+ name: `SNOMED CT ${name} Concept Map`,
1548
+ description: `The concept map implicitly defined by the ${name} Association Reference Set`,
1549
+ copyright: 'This value set includes content from SNOMED CT, which is copyright © 2002+ International Health Terminology Standards Development Organisation (SNOMED International), and distributed by agreement between SNOMED International and HL7',
1550
+ status: 'active',
1551
+ sourceUri: `${this.system}?fhir_vs`,
1552
+ targetUri: `${this.system}?fhir_vs`,
1553
+ group: [{
1554
+ source: 'http://snomed.info/sct',
1555
+ target: 'http://snomed.info/sct'
1556
+ }]
1557
+ }
1558
+ return new ConceptMap(cm);
1559
+ } else {
1560
+ return null;
1561
+ }
1562
+ }
1290
1563
  }
1291
1564
 
1292
1565
  function getEditionName(edition) {
Binary file
@@ -0,0 +1,186 @@
1
+ {
2
+ "resourceType" : "CodeSystem",
3
+ "language" : "de",
4
+ "id" : "de-multi",
5
+ "url" : "http://hl7.org/fhir/test/CodeSystem/de-multi",
6
+ "name" : "TestCodeSystemMultiLangDE",
7
+ "title" : "Testcodesystem mit mehreren Sprachen",
8
+ "title:en" : "Test Code System with Multiple Languages",
9
+ "_title" : {
10
+ "extension" : [{
11
+ "url" : "http://hl7.org/fhir/StructureDefinition/translation",
12
+ "extension" : [{
13
+ "url" : "lang",
14
+ "valueCode" : "en"
15
+ },{
16
+ "url" : "content",
17
+ "valueString" : "Test Code System with Multiple Languages"
18
+ }]
19
+ }]
20
+ },
21
+ "status" : "active",
22
+ "experimental" : false,
23
+ "date" : "2023-04-01",
24
+ "publisher" : "FHIR Project",
25
+ "caseSensitive" : true,
26
+ "content" : "complete",
27
+ "concept" : [{
28
+ "code" : "code1",
29
+ "display" : "Anzeige 1",
30
+ "definition" : "Mein erster Code",
31
+ "definition:en" : "My first code",
32
+ "_definition" : {
33
+ "extension" : [{
34
+ "url" : "http://hl7.org/fhir/StructureDefinition/translation",
35
+ "extension" : [{
36
+ "url" : "lang",
37
+ "valueCode" : "en"
38
+ },{
39
+ "url" : "content",
40
+ "valueString" : "My first code"
41
+ }]
42
+ }]
43
+ },
44
+ "designation" : [{
45
+ "language" : "en",
46
+ "value" : "Display 1"
47
+ }]
48
+ },
49
+ {
50
+ "code" : "code2",
51
+ "display" : "Anzeige 2",
52
+ "definition" : "Mein zweiter Code, mit Kindern",
53
+ "definition:en" : "My second code, with children",
54
+ "_definition" : {
55
+ "extension" : [{
56
+ "url" : "http://hl7.org/fhir/StructureDefinition/translation",
57
+ "extension" : [{
58
+ "url" : "lang",
59
+ "valueCode" : "en"
60
+ },{
61
+ "url" : "content",
62
+ "valueString" : "My second code, with children"
63
+ }]
64
+ }]
65
+ },
66
+ "designation" : [{
67
+ "language" : "de-CH",
68
+ "value" : "Anzeige 2"
69
+ },{
70
+ "language" : "es",
71
+ "value" : "Mostrar 2"
72
+ },{
73
+ "language" : "en",
74
+ "value" : "Display 2"
75
+ }],
76
+ "concept" : [{
77
+ "code" : "code2a",
78
+ "display" : "Anzeige 2a",
79
+ "definition" : "Mein erster Second-Level-Code",
80
+ "definition:en" : "My first second level code",
81
+ "_definition" : {
82
+ "extension" : [{
83
+ "url" : "http://hl7.org/fhir/StructureDefinition/translation",
84
+ "extension" : [{
85
+ "url" : "lang",
86
+ "valueCode" : "en"
87
+ },{
88
+ "url" : "content",
89
+ "valueString" : "My first second level code"
90
+ }]
91
+ }]
92
+ },
93
+ "designation" : [{
94
+ "language" : "en",
95
+ "value" : "Display 2a"
96
+ },{
97
+ "language" : "es",
98
+ "value" : "Mostrar 2a"
99
+ }],
100
+ "concept" : [{
101
+ "code" : "code2aI",
102
+ "display" : "Anzeige 2aI",
103
+ "definition" : "Mein erster Third-Level-Code",
104
+ "definition:en" : "My first third level code",
105
+ "_definition" : {
106
+ "extension" : [{
107
+ "url" : "http://hl7.org/fhir/StructureDefinition/translation",
108
+ "extension" : [{
109
+ "url" : "lang",
110
+ "valueCode" : "en"
111
+ },{
112
+ "url" : "content",
113
+ "valueString" : "My first third level code"
114
+ }]
115
+ }]
116
+ },
117
+ "designation" : [{
118
+ "language" : "es",
119
+ "value" : "Mostrar 2aI"
120
+ }]
121
+ },
122
+ {
123
+ "code" : "code2aII",
124
+ "display" : "Anzeige 2aII",
125
+ "definition" : "Mein zweiter Third-Level-Code",
126
+ "definition:en" : "My second third level code",
127
+ "_definition" : {
128
+ "extension" : [{
129
+ "url" : "http://hl7.org/fhir/StructureDefinition/translation",
130
+ "extension" : [{
131
+ "url" : "lang",
132
+ "valueCode" : "en"
133
+ },{
134
+ "url" : "content",
135
+ "valueString" : "My second third level code"
136
+ }]
137
+ }]
138
+ }
139
+ }]
140
+ },
141
+ {
142
+ "code" : "code2b",
143
+ "display" : "Anzeige 2b",
144
+ "definition" : "Mein zweiter Second-Level-Code",
145
+ "definition:en" : "My second second level code",
146
+ "_definition" : {
147
+ "extension" : [{
148
+ "url" : "http://hl7.org/fhir/StructureDefinition/translation",
149
+ "extension" : [{
150
+ "url" : "lang",
151
+ "valueCode" : "en"
152
+ },{
153
+ "url" : "content",
154
+ "valueString" : "My second second level code"
155
+ }]
156
+ }]
157
+ },
158
+ "designation" : [{
159
+ "language" : "en",
160
+ "value" : "Display 2b"
161
+ }]
162
+ }]
163
+ },
164
+ {
165
+ "code" : "code3",
166
+ "display" : "Anzeige 3",
167
+ "definition" : "Mein Third-Level-Code",
168
+ "definition:en" : "My Third Level Code",
169
+ "_definition" : {
170
+ "extension" : [{
171
+ "url" : "http://hl7.org/fhir/StructureDefinition/translation",
172
+ "extension" : [{
173
+ "url" : "lang",
174
+ "valueCode" : "en"
175
+ },{
176
+ "url" : "content",
177
+ "valueString" : "My Third Level Code"
178
+ }]
179
+ }]
180
+ },
181
+ "designation" : [{
182
+ "language" : "en",
183
+ "value" : "Display 3"
184
+ }]
185
+ }]
186
+ }