@imranq2/fhirpatientsummary 1.0.32 → 1.0.33

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.
package/dist/index.js CHANGED
@@ -169,7 +169,8 @@ var IPSSectionSummaryCompositionFilter = {
169
169
  ["HistoryOfProceduresSection" /* PROCEDURES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "procedure_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
170
170
  };
171
171
  var IPSSectionSummaryIPSCompositionFilter = {
172
- ["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => c.system === IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM && c.code === "ips_vital_summary_document")
172
+ ["Patient" /* PATIENT */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_patient_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
173
+ ["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_vital_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
173
174
  };
174
175
  var IPSSectionResourceHelper = class {
175
176
  static getResourceFilterForSection(section) {
@@ -884,18 +885,6 @@ var TemplateUtilities = class {
884
885
  }
885
886
  return "";
886
887
  }
887
- /**
888
- * Returns the owner tag from the resource meta.security array.
889
- * @param resource - FHIR resource with meta tag
890
- * @returns The owner code if found, otherwise undefined
891
- */
892
- getOwnerTag(resource) {
893
- if (!resource?.meta?.security) return "";
894
- const ownerEntry = resource.meta.security.find(
895
- (sec) => sec.system === "https://www.icanbwell.com/owner" && !!sec.code
896
- );
897
- return ownerEntry?.code;
898
- }
899
888
  /**
900
889
  * Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
901
890
  * This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
@@ -916,6 +905,17 @@ var TemplateUtilities = class {
916
905
  }
917
906
  return text.charAt(0).toUpperCase() + text.slice(1);
918
907
  }
908
+ renderListSectionData(sectionData) {
909
+ if (!sectionData || !Array.isArray(sectionData) || sectionData.length === 0) {
910
+ return "";
911
+ }
912
+ const items = [];
913
+ for (const section of sectionData) {
914
+ items.push(this.renderTextAsHtml(section.text?.div || ""));
915
+ }
916
+ const listString = Array.from(items).map((item) => `<li>${item}</li>`).join("");
917
+ return `<ul>${listString}</ul>`;
918
+ }
919
919
  /**
920
920
  * Renders note elements from a FHIR resource in a standardized format
921
921
  * Can render as simple comma-separated text or as styled HTML with timestamps
@@ -1403,6 +1403,60 @@ var PatientTemplate = class _PatientTemplate {
1403
1403
  generateNarrative(resources, timezone) {
1404
1404
  return _PatientTemplate.generateStaticNarrative(resources, timezone);
1405
1405
  }
1406
+ /**
1407
+ * Generate HTML narrative for Patient resources using summary
1408
+ * @param resources - FHIR Composition resources
1409
+ * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1410
+ * @returns HTML string for rendering
1411
+ */
1412
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1413
+ generateSummaryNarrative(resources, timezone) {
1414
+ const templateUtilities = new TemplateUtilities(resources);
1415
+ const compositionResources = resources[0];
1416
+ const data = {};
1417
+ for (const rowData of compositionResources.section ?? []) {
1418
+ for (const columnData of rowData.section ?? []) {
1419
+ switch (columnData.title) {
1420
+ case "Name":
1421
+ case "Address":
1422
+ case "Communication":
1423
+ data[columnData.title] = templateUtilities.renderListSectionData(columnData.section ?? []);
1424
+ break;
1425
+ case "Telecom": {
1426
+ const telecomStringParts = [];
1427
+ for (const telecomData of columnData.section ?? []) {
1428
+ const telecomSystem = telecomData?.title;
1429
+ const telecomValue = templateUtilities.renderListSectionData(telecomData.section ?? []);
1430
+ if (telecomSystem && telecomValue) {
1431
+ telecomStringParts.push(`<li><strong>${telecomSystem}:</strong>${telecomValue}</li>`);
1432
+ }
1433
+ }
1434
+ data["Telecom"] = `<ul>${telecomStringParts.join("")}</ul>`;
1435
+ break;
1436
+ }
1437
+ default:
1438
+ if (columnData.title) {
1439
+ data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1440
+ }
1441
+ break;
1442
+ }
1443
+ }
1444
+ }
1445
+ let html = `<p>This section merges all Patient resources into a single combined patient record, preferring non-empty values for each field.</p>`;
1446
+ html += `<div>
1447
+ <ul>
1448
+ <li><strong>Name(s):</strong>${data["Name"] || ""}</li>
1449
+ <li><strong>Gender:</strong>${data["Gender"] || ""}</li>
1450
+ <li><strong>Date of Birth:</strong>${data["Date of Birth"] || ""}</li>
1451
+ <li><strong>Telecom:</strong>${data["Telecom"] || ""}</li>
1452
+ <li><strong>Address(es):</strong>${data["Address"] || ""}</li>
1453
+ <li><strong>Marital Status:</strong> ${data["Marital Status"] || ""}</li>
1454
+ <li><strong>Deceased:</strong>${data["Deceased"] || ""}</li>
1455
+ <li><strong>Language(s):</strong>${data["Communication"] || ""}</li>
1456
+ </ul>
1457
+ </div>`;
1458
+ return html;
1459
+ }
1406
1460
  /**
1407
1461
  * Internal static implementation that actually generates the narrative
1408
1462
  * @param resources - FHIR Patient resources
@@ -1496,7 +1550,8 @@ var PatientTemplate = class _PatientTemplate {
1496
1550
  }
1497
1551
  }
1498
1552
  });
1499
- return Array.from(uniqueNames).map((nameText) => `<ul><li>${nameText}</li></ul>`).join("");
1553
+ const namesHtml = Array.from(uniqueNames).map((nameText) => `<li>${nameText}</li>`).join("");
1554
+ return `<ul>${namesHtml}</ul>`;
1500
1555
  }
1501
1556
  /**
1502
1557
  * Renders patient telecom information grouped by system
@@ -1600,7 +1655,8 @@ var PatientTemplate = class _PatientTemplate {
1600
1655
  }
1601
1656
  });
1602
1657
  const deduplicatedAddresses = this.deduplicateSimilarAddresses(Array.from(uniqueAddresses));
1603
- return deduplicatedAddresses.map((addressText) => `<ul><li>${addressText}</li></ul>`).join("");
1658
+ const addressesHtml = deduplicatedAddresses.map((addressText) => `<li>${addressText}</li>`).join("");
1659
+ return `<ul>${addressesHtml}</ul>`;
1604
1660
  }
1605
1661
  /**
1606
1662
  * Calculates the similarity between two strings using Levenshtein distance
@@ -1718,7 +1774,8 @@ var PatientTemplate = class _PatientTemplate {
1718
1774
  uniqueLanguages.add(language);
1719
1775
  }
1720
1776
  });
1721
- return Array.from(uniqueLanguages).map((language) => `<ul><li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li></ul>`).join("");
1777
+ const languagesHtml = Array.from(uniqueLanguages).map((language) => `<li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li>`).join("");
1778
+ return `<ul>${languagesHtml}</ul>`;
1722
1779
  }
1723
1780
  /**
1724
1781
  * Capitalizes first letter of a string
@@ -1762,7 +1819,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1762
1819
  <th>Code (System)</th>
1763
1820
  <th>Criticality</th>
1764
1821
  <th>Recorded Date</th>
1765
- <th>Source</th>
1766
1822
  </tr>
1767
1823
  </thead>
1768
1824
  <tbody>`;
@@ -1782,13 +1838,13 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1782
1838
  case "Recorded Date":
1783
1839
  data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1784
1840
  break;
1785
- case "Source":
1786
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1787
- break;
1788
1841
  default:
1789
1842
  break;
1790
1843
  }
1791
1844
  }
1845
+ if (data["allergen"]?.toLowerCase() === "unknown") {
1846
+ continue;
1847
+ }
1792
1848
  isSummaryCreated = true;
1793
1849
  html += `
1794
1850
  <tr>
@@ -1796,7 +1852,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1796
1852
  <td>${data["codeSystem"] ?? ""}</td>
1797
1853
  <td>${data["criticality"] ?? ""}</td>
1798
1854
  <td>${templateUtilities.renderTime(data["recordedDate"], timezone) ?? ""}</td>
1799
- <td>${data["source"] ?? ""}</td>
1800
1855
  </tr>`;
1801
1856
  }
1802
1857
  }
@@ -1850,7 +1905,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1850
1905
  <th>Reaction</th>
1851
1906
  <th>Onset Date</th>
1852
1907
  <th>Comments</th>
1853
- <th>Source</th>
1854
1908
  </tr>
1855
1909
  </thead>
1856
1910
  <tbody>`;
@@ -1880,7 +1934,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1880
1934
  <th>Onset Date</th>
1881
1935
  <th>Comments</th>
1882
1936
  <th>Resolved Date</th>
1883
- <th>Source</th>
1884
1937
  </tr>
1885
1938
  </thead>
1886
1939
  <tbody>`;
@@ -1909,16 +1962,19 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1909
1962
  static generateAllergyRows(allergies, templateUtilities, timezone, includeResolved = false) {
1910
1963
  let html = "";
1911
1964
  for (const allergy of allergies) {
1965
+ const allergenName = templateUtilities.codeableConceptDisplay(allergy.code);
1966
+ if (allergenName?.toLowerCase() === "unknown") {
1967
+ continue;
1968
+ }
1912
1969
  html += `
1913
1970
  <tr>
1914
- <td class="Name"><span class="AllergenName">${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(allergy.code)))}</span></td>
1971
+ <td class="Name"><span class="AllergenName">${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(allergenName))}</span></td>
1915
1972
  <td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(allergy.clinicalStatus)) || ""}</td>
1916
1973
  <td class="CodeSystem">${templateUtilities.codeableConceptCoding(allergy.code)}</td>
1917
1974
  <td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || ""}</td>
1918
1975
  <td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || ""}</td>
1919
1976
  <td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || ""}</td>
1920
- <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>
1921
- <td class="Source">${templateUtilities.getOwnerTag(allergy)}</td>`;
1977
+ <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
1922
1978
  if (includeResolved) {
1923
1979
  let endDate = "";
1924
1980
  if (allergy.extension && Array.isArray(allergy.extension)) {
@@ -1973,9 +2029,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1973
2029
  <th>Status</th>
1974
2030
  <th>Sig</th>
1975
2031
  <th>Days of Supply</th>
1976
- <th>Refills</th>
1977
2032
  <th>Start Date</th>
1978
- <th>Source</th>
1979
2033
  </tr>
1980
2034
  </thead>
1981
2035
  <tbody>`;
@@ -2001,15 +2055,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2001
2055
  case "Days Of Supply":
2002
2056
  data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2003
2057
  break;
2004
- case "Refills Remaining":
2005
- data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2006
- break;
2007
2058
  case "Authored On Date":
2008
2059
  data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2009
2060
  break;
2010
- case "Source":
2011
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2012
- break;
2013
2061
  default:
2014
2062
  break;
2015
2063
  }
@@ -2025,6 +2073,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2025
2073
  skippedMedications++;
2026
2074
  }
2027
2075
  if (data["status"] === "active" || startDateObj && startDateObj >= twoYearsAgo) {
2076
+ if (data["medication"]?.toLowerCase() === "unknown") {
2077
+ continue;
2078
+ }
2028
2079
  isSummaryCreated = true;
2029
2080
  html += `
2030
2081
  <tr>
@@ -2033,9 +2084,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2033
2084
  <td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
2034
2085
  <td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
2035
2086
  <td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
2036
- <td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
2037
2087
  <td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
2038
- <td>${templateUtilities.renderTextAsHtml(data["source"])}</td>
2039
2088
  </tr>`;
2040
2089
  }
2041
2090
  }
@@ -2160,9 +2209,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2160
2209
  <th>Code (System)</th>
2161
2210
  <th>Sig</th>
2162
2211
  <th>Dispense Quantity</th>
2163
- <th>Refills</th>
2164
2212
  <th>Start Date</th>
2165
- <th>Source</th>
2166
2213
  </tr>
2167
2214
  </thead>
2168
2215
  <tbody>`;
@@ -2171,7 +2218,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2171
2218
  let medicationName;
2172
2219
  let sig;
2173
2220
  let dispenseQuantity = "";
2174
- let refills = "";
2175
2221
  let startDate = "";
2176
2222
  let codeSystemDisplay = "";
2177
2223
  if (medication.type === "request") {
@@ -2187,7 +2233,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2187
2233
  dispenseQuantity = `${quantity.value} ${quantity.unit || quantity.code || ""}`.trim();
2188
2234
  }
2189
2235
  }
2190
- refills = mr.dispenseRequest?.numberOfRepeatsAllowed?.toString() || "";
2191
2236
  if (mr.dispenseRequest?.validityPeriod) {
2192
2237
  startDate = mr.dispenseRequest.validityPeriod.start || "";
2193
2238
  } else {
@@ -2212,6 +2257,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2212
2257
  codeSystemDisplay = templateUtilities.codeableConceptCoding(ms.medicationCodeableConcept);
2213
2258
  }
2214
2259
  }
2260
+ if (medicationName?.toLowerCase() === "unknown") {
2261
+ continue;
2262
+ }
2215
2263
  html += `
2216
2264
  <tr>
2217
2265
  <td>${type}</td>
@@ -2219,9 +2267,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2219
2267
  <td>${codeSystemDisplay}</td>
2220
2268
  <td>${sig}</td>
2221
2269
  <td>${dispenseQuantity}</td>
2222
- <td>${refills}</td>
2223
2270
  <td>${startDate}</td>
2224
- <td>${templateUtilities.getOwnerTag(medication.resource)}</td>
2225
2271
  </tr>`;
2226
2272
  }
2227
2273
  html += `
@@ -2266,7 +2312,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2266
2312
  <th>Code (System)</th>
2267
2313
  <th>Status</th>
2268
2314
  <th>Date</th>
2269
- <th>Source</th>
2270
2315
  </tr>
2271
2316
  </thead>
2272
2317
  <tbody>`;
@@ -2286,14 +2331,14 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2286
2331
  case "occurrenceDateTime":
2287
2332
  data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2288
2333
  break;
2289
- case "Source":
2290
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2291
- break;
2292
2334
  default:
2293
2335
  break;
2294
2336
  }
2295
2337
  }
2296
2338
  if (data["status"] === "completed") {
2339
+ if (data["immunization"]?.toLowerCase() === "unknown") {
2340
+ continue;
2341
+ }
2297
2342
  isSummaryCreated = true;
2298
2343
  html += `
2299
2344
  <tr>
@@ -2301,7 +2346,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2301
2346
  <td>${data["codeSystem"] ?? ""}</td>
2302
2347
  <td>${data["status"] ?? ""}</td>
2303
2348
  <td>${templateUtilities.renderTime(data["occurrenceDateTime"], timezone) ?? ""}</td>
2304
- <td>${data["source"] ?? ""}</td>
2305
2349
  </tr>`;
2306
2350
  }
2307
2351
  }
@@ -2332,7 +2376,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2332
2376
  <th>Lot Number</th>
2333
2377
  <th>Comments</th>
2334
2378
  <th>Date</th>
2335
- <th>Source</th>
2336
2379
  </tr>
2337
2380
  </thead>
2338
2381
  <tbody>`;
@@ -2340,9 +2383,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2340
2383
  if (immunizations.length > 0) {
2341
2384
  for (const resourceItem of immunizations) {
2342
2385
  const imm = resourceItem;
2386
+ const immunizationName = templateUtilities.codeableConceptDisplay(imm.vaccineCode);
2387
+ if (immunizationName?.toLowerCase() === "unknown") {
2388
+ continue;
2389
+ }
2343
2390
  html += `
2344
2391
  <tr>
2345
- <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(imm.vaccineCode)))}</td>
2392
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(immunizationName))}</td>
2346
2393
  <td>${templateUtilities.codeableConceptCoding(imm.vaccineCode)}</td>
2347
2394
  <td>${imm.status || ""}</td>
2348
2395
  <td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
@@ -2350,7 +2397,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2350
2397
  <td>${imm.lotNumber || ""}</td>
2351
2398
  <td>${templateUtilities.renderNotes(imm.note, timezone)}</td>
2352
2399
  <td>${templateUtilities.renderTime(imm.occurrenceDateTime, timezone)}</td>
2353
- <td>${templateUtilities.getOwnerTag(imm)}</td>
2354
2400
  </tr>`;
2355
2401
  }
2356
2402
  }
@@ -2400,7 +2446,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
2400
2446
  <th>Code (System)</th>
2401
2447
  <th>Onset Date</th>
2402
2448
  <th>Recorded Date</th>
2403
- <th>Source</th>
2404
2449
  </tr>
2405
2450
  </thead>
2406
2451
  <tbody>`;
@@ -2411,13 +2456,15 @@ var ProblemListTemplate = class _ProblemListTemplate {
2411
2456
  if (codeAndSystem && seenCodeAndSystems.has(codeAndSystem)) {
2412
2457
  continue;
2413
2458
  }
2459
+ if (conditionDisplay?.toLowerCase() === "unknown") {
2460
+ continue;
2461
+ }
2414
2462
  seenCodeAndSystems.add(codeAndSystem);
2415
2463
  html += `<tr>
2416
2464
  <td class="Name">${templateUtilities.capitalizeFirstLetter(conditionDisplay)}</td>
2417
2465
  <td class="CodeSystem">${codeAndSystem}</td>
2418
2466
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2419
2467
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2420
- <td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
2421
2468
  </tr>`;
2422
2469
  }
2423
2470
  html += `</tbody>
@@ -2457,7 +2504,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2457
2504
  <th>Code (System)</th>
2458
2505
  <th>Result</th>
2459
2506
  <th>Date</th>
2460
- <th>Source</th>
2461
2507
  </tr>
2462
2508
  </thead>
2463
2509
  <tbody>`;
@@ -2490,6 +2536,9 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2490
2536
  data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2491
2537
  }
2492
2538
  }
2539
+ if (data["Vital Name"]?.toLowerCase() === "unknown") {
2540
+ continue;
2541
+ }
2493
2542
  isSummaryCreated = true;
2494
2543
  html += `
2495
2544
  <tr>
@@ -2497,7 +2546,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2497
2546
  <td>${data["codeSystem"] ?? ""}</td>
2498
2547
  <td>${templateUtilities.extractObservationSummaryValue(data, timezone) ?? ""}</td>
2499
2548
  <td>${templateUtilities.extractObservationSummaryEffectiveTime(data, timezone) ?? ""}</td>
2500
- <td>${data["Source"] ?? ""}</td>
2501
2549
  </tr>`;
2502
2550
  }
2503
2551
  }
@@ -2535,14 +2583,17 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2535
2583
  <th>Component(s)</th>
2536
2584
  <th>Comments</th>
2537
2585
  <th>Date</th>
2538
- <th>Source</th>
2539
2586
  </tr>
2540
2587
  </thead>
2541
2588
  <tbody>`;
2542
2589
  for (const obs of observations) {
2590
+ const vitalName = templateUtilities.codeableConceptDisplay(obs.code, "display");
2591
+ if (vitalName?.toLowerCase() === "unknown") {
2592
+ continue;
2593
+ }
2543
2594
  html += `
2544
2595
  <tr>
2545
- <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code, "display")))}</td>
2596
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(vitalName))}</td>
2546
2597
  <td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
2547
2598
  <td>${templateUtilities.extractObservationValue(obs)}</td>
2548
2599
  <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
@@ -2550,7 +2601,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2550
2601
  <td>${templateUtilities.renderComponent(obs.component)}</td>
2551
2602
  <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
2552
2603
  <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
2553
- <td>${templateUtilities.getOwnerTag(obs)}</td>
2554
2604
  </tr>`;
2555
2605
  }
2556
2606
  html += `
@@ -2597,10 +2647,14 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
2597
2647
  });
2598
2648
  let isDeviceAdded = false;
2599
2649
  for (const dus of deviceStatements) {
2650
+ const deviceName = templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device));
2651
+ if (deviceName?.toLowerCase() === "unknown") {
2652
+ continue;
2653
+ }
2600
2654
  isDeviceAdded = true;
2601
2655
  html += `
2602
2656
  <tr>
2603
- <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device)))}</td>
2657
+ <td>${templateUtilities.capitalizeFirstLetter(deviceName)}</td>
2604
2658
  <td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
2605
2659
  <td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
2606
2660
  <td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
@@ -2974,7 +3028,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2974
3028
  <th>Result</th>
2975
3029
  <th>Reference Range</th>
2976
3030
  <th>Date</th>
2977
- <th>Source</th>
2978
3031
  </tr>
2979
3032
  </thead>
2980
3033
  <tbody>`;
@@ -2988,7 +3041,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2988
3041
  <th>Report</th>
2989
3042
  <th>Performer</th>
2990
3043
  <th>Issued</th>
2991
- <th>Source</th>
2992
3044
  </tr>
2993
3045
  </thead>
2994
3046
  <tbody>`;
@@ -3035,8 +3087,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3035
3087
  case "Status":
3036
3088
  data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3037
3089
  break;
3038
- case "Source":
3039
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3040
3090
  break;
3041
3091
  default:
3042
3092
  break;
@@ -3062,6 +3112,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3062
3112
  for (const component of components) {
3063
3113
  const componentCode = `${groupName}${component["code"] ?? ""}`;
3064
3114
  if (componentCode && !observationAdded.has(componentCode)) {
3115
+ if (component["code"]?.toLowerCase() === "unknown") {
3116
+ continue;
3117
+ }
3065
3118
  observationAdded.add(componentCode);
3066
3119
  this.formatSummaryObservationData(component);
3067
3120
  observationhtml += `
@@ -3071,7 +3124,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3071
3124
  <td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? ""}</td>
3072
3125
  <td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? ""}</td>
3073
3126
  <td>${date ?? ""}</td>
3074
- <td>${data["source"] ?? ""}</td>
3075
3127
  </tr>`;
3076
3128
  }
3077
3129
  }
@@ -3079,6 +3131,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3079
3131
  if (obsDate && obsDate >= twoYearsAgo) {
3080
3132
  const code = data["code"] ?? "";
3081
3133
  if (code && !observationAdded.has(code)) {
3134
+ if (code.toLowerCase() === "unknown") {
3135
+ continue;
3136
+ }
3082
3137
  observationAdded.add(code);
3083
3138
  this.formatSummaryObservationData(data);
3084
3139
  observationhtml += `
@@ -3088,7 +3143,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3088
3143
  <td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? ""}</td>
3089
3144
  <td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? ""}</td>
3090
3145
  <td>${date ?? ""}</td>
3091
- <td>${data["source"] ?? ""}</td>
3092
3146
  </tr>`;
3093
3147
  }
3094
3148
  }
@@ -3101,13 +3155,15 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3101
3155
  if (data["status"] === "final" && issuedDate && issuedDate >= twoYearsAgo) {
3102
3156
  const reportName = data["report"] ?? "";
3103
3157
  if (reportName && !diagnosticReportAdded.has(reportName)) {
3158
+ if (reportName.toLowerCase() === "unknown") {
3159
+ continue;
3160
+ }
3104
3161
  diagnosticReportAdded.add(reportName);
3105
3162
  diagnosticReporthtml += `
3106
3163
  <tr>
3107
3164
  <td>${templateUtilities.capitalizeFirstLetter(data["report"] ?? "")}</td>
3108
3165
  <td>${data["performer"] ?? ""}</td>
3109
3166
  <td>${templateUtilities.renderTime(data["issued"], timezone) ?? ""}</td>
3110
- <td>${data["source"] ?? ""}</td>
3111
3167
  </tr>`;
3112
3168
  }
3113
3169
  }
@@ -3292,7 +3348,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3292
3348
  <th>Result</th>
3293
3349
  <th>Reference Range</th>
3294
3350
  <th>Date</th>
3295
- <th>Source</th>
3296
3351
  </tr>
3297
3352
  </thead>
3298
3353
  <tbody>`;
@@ -3301,6 +3356,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3301
3356
  const obsCodeDisplay = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
3302
3357
  const obsCodeAndSystem = templateUtilities.codeableConceptCoding(obs.code);
3303
3358
  if (!observationAdded.has(obsCodeDisplay) && !observationAdded.has(obsCodeAndSystem)) {
3359
+ if (obsCodeDisplay?.toLowerCase() === "unknown") {
3360
+ continue;
3361
+ }
3304
3362
  observationAdded.add(obsCodeDisplay);
3305
3363
  observationAdded.add(obsCodeAndSystem);
3306
3364
  html += `
@@ -3310,7 +3368,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3310
3368
  <td>${templateUtilities.extractObservationValue(obs)}</td>
3311
3369
  <td>${templateUtilities.concatReferenceRange(obs.referenceRange)}</td>
3312
3370
  <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3313
- <td>${templateUtilities.getOwnerTag(obs)}</td>
3314
3371
  </tr>`;
3315
3372
  }
3316
3373
  }
@@ -3337,7 +3394,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3337
3394
  <th>Category</th>
3338
3395
  <th>Result</th>
3339
3396
  <th>Issued</th>
3340
- <th>Source</th>
3341
3397
  </tr>
3342
3398
  </thead>
3343
3399
  <tbody>`;
@@ -3346,6 +3402,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3346
3402
  const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(report.code));
3347
3403
  const codeAndSystem = templateUtilities.codeableConceptCoding(report.code);
3348
3404
  if (!diagnosticReportAdded.has(reportName) && !diagnosticReportAdded.has(codeAndSystem)) {
3405
+ if (reportName?.toLowerCase() === "unknown") {
3406
+ continue;
3407
+ }
3349
3408
  diagnosticReportAdded.add(reportName);
3350
3409
  diagnosticReportAdded.add(codeAndSystem);
3351
3410
  let resultCount = "";
@@ -3359,7 +3418,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3359
3418
  <td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
3360
3419
  <td>${resultCount}</td>
3361
3420
  <td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
3362
- <td>${templateUtilities.getOwnerTag(report)}</td>
3363
3421
  </tr>`;
3364
3422
  }
3365
3423
  }
@@ -3426,7 +3484,6 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3426
3484
  <th>Code (System)</th>
3427
3485
  <th>Performer</th>
3428
3486
  <th>Date</th>
3429
- <th>Source</th>
3430
3487
  </tr>
3431
3488
  </thead>
3432
3489
  <tbody>`;
@@ -3446,13 +3503,14 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3446
3503
  case "Performed Date":
3447
3504
  data["date"] = columnData.text?.div ?? "";
3448
3505
  break;
3449
- case "Source":
3450
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3451
3506
  break;
3452
3507
  default:
3453
3508
  break;
3454
3509
  }
3455
3510
  }
3511
+ if (data["procedure"]?.toLowerCase() === "unknown") {
3512
+ continue;
3513
+ }
3456
3514
  isSummaryCreated = true;
3457
3515
  html += `
3458
3516
  <tr>
@@ -3460,7 +3518,6 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3460
3518
  <td>${data["codeSystem"] ?? ""}</td>
3461
3519
  <td>${data["performer"] ?? ""}</td>
3462
3520
  <td>${templateUtilities.renderTime(data["date"], timezone) ?? ""}</td>
3463
- <td>${data["source"] ?? ""}</td>
3464
3521
  </tr>`;
3465
3522
  }
3466
3523
  }
@@ -3488,19 +3545,21 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3488
3545
  <th>Code (System)</th>
3489
3546
  <th>Comments</th>
3490
3547
  <th>Date</th>
3491
- <th>Source</th>
3492
3548
  </tr>
3493
3549
  </thead>
3494
3550
  <tbody>`;
3495
3551
  for (const resourceItem of resources) {
3496
3552
  const proc = resourceItem;
3553
+ const procedureName = templateUtilities.codeableConceptDisplay(proc.code, "display");
3554
+ if (procedureName?.toLowerCase() === "unknown") {
3555
+ continue;
3556
+ }
3497
3557
  html += `
3498
3558
  <tr>
3499
- <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(proc.code, "display")))}</td>
3559
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(procedureName))}</td>
3500
3560
  <td>${templateUtilities.codeableConceptCoding(proc.code)}</td>
3501
3561
  <td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
3502
3562
  <td>${templateUtilities.renderTime(proc.performedDateTime || proc.performedPeriod?.start, timezone)}</td>
3503
- <td>${templateUtilities.getOwnerTag(proc)}</td>
3504
3563
  </tr>`;
3505
3564
  }
3506
3565
  html += `
@@ -3547,7 +3606,6 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
3547
3606
  <th>Unit</th>
3548
3607
  <th>Comments</th>
3549
3608
  <th>Date</th>
3550
- <th>Source</th>
3551
3609
  </tr>
3552
3610
  </thead>
3553
3611
  <tbody>`;
@@ -3555,6 +3613,9 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
3555
3613
  for (const obs of observations) {
3556
3614
  const obsName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
3557
3615
  if (!addedObservations.has(obsName)) {
3616
+ if (obsName?.toLowerCase() === "unknown") {
3617
+ continue;
3618
+ }
3558
3619
  addedObservations.add(obsName);
3559
3620
  html += `
3560
3621
  <tr>
@@ -3564,7 +3625,6 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
3564
3625
  <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
3565
3626
  <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
3566
3627
  <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3567
- <td>${templateUtilities.getOwnerTag(obs)}</td>
3568
3628
  </tr>`;
3569
3629
  }
3570
3630
  }
@@ -3615,7 +3675,6 @@ var PastHistoryOfIllnessTemplate = class {
3615
3675
  <th>Onset Date</th>
3616
3676
  <th>Recorded Date</th>
3617
3677
  <th>Resolved Date</th>
3618
- <th>Source</th>
3619
3678
  </tr>
3620
3679
  </thead>
3621
3680
  <tbody>`;
@@ -3623,6 +3682,9 @@ var PastHistoryOfIllnessTemplate = class {
3623
3682
  for (const cond of filteredConditions) {
3624
3683
  const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(cond.code));
3625
3684
  if (!addedConditionCodes.has(conditionCode)) {
3685
+ if (conditionCode?.toLowerCase() === "unknown") {
3686
+ continue;
3687
+ }
3626
3688
  addedConditionCodes.add(conditionCode);
3627
3689
  html += `<tr>
3628
3690
  <td class="Name">${templateUtilities.capitalizeFirstLetter(conditionCode)}</td>
@@ -3630,7 +3692,6 @@ var PastHistoryOfIllnessTemplate = class {
3630
3692
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
3631
3693
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
3632
3694
  <td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
3633
- <td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
3634
3695
  </tr>`;
3635
3696
  }
3636
3697
  }
@@ -3671,19 +3732,21 @@ var PlanOfCareTemplate = class {
3671
3732
  <th>Comments</th>
3672
3733
  <th>Planned Start</th>
3673
3734
  <th>Planned End</th>
3674
- <th>Source</th>
3675
3735
  </tr>
3676
3736
  </thead>
3677
3737
  <tbody>`;
3678
3738
  for (const cp of carePlans) {
3739
+ const carePlanName = cp.description || cp.title || "";
3740
+ if (carePlanName.toLowerCase() === "unknown") {
3741
+ continue;
3742
+ }
3679
3743
  html += `
3680
3744
  <tr>
3681
- <td>${templateUtilities.capitalizeFirstLetter(cp.description || cp.title || "")}</td>
3745
+ <td>${templateUtilities.capitalizeFirstLetter(carePlanName)}</td>
3682
3746
  <td>${cp.intent || ""}</td>
3683
3747
  <td>${templateUtilities.concat(cp.note, "text")}</td>
3684
3748
  <td>${cp.period?.start ? templateUtilities.renderTime(cp.period?.start, timezone) : ""}</td>
3685
3749
  <td>${cp.period?.end ? templateUtilities.renderTime(cp.period?.end, timezone) : ""}</td>
3686
- <td>${templateUtilities.getOwnerTag(cp)}</td>
3687
3750
  </tr>`;
3688
3751
  }
3689
3752
  html += `
@@ -3711,7 +3774,6 @@ var PlanOfCareTemplate = class {
3711
3774
  <th>Created</th>
3712
3775
  <th>Planned Start</th>
3713
3776
  <th>Planned End</th>
3714
- <th>Source</th>
3715
3777
  </tr>
3716
3778
  </thead>
3717
3779
  <tbody>`;
@@ -3726,6 +3788,9 @@ var PlanOfCareTemplate = class {
3726
3788
  if (data["status"] !== "active") {
3727
3789
  continue;
3728
3790
  }
3791
+ if (data["CarePlan Name"]?.toLowerCase() === "unknown") {
3792
+ continue;
3793
+ }
3729
3794
  isSummaryCreated = true;
3730
3795
  html += `
3731
3796
  <tr>
@@ -3733,7 +3798,6 @@ var PlanOfCareTemplate = class {
3733
3798
  <td>${templateUtilities.renderTime(data["created"], timezone) ?? ""}</td>
3734
3799
  <td>${templateUtilities.renderTime(data["period.start"], timezone) ?? ""}</td>
3735
3800
  <td>${templateUtilities.renderTime(data["period.end"], timezone) ?? ""}</td>
3736
- <td>${data["source"] ?? ""}</td>
3737
3801
  </tr>`;
3738
3802
  }
3739
3803
  }
@@ -3790,6 +3854,9 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
3790
3854
  for (const obs of functionalObservations) {
3791
3855
  const observation = obs;
3792
3856
  const obsName = templateUtilities.codeableConceptDisplay(observation.code);
3857
+ if (obsName?.toLowerCase() === "unknown") {
3858
+ continue;
3859
+ }
3793
3860
  const value = templateUtilities.extractObservationValue(observation);
3794
3861
  const date = observation.effectiveDateTime ? templateUtilities.renderDate(observation.effectiveDateTime) : observation.issued ? templateUtilities.renderDate(observation.issued) : "";
3795
3862
  const interpretation = observation.interpretation ? templateUtilities.codeableConceptDisplay(observation.interpretation[0]) : "";
@@ -3897,18 +3964,19 @@ var PregnancyTemplate = class _PregnancyTemplate {
3897
3964
  <th>Code (System)</th>
3898
3965
  <th>Comments</th>
3899
3966
  <th>Date</th>
3900
- <th>Source</th>
3901
3967
  </tr>
3902
3968
  </thead>
3903
3969
  <tbody>`;
3904
- function renderRow({ result, comments, date, codeSystem, owner }) {
3970
+ function renderRow({ result, comments, date, codeSystem }) {
3971
+ if (result?.toLowerCase() === "unknown") {
3972
+ return;
3973
+ }
3905
3974
  html += `
3906
3975
  <tr>
3907
3976
  <td class="Result">${templateUtilities.capitalizeFirstLetter(result)}</td>
3908
3977
  <td class="CodeSystem">${codeSystem}</td>
3909
3978
  <td class="Comments">${comments}</td>
3910
3979
  <td class="Date">${date}</td>
3911
- <td class="Source">${owner}</td>
3912
3980
  </tr>`;
3913
3981
  }
3914
3982
  const rowResources = [];
@@ -3962,8 +4030,7 @@ var PregnancyTemplate = class _PregnancyTemplate {
3962
4030
  const rowKey = `${result}|${codeSystem}`;
3963
4031
  if (!addedRows.has(rowKey)) {
3964
4032
  addedRows.add(rowKey);
3965
- const owner = templateUtilities.getOwnerTag(resource);
3966
- renderRow({ result, comments, date: dateStr, codeSystem, owner });
4033
+ renderRow({ result, comments, date: dateStr, codeSystem });
3967
4034
  }
3968
4035
  }
3969
4036
  html += `
@@ -4010,11 +4077,17 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
4010
4077
  </tr>
4011
4078
  </thead>
4012
4079
  <tbody>`;
4080
+ let isConsentAdded = false;
4013
4081
  for (const resourceItem of resources) {
4014
4082
  const consent = resourceItem;
4083
+ const consentScope = templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(consent.scope, "display")));
4084
+ if (!consentScope || consentScope.toLowerCase() === "unknown") {
4085
+ continue;
4086
+ }
4087
+ isConsentAdded = true;
4015
4088
  html += `
4016
4089
  <tr>
4017
- <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(consent.scope, "display")))}</td>
4090
+ <td>${consentScope}</td>
4018
4091
  <td>${consent.status || ""}</td>
4019
4092
  <td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
4020
4093
  <td>${consent.dateTime || ""}</td>
@@ -4023,7 +4096,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
4023
4096
  html += `
4024
4097
  </tbody>
4025
4098
  </table>`;
4026
- return html;
4099
+ return isConsentAdded ? html : void 0;
4027
4100
  }
4028
4101
  };
4029
4102
 
@@ -4218,6 +4291,10 @@ var ComprehensiveIPSCompositionBuilder = class {
4218
4291
  * @param validResources - Array of domain resources
4219
4292
  */
4220
4293
  addSectionAsync(narrative, sectionType, validResources) {
4294
+ if (sectionType === "Patient" /* PATIENT */) {
4295
+ this.patientSummary = narrative;
4296
+ return this;
4297
+ }
4221
4298
  const sectionEntry = {
4222
4299
  title: IPS_SECTION_DISPLAY_NAMES[sectionType] || sectionType,
4223
4300
  code: {
@@ -4247,26 +4324,24 @@ var ComprehensiveIPSCompositionBuilder = class {
4247
4324
  for (const resource of validResources) {
4248
4325
  this.resources.add(resource);
4249
4326
  }
4250
- if (sectionType !== "Patient" /* PATIENT */) {
4251
- let narrative = void 0;
4252
- if (validResources.length > 0) {
4253
- narrative = await NarrativeGenerator.generateNarrativeAsync(
4254
- sectionType,
4255
- validResources,
4256
- timezone,
4257
- true
4258
- );
4259
- }
4260
- if (!narrative && sectionType in IPSMandatorySections) {
4261
- narrative = await NarrativeGenerator.createNarrativeAsync(
4262
- IPSMissingMandatorySectionContent[sectionType]
4263
- );
4264
- }
4265
- if (!narrative) {
4266
- return this;
4267
- }
4268
- this.addSectionAsync(narrative, sectionType, validResources);
4327
+ let narrative = void 0;
4328
+ if (validResources.length > 0) {
4329
+ narrative = await NarrativeGenerator.generateNarrativeAsync(
4330
+ sectionType,
4331
+ validResources,
4332
+ timezone,
4333
+ true
4334
+ );
4269
4335
  }
4336
+ if (!narrative && sectionType in IPSMandatorySections) {
4337
+ narrative = await NarrativeGenerator.createNarrativeAsync(
4338
+ IPSMissingMandatorySectionContent[sectionType]
4339
+ );
4340
+ }
4341
+ if (!narrative) {
4342
+ return this;
4343
+ }
4344
+ this.addSectionAsync(narrative, sectionType, validResources);
4270
4345
  return this;
4271
4346
  }
4272
4347
  async makeSectionFromSummaryAsync(sectionType, summaryCompositions, resources, timezone) {
@@ -4304,17 +4379,18 @@ var ComprehensiveIPSCompositionBuilder = class {
4304
4379
  * @param timezone - Optional timezone to use for date formatting
4305
4380
  * @param useSummaryCompositions - Whether to use summary compositions (default: false)
4306
4381
  */
4307
- async readBundleAsync(bundle, timezone, useSummaryCompositions = false) {
4382
+ async readBundleAsync(bundle, timezone, useSummaryCompositions = false, consoleLogger = console) {
4308
4383
  if (!bundle.entry) {
4309
4384
  return this;
4310
4385
  }
4311
4386
  const patientEntries = [];
4312
4387
  const resources = [];
4313
4388
  bundle.entry.forEach((e) => {
4314
- if (e.resource?.resourceType === "Patient") {
4315
- patientEntries.push(e.resource);
4316
- this.resources.add(e.resource);
4317
- } else if (e.resource) {
4389
+ if (e.resource) {
4390
+ if (e.resource.resourceType === "Patient") {
4391
+ patientEntries.push(e.resource);
4392
+ this.resources.add(e.resource);
4393
+ }
4318
4394
  resources.push(e.resource);
4319
4395
  }
4320
4396
  });
@@ -4323,23 +4399,20 @@ var ComprehensiveIPSCompositionBuilder = class {
4323
4399
  }
4324
4400
  this.patients = patientEntries;
4325
4401
  for (const sectionType of Object.values(IPSSections)) {
4326
- if (sectionType === "Patient" /* PATIENT */) {
4327
- continue;
4328
- }
4329
4402
  const summaryIPSCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryIPSCompositionFilterForSection(sectionType) : void 0;
4330
4403
  const sectionIPSSummary = summaryIPSCompositionFilter ? resources.filter((resource) => summaryIPSCompositionFilter(resource)) : [];
4331
4404
  if (sectionIPSSummary.length > 0) {
4332
- console.log(`Using IPS summary composition for section: ${sectionType}`);
4405
+ consoleLogger.info(`Using IPS summary composition for section: ${sectionType}`);
4333
4406
  await this.makeSectionFromSummaryAsync(sectionType, sectionIPSSummary, resources, timezone);
4334
4407
  continue;
4335
4408
  }
4336
4409
  const summaryCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryCompositionFilterForSection(sectionType) : void 0;
4337
4410
  const sectionSummary = summaryCompositionFilter ? resources.filter((resource) => summaryCompositionFilter(resource)) : [];
4338
4411
  if (sectionSummary.length > 0) {
4339
- console.log(`Using summary composition for section: ${sectionType}`);
4412
+ consoleLogger.info(`Using summary composition for section: ${sectionType}`);
4340
4413
  await this.makeSectionFromSummaryAsync(sectionType, sectionSummary, resources, timezone);
4341
4414
  } else {
4342
- console.log(`Using individual resources for section: ${sectionType}`);
4415
+ consoleLogger.info(`Using individual resources for section: ${sectionType}`);
4343
4416
  const sectionFilter = IPSSectionResourceHelper.getResourceFilterForSection(sectionType);
4344
4417
  const sectionResources = resources.filter((resource) => sectionFilter(resource));
4345
4418
  await this.makeSectionAsync(sectionType, sectionResources, timezone);
@@ -4363,6 +4436,9 @@ var ComprehensiveIPSCompositionBuilder = class {
4363
4436
  if (!this.patients) {
4364
4437
  throw new Error("Patient resource must be set before building the bundle");
4365
4438
  }
4439
+ if (!this.patientSummary) {
4440
+ throw new Error("Patient summary narrative must be set before building the bundle");
4441
+ }
4366
4442
  const primaryPatientId = patientId ?? this.patients[0].id;
4367
4443
  const composition = {
4368
4444
  id: `Composition-${primaryPatientId}`,
@@ -4386,14 +4462,7 @@ var ComprehensiveIPSCompositionBuilder = class {
4386
4462
  date: (now || /* @__PURE__ */ new Date()).toISOString(),
4387
4463
  title: "International Patient Summary",
4388
4464
  section: this.sections,
4389
- text: await NarrativeGenerator.generateNarrativeAsync(
4390
- "Patient" /* PATIENT */,
4391
- this.patients,
4392
- timezone,
4393
- true,
4394
- false,
4395
- now
4396
- )
4465
+ text: this.patientSummary
4397
4466
  };
4398
4467
  const bundle = {
4399
4468
  resourceType: "Bundle",