@imranq2/fhirpatientsummary 1.0.27 → 1.0.29

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
@@ -133,6 +133,9 @@ var IPSSectionSummaryCompositionFilter = {
133
133
  // [IPSSections.DIAGNOSTIC_REPORTS]: (resource) => resource.resourceType === 'Composition' && resource.type?.coding?.some((c: any) => c.system === IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM && ["lab_summary_document", "diagnosticreportlab_summary_document"].includes(c.code)),
134
134
  ["HistoryOfProceduresSection" /* PROCEDURES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => c.system === IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM && c.code === "procedure_summary_document")
135
135
  };
136
+ var IPSSectionSummaryIPSCompositionFilter = {
137
+ ["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")
138
+ };
136
139
  var IPSSectionResourceHelper = class {
137
140
  static getResourceFilterForSection(section) {
138
141
  return IPSSectionResourceFilters[section];
@@ -145,6 +148,9 @@ var IPSSectionResourceHelper = class {
145
148
  static getSummaryCompositionFilterForSection(section) {
146
149
  return IPSSectionSummaryCompositionFilter[section];
147
150
  }
151
+ static getSummaryIPSCompositionFilterForSection(section) {
152
+ return IPSSectionSummaryIPSCompositionFilter[section];
153
+ }
148
154
  };
149
155
 
150
156
  // src/narratives/templates/typescript/TemplateUtilities.ts
@@ -220,7 +226,7 @@ var TemplateUtilities = class {
220
226
  renderOrganization(orgRef) {
221
227
  const organization = orgRef && this.resolveReference(orgRef);
222
228
  if (organization && organization.resourceType === "Organization" && organization.name) {
223
- return organization.name;
229
+ return this.renderTextAsHtml(organization.name);
224
230
  }
225
231
  return "";
226
232
  }
@@ -232,7 +238,7 @@ var TemplateUtilities = class {
232
238
  renderVaccineManufacturer(immunization) {
233
239
  const organization = immunization.manufacturer && this.resolveReference(immunization.manufacturer);
234
240
  if (organization && organization.resourceType === "Organization" && organization.name) {
235
- return organization.name;
241
+ return this.renderTextAsHtml(organization.name);
236
242
  }
237
243
  return "";
238
244
  }
@@ -271,7 +277,7 @@ var TemplateUtilities = class {
271
277
  */
272
278
  renderMedicationCode(medication) {
273
279
  if (medication && medication.code) {
274
- return this.codeableConcept(medication.code, "display");
280
+ return this.renderTextAsHtml(this.codeableConcept(medication.code, "display"));
275
281
  }
276
282
  return "";
277
283
  }
@@ -282,7 +288,7 @@ var TemplateUtilities = class {
282
288
  */
283
289
  renderDoseNumber(doseNumber) {
284
290
  if (doseNumber && doseNumber.value !== void 0) {
285
- return doseNumber.value.toString();
291
+ return this.renderTextAsHtml(doseNumber.value.toString());
286
292
  }
287
293
  return "";
288
294
  }
@@ -293,7 +299,7 @@ var TemplateUtilities = class {
293
299
  */
294
300
  renderValueUnit(value) {
295
301
  if (value && value.constructor?.name === "Quantity" && value.unit) {
296
- return value.unit;
302
+ return this.renderTextAsHtml(value.unit);
297
303
  }
298
304
  return "";
299
305
  }
@@ -359,7 +365,7 @@ var TemplateUtilities = class {
359
365
  * @returns Comma-separated string of items
360
366
  */
361
367
  safeConcat(list, attr) {
362
- return this.concat(list || [], attr);
368
+ return this.renderTextAsHtml(this.concat(list || [], attr));
363
369
  }
364
370
  /**
365
371
  * Concatenates text from a list of CodeableConcept objects
@@ -376,7 +382,7 @@ var TemplateUtilities = class {
376
382
  items.push(item.text);
377
383
  }
378
384
  }
379
- return items.join(", ");
385
+ return this.renderTextAsHtml(items.join(", "));
380
386
  }
381
387
  /**
382
388
  * Concatenates reaction manifestations
@@ -397,7 +403,7 @@ var TemplateUtilities = class {
397
403
  }
398
404
  }
399
405
  }
400
- return texts.join(", ");
406
+ return this.renderTextAsHtml(texts.join(", "));
401
407
  }
402
408
  /**
403
409
  * Concatenates dose numbers
@@ -414,7 +420,7 @@ var TemplateUtilities = class {
414
420
  doseNumbers.push(item.doseNumberPositiveInt.toString());
415
421
  }
416
422
  }
417
- return doseNumbers.join(", ");
423
+ return this.renderTextAsHtml(doseNumbers.join(", "));
418
424
  }
419
425
  /**
420
426
  * Concatenates dosage routes
@@ -431,7 +437,7 @@ var TemplateUtilities = class {
431
437
  routes.push(item.route.text);
432
438
  }
433
439
  }
434
- return routes.join(", ");
440
+ return this.renderTextAsHtml(routes.join(", "));
435
441
  }
436
442
  /**
437
443
  * Returns the first item from a list of CodeableConcept objects
@@ -440,7 +446,7 @@ var TemplateUtilities = class {
440
446
  */
441
447
  firstFromCodeableConceptList(list) {
442
448
  if (list && Array.isArray(list) && list[0]) {
443
- return this.codeableConcept(list[0], "display");
449
+ return this.renderTextAsHtml(this.codeableConcept(list[0], "display"));
444
450
  }
445
451
  return "";
446
452
  }
@@ -459,7 +465,7 @@ var TemplateUtilities = class {
459
465
  texts.push(item.text);
460
466
  }
461
467
  }
462
- return texts.join(", ");
468
+ return this.renderTextAsHtml(texts.join(", "));
463
469
  }
464
470
  /**
465
471
  * Renders component codes
@@ -791,9 +797,11 @@ var TemplateUtilities = class {
791
797
  return "";
792
798
  }
793
799
  /**
794
- * Renders text as HTML, escaping special characters and replacing newlines with <br />
795
- * @param text - The text to render
796
- * @private
800
+ * Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
801
+ * This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
802
+ * and to preserve formatting. Use this in templates or UI components that need to safely display multi-line or arbitrary text.
803
+ * @param text - The text to render as HTML
804
+ * @returns The HTML-safe string with newlines converted to <br />
797
805
  */
798
806
  renderTextAsHtml(text) {
799
807
  if (!text || text.trim() === "") {
@@ -857,7 +865,7 @@ var TemplateUtilities = class {
857
865
  dateTime = DateTime.fromISO(String(dateValue));
858
866
  }
859
867
  if (!dateTime.isValid) {
860
- return String(dateValue);
868
+ return this.renderTextAsHtml(String(dateValue));
861
869
  }
862
870
  if (dateOnly) {
863
871
  dateTime = dateTime.toUTC();
@@ -873,9 +881,9 @@ var TemplateUtilities = class {
873
881
  hour12: true,
874
882
  timeZoneName: "short"
875
883
  };
876
- return dateTime.toLocaleString(formatOptions);
884
+ return this.renderTextAsHtml(dateTime.toLocaleString(formatOptions));
877
885
  } catch {
878
- return String(dateValue);
886
+ return this.renderTextAsHtml(String(dateValue));
879
887
  }
880
888
  }
881
889
  /**
@@ -1579,7 +1587,7 @@ var PatientTemplate = class _PatientTemplate {
1579
1587
  const uniqueLanguages = /* @__PURE__ */ new Set();
1580
1588
  const preferredLanguages = /* @__PURE__ */ new Set();
1581
1589
  patient.communication.forEach((comm) => {
1582
- const language = templateUtilities.codeableConcept(comm.language);
1590
+ const language = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(comm.language));
1583
1591
  if (language) {
1584
1592
  if (comm.preferred) {
1585
1593
  preferredLanguages.add(language);
@@ -1637,13 +1645,13 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1637
1645
  for (const columnData of rowData.section ?? []) {
1638
1646
  switch (columnData.title) {
1639
1647
  case "Allergen Name":
1640
- data["allergen"] = columnData.text?.div ?? "";
1648
+ data["allergen"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1641
1649
  break;
1642
1650
  case "Criticality":
1643
- data["criticality"] = columnData.text?.div ?? "";
1651
+ data["criticality"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1644
1652
  break;
1645
1653
  case "Recorded Date":
1646
- data["recordedDate"] = columnData.text?.div ?? "";
1654
+ data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1647
1655
  break;
1648
1656
  default:
1649
1657
  break;
@@ -1764,11 +1772,11 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1764
1772
  for (const allergy of allergies) {
1765
1773
  html += `
1766
1774
  <tr id="${templateUtilities.narrativeLinkId(allergy.extension)}">
1767
- <td class="Name"><span class="AllergenName">${templateUtilities.codeableConcept(allergy.code)}</span></td>
1768
- <td class="Status">${templateUtilities.codeableConcept(allergy.clinicalStatus) || "-"}</td>
1769
- <td class="Category">${templateUtilities.safeConcat(allergy.category) || "-"}</td>
1770
- <td class="Reaction">${templateUtilities.concatReactionManifestation(allergy.reaction) || "-"}</td>
1771
- <td class="OnsetDate">${templateUtilities.renderTime(allergy.onsetDateTime, timezone) || "-"}</td>
1775
+ <td class="Name"><span class="AllergenName">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.code))}</span></td>
1776
+ <td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.clinicalStatus)) || "-"}</td>
1777
+ <td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || "-"}</td>
1778
+ <td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || "-"}</td>
1779
+ <td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || "-"}</td>
1772
1780
  <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
1773
1781
  if (includeResolved) {
1774
1782
  let endDate = "-";
@@ -1781,7 +1789,7 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1781
1789
  }
1782
1790
  }
1783
1791
  html += `
1784
- <td class="ResolvedDate">${endDate}</td>`;
1792
+ <td class="ResolvedDate">${templateUtilities.renderTextAsHtml(endDate)}</td>`;
1785
1793
  }
1786
1794
  html += `</tr>`;
1787
1795
  }
@@ -1804,17 +1812,21 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1804
1812
  * Generate HTML narrative for Medication resources using summary
1805
1813
  * @param resources - FHIR Composition resources
1806
1814
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1815
+ * @param now - Optional current date to use for calculations (defaults to new Date())
1807
1816
  * @returns HTML string for rendering
1808
1817
  */
1809
- generateSummaryNarrative(resources, timezone) {
1818
+ generateSummaryNarrative(resources, timezone, now) {
1810
1819
  const templateUtilities = new TemplateUtilities(resources);
1811
1820
  let isSummaryCreated = false;
1821
+ const currentDate = now || /* @__PURE__ */ new Date();
1822
+ const twelveMonthsAgo = new Date(currentDate.getFullYear(), currentDate.getMonth() - 12, currentDate.getDate());
1812
1823
  let html = `
1813
1824
  <div>
1814
1825
  <table>
1815
1826
  <thead>
1816
1827
  <tr>
1817
1828
  <th>Medication</th>
1829
+ <th>Status</th>
1818
1830
  <th>Sig</th>
1819
1831
  <th>Days of Supply</th>
1820
1832
  <th>Refills</th>
@@ -1828,40 +1840,48 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1828
1840
  for (const columnData of rowData.section ?? []) {
1829
1841
  switch (columnData.title) {
1830
1842
  case "Medication Name":
1831
- data["medication"] = columnData.text?.div ?? "";
1843
+ data["medication"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1832
1844
  break;
1833
1845
  case "Status":
1834
- data["status"] = columnData.text?.div ?? "";
1846
+ data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1835
1847
  break;
1836
1848
  case "Prescriber Instruction":
1837
- data["sig-prescriber"] = columnData.text?.div ?? "";
1849
+ data["sig-prescriber"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1838
1850
  break;
1839
1851
  case "Pharmacy Instruction":
1840
- data["sig-pharmacy"] = columnData.text?.div ?? "";
1852
+ data["sig-pharmacy"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1841
1853
  break;
1842
1854
  case "Days Of Supply":
1843
- data["daysOfSupply"] = columnData.text?.div ?? "";
1855
+ data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1844
1856
  break;
1845
1857
  case "Refills Remaining":
1846
- data["refills"] = columnData.text?.div ?? "";
1858
+ data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1847
1859
  break;
1848
1860
  case "Authored On Date":
1849
- data["startDate"] = columnData.text?.div ?? "";
1861
+ data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1850
1862
  break;
1851
1863
  default:
1852
1864
  break;
1853
1865
  }
1854
1866
  }
1855
- if (data["status"] === "active") {
1867
+ let startDateObj;
1868
+ if (data["startDate"]) {
1869
+ startDateObj = new Date(data["startDate"]);
1870
+ if (isNaN(startDateObj.getTime())) {
1871
+ startDateObj = void 0;
1872
+ }
1873
+ }
1874
+ if (data["status"] === "active" || startDateObj && startDateObj >= twelveMonthsAgo) {
1856
1875
  isSummaryCreated = true;
1857
1876
  html += `
1858
- <tr>
1859
- <td>${data["medication"]}</td>
1860
- <td>${data["sig-prescriber"] || data["sig-pharmacy"]}</td>
1861
- <td>${data["daysOfSupply"]}</td>
1862
- <td>${data["refills"]}</td>
1863
- <td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
1864
- </tr>`;
1877
+ <tr>
1878
+ <td>${templateUtilities.renderTextAsHtml(data["medication"])}</td>
1879
+ <td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
1880
+ <td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
1881
+ <td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
1882
+ <td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
1883
+ <td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
1884
+ </tr>`;
1865
1885
  }
1866
1886
  }
1867
1887
  }
@@ -2083,13 +2103,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2083
2103
  for (const columnData of rowData.section ?? []) {
2084
2104
  switch (columnData.title) {
2085
2105
  case "Immunization Name":
2086
- data["immunization"] = columnData.text?.div ?? "";
2106
+ data["immunization"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2087
2107
  break;
2088
2108
  case "Status":
2089
- data["status"] = columnData.text?.div ?? "";
2109
+ data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2090
2110
  break;
2091
2111
  case "occurrenceDateTime":
2092
- data["occurrenceDateTime"] = columnData.text?.div ?? "";
2112
+ data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2093
2113
  break;
2094
2114
  default:
2095
2115
  break;
@@ -2140,7 +2160,7 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2140
2160
  const imm = resourceItem;
2141
2161
  html += `
2142
2162
  <tr id="${templateUtilities.narrativeLinkId(imm)}">
2143
- <td>${templateUtilities.codeableConcept(imm.vaccineCode)}</td>
2163
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(imm.vaccineCode))}</td>
2144
2164
  <td>${imm.status || ""}</td>
2145
2165
  <td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
2146
2166
  <td>${templateUtilities.renderVaccineManufacturer(imm)}</td>
@@ -2196,7 +2216,7 @@ var ProblemListTemplate = class _ProblemListTemplate {
2196
2216
  <tbody>`;
2197
2217
  const addedConditionCodes = /* @__PURE__ */ new Set();
2198
2218
  for (const cond of activeConditions) {
2199
- const conditionCode = templateUtilities.codeableConcept(cond.code);
2219
+ const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
2200
2220
  if (!addedConditionCodes.has(conditionCode)) {
2201
2221
  addedConditionCodes.add(conditionCode);
2202
2222
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
@@ -2256,7 +2276,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2256
2276
  const vitalData = {};
2257
2277
  for (const component of columnData.section?.[0]?.section ?? []) {
2258
2278
  if (component.title) {
2259
- vitalData[component.title] = component.text?.div ?? "";
2279
+ vitalData[component.title] = templateUtilities.renderTextAsHtml(component.text?.div ?? "");
2260
2280
  }
2261
2281
  }
2262
2282
  const vitalValue = templateUtilities.extractObservationSummaryValue(
@@ -2268,7 +2288,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2268
2288
  data[dataKey] = vitalValue;
2269
2289
  }
2270
2290
  }
2271
- data[columnTitle] = columnData.text?.div ?? "";
2291
+ data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2272
2292
  }
2273
2293
  }
2274
2294
  isSummaryCreated = true;
@@ -2318,7 +2338,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2318
2338
  for (const obs of observations) {
2319
2339
  html += `
2320
2340
  <tr id="${templateUtilities.narrativeLinkId(obs)}">
2321
- <td>${templateUtilities.codeableConcept(obs.code, "display")}</td>
2341
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code, "display"))}</td>
2322
2342
  <td>${templateUtilities.extractObservationValue(obs)}</td>
2323
2343
  <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
2324
2344
  <td>${templateUtilities.firstFromCodeableConceptList(obs.interpretation)}</td>
@@ -2372,10 +2392,10 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
2372
2392
  for (const dus of deviceStatements) {
2373
2393
  html += `
2374
2394
  <tr id="${templateUtilities.narrativeLinkId(dus)}">
2375
- <td>${templateUtilities.renderDevice(dus.device)}</td>
2376
- <td>${dus.status || ""}</td>
2395
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device))}</td>
2396
+ <td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
2377
2397
  <td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
2378
- <td>${templateUtilities.renderRecorded(dus.recordedOn, timezone)}</td>
2398
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
2379
2399
  </tr>`;
2380
2400
  }
2381
2401
  html += `
@@ -2511,149 +2531,150 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2511
2531
  * Helper function to extract observation field data
2512
2532
  * @param column - Column data from the summary
2513
2533
  * @param targetData - Record to populate with extracted data
2534
+ * @param templateUtilities - Instance of TemplateUtilities for utility functions
2514
2535
  */
2515
- extractSummaryObservationFields(column, targetData) {
2536
+ extractSummaryObservationFields(column, targetData, templateUtilities) {
2516
2537
  switch (column.title) {
2517
2538
  case "Labs Name":
2518
- targetData["code"] = column.text?.div ?? "";
2539
+ targetData["code"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2519
2540
  break;
2520
2541
  case "effectiveDateTime":
2521
- targetData["effectiveDateTime"] = column.text?.div ?? "";
2542
+ targetData["effectiveDateTime"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2522
2543
  break;
2523
2544
  case "effectivePeriod.start":
2524
- targetData["effectivePeriodStart"] = column.text?.div ?? "";
2545
+ targetData["effectivePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2525
2546
  break;
2526
2547
  case "effectivePeriod.end":
2527
- targetData["effectivePeriodEnd"] = column.text?.div ?? "";
2548
+ targetData["effectivePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2528
2549
  break;
2529
2550
  // valueQuantity
2530
2551
  case "valueQuantity.value":
2531
- targetData["value"] = column.text?.div ?? "";
2552
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2532
2553
  targetData["valueType"] = "valueQuantity";
2533
2554
  break;
2534
2555
  case "valueQuantity.unit":
2535
- targetData["unit"] = column.text?.div ?? "";
2556
+ targetData["unit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2536
2557
  break;
2537
2558
  // valueCodeableConcept
2538
2559
  case "valueCodeableConcept.text":
2539
- targetData["value"] = column.text?.div ?? "";
2560
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2540
2561
  targetData["valueType"] = "valueCodeableConcept";
2541
2562
  break;
2542
2563
  case "valueCodeableConcept.coding.display":
2543
2564
  if (!targetData["value"]) {
2544
- targetData["value"] = column.text?.div ?? "";
2565
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2545
2566
  targetData["valueType"] = "valueCodeableConcept";
2546
2567
  }
2547
2568
  break;
2548
2569
  // valueString
2549
2570
  case "valueString":
2550
- targetData["value"] = column.text?.div ?? "";
2571
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2551
2572
  targetData["valueType"] = "valueString";
2552
2573
  break;
2553
2574
  // valueBoolean
2554
2575
  case "valueBoolean":
2555
- targetData["value"] = column.text?.div ?? "";
2576
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2556
2577
  targetData["valueType"] = "valueBoolean";
2557
2578
  break;
2558
2579
  // valueInteger
2559
2580
  case "valueInteger":
2560
- targetData["value"] = column.text?.div ?? "";
2581
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2561
2582
  targetData["valueType"] = "valueInteger";
2562
2583
  break;
2563
2584
  // valueDateTime
2564
2585
  case "valueDateTime":
2565
- targetData["value"] = column.text?.div ?? "";
2586
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2566
2587
  targetData["valueType"] = "valueDateTime";
2567
2588
  break;
2568
2589
  // valuePeriod
2569
2590
  case "valuePeriod.start":
2570
- targetData["valuePeriodStart"] = column.text?.div ?? "";
2591
+ targetData["valuePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2571
2592
  targetData["valueType"] = "valuePeriod";
2572
2593
  break;
2573
2594
  case "valuePeriod.end":
2574
- targetData["valuePeriodEnd"] = column.text?.div ?? "";
2595
+ targetData["valuePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2575
2596
  targetData["valueType"] = "valuePeriod";
2576
2597
  break;
2577
2598
  // valueTime
2578
2599
  case "valueTime":
2579
- targetData["value"] = column.text?.div ?? "";
2600
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2580
2601
  targetData["valueType"] = "valueTime";
2581
2602
  break;
2582
2603
  // valueSampledData
2583
2604
  case "valueSampledData.origin.value":
2584
- targetData["sampledDataOriginValue"] = column.text?.div ?? "";
2605
+ targetData["sampledDataOriginValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2585
2606
  targetData["valueType"] = "valueSampledData";
2586
2607
  break;
2587
2608
  case "valueSampledData.origin.unit":
2588
- targetData["sampledDataOriginUnit"] = column.text?.div ?? "";
2609
+ targetData["sampledDataOriginUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2589
2610
  break;
2590
2611
  case "valueSampledData.period":
2591
- targetData["sampledDataPeriod"] = column.text?.div ?? "";
2612
+ targetData["sampledDataPeriod"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2592
2613
  break;
2593
2614
  case "valueSampledData.factor":
2594
- targetData["sampledDataFactor"] = column.text?.div ?? "";
2615
+ targetData["sampledDataFactor"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2595
2616
  break;
2596
2617
  case "valueSampledData.lowerLimit":
2597
- targetData["sampledDataLowerLimit"] = column.text?.div ?? "";
2618
+ targetData["sampledDataLowerLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2598
2619
  break;
2599
2620
  case "valueSampledData.upperLimit":
2600
- targetData["sampledDataUpperLimit"] = column.text?.div ?? "";
2621
+ targetData["sampledDataUpperLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2601
2622
  break;
2602
2623
  case "valueSampledData.data":
2603
- targetData["sampledDataData"] = column.text?.div ?? "";
2624
+ targetData["sampledDataData"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2604
2625
  break;
2605
2626
  // valueRange
2606
2627
  case "valueRange.low.value":
2607
- targetData["valueRangeLowValue"] = column.text?.div ?? "";
2628
+ targetData["valueRangeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2608
2629
  targetData["valueType"] = "valueRange";
2609
2630
  break;
2610
2631
  case "valueRange.low.unit":
2611
- targetData["valueRangeLowUnit"] = column.text?.div ?? "";
2632
+ targetData["valueRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2612
2633
  break;
2613
2634
  case "valueRange.high.value":
2614
- targetData["valueRangeHighValue"] = column.text?.div ?? "";
2635
+ targetData["valueRangeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2615
2636
  break;
2616
2637
  case "valueRange.high.unit":
2617
- targetData["valueRangeHighUnit"] = column.text?.div ?? "";
2638
+ targetData["valueRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2618
2639
  break;
2619
2640
  // valueRatio
2620
2641
  case "valueRatio.numerator.value":
2621
- targetData["valueRatioNumeratorValue"] = column.text?.div ?? "";
2642
+ targetData["valueRatioNumeratorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2622
2643
  targetData["valueType"] = "valueRatio";
2623
2644
  break;
2624
2645
  case "valueRatio.numerator.unit":
2625
- targetData["valueRatioNumeratorUnit"] = column.text?.div ?? "";
2646
+ targetData["valueRatioNumeratorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2626
2647
  break;
2627
2648
  case "valueRatio.denominator.value":
2628
- targetData["valueRatioDenominatorValue"] = column.text?.div ?? "";
2649
+ targetData["valueRatioDenominatorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2629
2650
  break;
2630
2651
  case "valueRatio.denominator.unit":
2631
- targetData["valueRatioDenominatorUnit"] = column.text?.div ?? "";
2652
+ targetData["valueRatioDenominatorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2632
2653
  break;
2633
2654
  // referenceRange
2634
2655
  case "referenceRange.low.value":
2635
- targetData["referenceRangeLow"] = column.text?.div ?? "";
2656
+ targetData["referenceRangeLow"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2636
2657
  break;
2637
2658
  case "referenceRange.low.unit":
2638
- targetData["referenceRangeLowUnit"] = column.text?.div ?? "";
2659
+ targetData["referenceRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2639
2660
  break;
2640
2661
  case "referenceRange.high.value":
2641
- targetData["referenceRangeHigh"] = column.text?.div ?? "";
2662
+ targetData["referenceRangeHigh"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2642
2663
  break;
2643
2664
  case "referenceRange.high.unit":
2644
- targetData["referenceRangeHighUnit"] = column.text?.div ?? "";
2665
+ targetData["referenceRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2645
2666
  break;
2646
2667
  case "referenceRange.age.low.value":
2647
- targetData["referenceRangeAgeLowValue"] = column.text?.div ?? "";
2668
+ targetData["referenceRangeAgeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2648
2669
  break;
2649
2670
  case "referenceRange.age.low.unit":
2650
- targetData["referenceRangeAgeLowUnit"] = column.text?.div ?? "";
2671
+ targetData["referenceRangeAgeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2651
2672
  break;
2652
2673
  case "referenceRange.age.high.value":
2653
- targetData["referenceRangeAgeHighValue"] = column.text?.div ?? "";
2674
+ targetData["referenceRangeAgeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2654
2675
  break;
2655
2676
  case "referenceRange.age.high.unit":
2656
- targetData["referenceRangeAgeHighUnit"] = column.text?.div ?? "";
2677
+ targetData["referenceRangeAgeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2657
2678
  break;
2658
2679
  default:
2659
2680
  break;
@@ -2706,28 +2727,28 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2706
2727
  for (const componentSection of columnData.section) {
2707
2728
  const componentData = {};
2708
2729
  for (const nestedColumn of componentSection.section ?? []) {
2709
- this.extractSummaryObservationFields(nestedColumn, componentData);
2730
+ this.extractSummaryObservationFields(nestedColumn, componentData, templateUtilities);
2710
2731
  }
2711
2732
  if (Object.keys(componentData).length > 0) {
2712
2733
  components.push(componentData);
2713
2734
  }
2714
2735
  }
2715
2736
  } else {
2716
- this.extractSummaryObservationFields(columnData, data);
2737
+ this.extractSummaryObservationFields(columnData, data, templateUtilities);
2717
2738
  }
2718
2739
  } else if (resourceItem.title === "DiagnosticReportLab Summary Grouped by DiagnosticReport|Lab Code") {
2719
2740
  switch (columnData.title) {
2720
2741
  case "Diagnostic Report Name":
2721
- data["report"] = columnData.text?.div ?? "";
2742
+ data["report"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2722
2743
  break;
2723
2744
  case "Performer":
2724
- data["performer"] = columnData.text?.div ?? "";
2745
+ data["performer"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2725
2746
  break;
2726
2747
  case "Issued Date":
2727
- data["issued"] = columnData.text?.div ?? "";
2748
+ data["issued"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2728
2749
  break;
2729
2750
  case "Status":
2730
- data["status"] = columnData.text?.div ?? "";
2751
+ data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2731
2752
  break;
2732
2753
  default:
2733
2754
  break;
@@ -2752,8 +2773,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2752
2773
  observationhtml += `
2753
2774
  <tr>
2754
2775
  <td>${componentCode}</td>
2755
- <td>${component["formattedValue"] ?? "-"}</td>
2756
- <td>${component["referenceRange"]?.trim() ?? "-"}</td>
2776
+ <td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? "-"}</td>
2777
+ <td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? "-"}</td>
2757
2778
  <td>${date ?? "-"}</td>
2758
2779
  </tr>`;
2759
2780
  }
@@ -2766,8 +2787,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2766
2787
  observationhtml += `
2767
2788
  <tr>
2768
2789
  <td>${data["code"] ?? "-"}</td>
2769
- <td>${data["formattedValue"] ?? "-"}</td>
2770
- <td>${data["referenceRange"]?.trim() ?? "-"}</td>
2790
+ <td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? "-"}</td>
2791
+ <td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? "-"}</td>
2771
2792
  <td>${date ?? "-"}</td>
2772
2793
  </tr>`;
2773
2794
  }
@@ -2927,7 +2948,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2927
2948
  <tbody>`;
2928
2949
  const observationAdded = /* @__PURE__ */ new Set();
2929
2950
  for (const obs of observations) {
2930
- const obsCode = templateUtilities.codeableConcept(obs.code);
2951
+ const obsCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code));
2931
2952
  if (!observationAdded.has(obsCode)) {
2932
2953
  observationAdded.add(obsCode);
2933
2954
  html += `
@@ -2966,7 +2987,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2966
2987
  <tbody>`;
2967
2988
  const diagnosticReportAdded = /* @__PURE__ */ new Set();
2968
2989
  for (const report of reports) {
2969
- const reportName = templateUtilities.codeableConcept(report.code);
2990
+ const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(report.code));
2970
2991
  if (!diagnosticReportAdded.has(reportName)) {
2971
2992
  diagnosticReportAdded.add(reportName);
2972
2993
  let resultCount = "";
@@ -3080,7 +3101,7 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3080
3101
  const proc = resourceItem;
3081
3102
  html += `
3082
3103
  <tr id="${templateUtilities.narrativeLinkId(proc)}">
3083
- <td>${templateUtilities.codeableConcept(proc.code, "display")}</td>
3104
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(proc.code, "display"))}</td>
3084
3105
  <td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
3085
3106
  <td>${proc.performedDateTime ? templateUtilities.renderTime(proc.performedDateTime, timezone) : proc.performedPeriod ? templateUtilities.renderPeriod(proc.performedPeriod, timezone) : ""}</td>
3086
3107
  </tr>`;
@@ -3132,7 +3153,7 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
3132
3153
  for (const obs of observations) {
3133
3154
  html += `
3134
3155
  <tr id="${templateUtilities.narrativeLinkId(obs)}">
3135
- <td>${templateUtilities.codeableConcept(obs.code)}</td>
3156
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code))}</td>
3136
3157
  <td>${templateUtilities.extractObservationValue(obs)}</td>
3137
3158
  <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
3138
3159
  <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
@@ -3177,7 +3198,7 @@ var PastHistoryOfIllnessTemplate = class {
3177
3198
  <tbody>`;
3178
3199
  const addedConditionCodes = /* @__PURE__ */ new Set();
3179
3200
  for (const cond of resolvedConditions) {
3180
- const conditionCode = templateUtilities.codeableConcept(cond.code);
3201
+ const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
3181
3202
  if (!addedConditionCodes.has(conditionCode)) {
3182
3203
  addedConditionCodes.add(conditionCode);
3183
3204
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
@@ -3263,7 +3284,7 @@ var PlanOfCareTemplate = class {
3263
3284
  const data = {};
3264
3285
  for (const columnData of rowData.section ?? []) {
3265
3286
  if (columnData.title) {
3266
- data[columnData.title] = columnData.text?.div ?? "";
3287
+ data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3267
3288
  }
3268
3289
  }
3269
3290
  if (data["status"] !== "active") {
@@ -3339,7 +3360,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
3339
3360
  <tbody>`;
3340
3361
  const addedConditionCodes = /* @__PURE__ */ new Set();
3341
3362
  for (const cond of activeConditions) {
3342
- const conditionCode = templateUtilities.codeableConcept(cond.code);
3363
+ const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
3343
3364
  if (!addedConditionCodes.has(conditionCode)) {
3344
3365
  addedConditionCodes.add(conditionCode);
3345
3366
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
@@ -3384,7 +3405,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
3384
3405
  if (impression.finding && impression.finding.length > 0) {
3385
3406
  findingsHtml = "<ul>";
3386
3407
  for (const finding of impression.finding) {
3387
- const findingText = finding.itemCodeableConcept ? templateUtilities.codeableConcept(finding.itemCodeableConcept) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
3408
+ const findingText = finding.itemCodeableConcept ? templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(finding.itemCodeableConcept)) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
3388
3409
  const cause = finding.basis || "";
3389
3410
  findingsHtml += `<li>${findingText}${cause ? ` - ${cause}` : ""}</li>`;
3390
3411
  }
@@ -3445,9 +3466,9 @@ var PregnancyTemplate = class _PregnancyTemplate {
3445
3466
  const obs = resource;
3446
3467
  html += `
3447
3468
  <tr id="${templateUtilities.narrativeLinkId(obs)}">
3448
- <td>${templateUtilities.extractPregnancyStatus(obs)}</td>
3469
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.extractPregnancyStatus(obs))}</td>
3449
3470
  <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
3450
- <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3471
+ <td>${obs.effectiveDateTime ? templateUtilities.renderTextAsHtml(templateUtilities.renderTime(obs.effectiveDateTime, timezone)) : obs.effectivePeriod ? templateUtilities.renderTextAsHtml(templateUtilities.renderPeriod(obs.effectivePeriod, timezone)) : ""}</td>
3451
3472
  </tr>`;
3452
3473
  }
3453
3474
  html += `
@@ -3497,7 +3518,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
3497
3518
  const consent = resourceItem;
3498
3519
  html += `
3499
3520
  <tr id="${templateUtilities.narrativeLinkId(consent)}">
3500
- <td>${templateUtilities.codeableConcept(consent.scope, "display")}</td>
3521
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(consent.scope, "display"))}</td>
3501
3522
  <td>${consent.status || ""}</td>
3502
3523
  <td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
3503
3524
  <td>${consent.dateTime || ""}</td>
@@ -3518,16 +3539,18 @@ var TypeScriptTemplateMapper = class {
3518
3539
  * @param resources - FHIR resources
3519
3540
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
3520
3541
  * @param useSectionSummary - Whether to use the section summary for narrative generation
3542
+ * @param now - Optional current date to use for generating relative dates in the narrative
3521
3543
  * @returns HTML string for rendering
3522
3544
  */
3523
- static generateNarrative(section, resources, timezone, useSectionSummary = false) {
3545
+ static generateNarrative(section, resources, timezone, useSectionSummary = false, now) {
3524
3546
  const templateClass = this.sectionToTemplate[section];
3525
3547
  if (!templateClass) {
3526
3548
  throw new Error(`No template found for section: ${section}`);
3527
3549
  }
3528
3550
  return useSectionSummary ? templateClass.generateSummaryNarrative(
3529
3551
  resources,
3530
- timezone
3552
+ timezone,
3553
+ now
3531
3554
  ) : templateClass.generateNarrative(resources, timezone);
3532
3555
  }
3533
3556
  };
@@ -3585,14 +3608,15 @@ var NarrativeGenerator = class {
3585
3608
  * @param resources - Array of domain resources
3586
3609
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
3587
3610
  * @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
3611
+ * @param now - Optional date parameter
3588
3612
  * @returns Generated HTML content or undefined if no resources
3589
3613
  */
3590
- static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false) {
3614
+ static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false, now) {
3591
3615
  if (!resources || resources.length === 0) {
3592
3616
  return void 0;
3593
3617
  }
3594
3618
  try {
3595
- const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary);
3619
+ const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary, now);
3596
3620
  if (!content) {
3597
3621
  return void 0;
3598
3622
  }
@@ -3614,8 +3638,8 @@ var NarrativeGenerator = class {
3614
3638
  const options = aggressive ? AGGRESSIVE_MINIFY_OPTIONS : DEFAULT_MINIFY_OPTIONS;
3615
3639
  return await htmlMinify(html, options);
3616
3640
  } catch (error) {
3617
- console.warn("HTML minification failed", error);
3618
- return html;
3641
+ console.warn("HTML minification failed", error, html);
3642
+ return `${error instanceof Error ? error.message : String(error)}`;
3619
3643
  }
3620
3644
  }
3621
3645
  /**
@@ -3644,10 +3668,11 @@ var NarrativeGenerator = class {
3644
3668
  * @param timezone - Optional timezone to use for date formatting
3645
3669
  * @param minify - Whether to minify the HTML content (default: true)
3646
3670
  * @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
3671
+ * @param now - Optional date parameter
3647
3672
  * @returns Promise that resolves to a FHIR Narrative object or undefined if no resources
3648
3673
  */
3649
- static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false) {
3650
- const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary);
3674
+ static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false, now) {
3675
+ const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary, now);
3651
3676
  if (!content) {
3652
3677
  return void 0;
3653
3678
  }
@@ -3805,6 +3830,12 @@ var ComprehensiveIPSCompositionBuilder = class {
3805
3830
  if (sectionType === "Patient" /* PATIENT */) {
3806
3831
  continue;
3807
3832
  }
3833
+ const summaryIPSCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryIPSCompositionFilterForSection(sectionType) : void 0;
3834
+ const sectionIPSSummary = summaryIPSCompositionFilter ? resources.filter((resource) => summaryIPSCompositionFilter(resource)) : [];
3835
+ if (sectionIPSSummary.length > 0) {
3836
+ await this.makeSectionFromSummaryAsync(sectionType, sectionIPSSummary, resources, timezone);
3837
+ continue;
3838
+ }
3808
3839
  const summaryCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryCompositionFilterForSection(sectionType) : void 0;
3809
3840
  const sectionSummary = summaryCompositionFilter ? resources.filter((resource) => summaryCompositionFilter(resource)) : [];
3810
3841
  if (sectionSummary.length > 0) {
@@ -3824,8 +3855,9 @@ var ComprehensiveIPSCompositionBuilder = class {
3824
3855
  * @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
3825
3856
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
3826
3857
  * @param patientId - Optional patient ID to use as primary patient for composition reference
3858
+ * @param now - Optional current date to use for composition date (defaults to new Date())
3827
3859
  */
3828
- async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId) {
3860
+ async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId, now) {
3829
3861
  if (baseUrl.endsWith("/")) {
3830
3862
  baseUrl = baseUrl.slice(0, -1);
3831
3863
  }
@@ -3852,20 +3884,22 @@ var ComprehensiveIPSCompositionBuilder = class {
3852
3884
  // Assuming patient is also a practitioner for simplicity
3853
3885
  display: authorOrganizationName
3854
3886
  }],
3855
- date: (/* @__PURE__ */ new Date()).toISOString(),
3887
+ date: (now || /* @__PURE__ */ new Date()).toISOString(),
3856
3888
  title: "International Patient Summary",
3857
3889
  section: this.sections,
3858
3890
  text: await NarrativeGenerator.generateNarrativeAsync(
3859
3891
  "Patient" /* PATIENT */,
3860
3892
  this.patients,
3861
3893
  timezone,
3862
- true
3894
+ true,
3895
+ false,
3896
+ now
3863
3897
  )
3864
3898
  };
3865
3899
  const bundle = {
3866
3900
  resourceType: "Bundle",
3867
3901
  type: "document",
3868
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3902
+ timestamp: (now || /* @__PURE__ */ new Date()).toISOString(),
3869
3903
  identifier: {
3870
3904
  "system": "urn:ietf:rfc:3986",
3871
3905
  "value": "urn:uuid:4dcfd353-49fd-4ab0-b521-c8d57ced74d6"