@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.cjs CHANGED
@@ -161,6 +161,9 @@ var IPSSectionSummaryCompositionFilter = {
161
161
  // [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)),
162
162
  ["HistoryOfProceduresSection" /* PROCEDURES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => c.system === IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM && c.code === "procedure_summary_document")
163
163
  };
164
+ var IPSSectionSummaryIPSCompositionFilter = {
165
+ ["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")
166
+ };
164
167
  var IPSSectionResourceHelper = class {
165
168
  static getResourceFilterForSection(section) {
166
169
  return IPSSectionResourceFilters[section];
@@ -173,6 +176,9 @@ var IPSSectionResourceHelper = class {
173
176
  static getSummaryCompositionFilterForSection(section) {
174
177
  return IPSSectionSummaryCompositionFilter[section];
175
178
  }
179
+ static getSummaryIPSCompositionFilterForSection(section) {
180
+ return IPSSectionSummaryIPSCompositionFilter[section];
181
+ }
176
182
  };
177
183
 
178
184
  // src/narratives/templates/typescript/TemplateUtilities.ts
@@ -248,7 +254,7 @@ var TemplateUtilities = class {
248
254
  renderOrganization(orgRef) {
249
255
  const organization = orgRef && this.resolveReference(orgRef);
250
256
  if (organization && organization.resourceType === "Organization" && organization.name) {
251
- return organization.name;
257
+ return this.renderTextAsHtml(organization.name);
252
258
  }
253
259
  return "";
254
260
  }
@@ -260,7 +266,7 @@ var TemplateUtilities = class {
260
266
  renderVaccineManufacturer(immunization) {
261
267
  const organization = immunization.manufacturer && this.resolveReference(immunization.manufacturer);
262
268
  if (organization && organization.resourceType === "Organization" && organization.name) {
263
- return organization.name;
269
+ return this.renderTextAsHtml(organization.name);
264
270
  }
265
271
  return "";
266
272
  }
@@ -299,7 +305,7 @@ var TemplateUtilities = class {
299
305
  */
300
306
  renderMedicationCode(medication) {
301
307
  if (medication && medication.code) {
302
- return this.codeableConcept(medication.code, "display");
308
+ return this.renderTextAsHtml(this.codeableConcept(medication.code, "display"));
303
309
  }
304
310
  return "";
305
311
  }
@@ -310,7 +316,7 @@ var TemplateUtilities = class {
310
316
  */
311
317
  renderDoseNumber(doseNumber) {
312
318
  if (doseNumber && doseNumber.value !== void 0) {
313
- return doseNumber.value.toString();
319
+ return this.renderTextAsHtml(doseNumber.value.toString());
314
320
  }
315
321
  return "";
316
322
  }
@@ -321,7 +327,7 @@ var TemplateUtilities = class {
321
327
  */
322
328
  renderValueUnit(value) {
323
329
  if (value && value.constructor?.name === "Quantity" && value.unit) {
324
- return value.unit;
330
+ return this.renderTextAsHtml(value.unit);
325
331
  }
326
332
  return "";
327
333
  }
@@ -387,7 +393,7 @@ var TemplateUtilities = class {
387
393
  * @returns Comma-separated string of items
388
394
  */
389
395
  safeConcat(list, attr) {
390
- return this.concat(list || [], attr);
396
+ return this.renderTextAsHtml(this.concat(list || [], attr));
391
397
  }
392
398
  /**
393
399
  * Concatenates text from a list of CodeableConcept objects
@@ -404,7 +410,7 @@ var TemplateUtilities = class {
404
410
  items.push(item.text);
405
411
  }
406
412
  }
407
- return items.join(", ");
413
+ return this.renderTextAsHtml(items.join(", "));
408
414
  }
409
415
  /**
410
416
  * Concatenates reaction manifestations
@@ -425,7 +431,7 @@ var TemplateUtilities = class {
425
431
  }
426
432
  }
427
433
  }
428
- return texts.join(", ");
434
+ return this.renderTextAsHtml(texts.join(", "));
429
435
  }
430
436
  /**
431
437
  * Concatenates dose numbers
@@ -442,7 +448,7 @@ var TemplateUtilities = class {
442
448
  doseNumbers.push(item.doseNumberPositiveInt.toString());
443
449
  }
444
450
  }
445
- return doseNumbers.join(", ");
451
+ return this.renderTextAsHtml(doseNumbers.join(", "));
446
452
  }
447
453
  /**
448
454
  * Concatenates dosage routes
@@ -459,7 +465,7 @@ var TemplateUtilities = class {
459
465
  routes.push(item.route.text);
460
466
  }
461
467
  }
462
- return routes.join(", ");
468
+ return this.renderTextAsHtml(routes.join(", "));
463
469
  }
464
470
  /**
465
471
  * Returns the first item from a list of CodeableConcept objects
@@ -468,7 +474,7 @@ var TemplateUtilities = class {
468
474
  */
469
475
  firstFromCodeableConceptList(list) {
470
476
  if (list && Array.isArray(list) && list[0]) {
471
- return this.codeableConcept(list[0], "display");
477
+ return this.renderTextAsHtml(this.codeableConcept(list[0], "display"));
472
478
  }
473
479
  return "";
474
480
  }
@@ -487,7 +493,7 @@ var TemplateUtilities = class {
487
493
  texts.push(item.text);
488
494
  }
489
495
  }
490
- return texts.join(", ");
496
+ return this.renderTextAsHtml(texts.join(", "));
491
497
  }
492
498
  /**
493
499
  * Renders component codes
@@ -819,9 +825,11 @@ var TemplateUtilities = class {
819
825
  return "";
820
826
  }
821
827
  /**
822
- * Renders text as HTML, escaping special characters and replacing newlines with <br />
823
- * @param text - The text to render
824
- * @private
828
+ * Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
829
+ * This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
830
+ * and to preserve formatting. Use this in templates or UI components that need to safely display multi-line or arbitrary text.
831
+ * @param text - The text to render as HTML
832
+ * @returns The HTML-safe string with newlines converted to <br />
825
833
  */
826
834
  renderTextAsHtml(text) {
827
835
  if (!text || text.trim() === "") {
@@ -885,7 +893,7 @@ var TemplateUtilities = class {
885
893
  dateTime = import_luxon.DateTime.fromISO(String(dateValue));
886
894
  }
887
895
  if (!dateTime.isValid) {
888
- return String(dateValue);
896
+ return this.renderTextAsHtml(String(dateValue));
889
897
  }
890
898
  if (dateOnly) {
891
899
  dateTime = dateTime.toUTC();
@@ -901,9 +909,9 @@ var TemplateUtilities = class {
901
909
  hour12: true,
902
910
  timeZoneName: "short"
903
911
  };
904
- return dateTime.toLocaleString(formatOptions);
912
+ return this.renderTextAsHtml(dateTime.toLocaleString(formatOptions));
905
913
  } catch {
906
- return String(dateValue);
914
+ return this.renderTextAsHtml(String(dateValue));
907
915
  }
908
916
  }
909
917
  /**
@@ -1607,7 +1615,7 @@ var PatientTemplate = class _PatientTemplate {
1607
1615
  const uniqueLanguages = /* @__PURE__ */ new Set();
1608
1616
  const preferredLanguages = /* @__PURE__ */ new Set();
1609
1617
  patient.communication.forEach((comm) => {
1610
- const language = templateUtilities.codeableConcept(comm.language);
1618
+ const language = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(comm.language));
1611
1619
  if (language) {
1612
1620
  if (comm.preferred) {
1613
1621
  preferredLanguages.add(language);
@@ -1665,13 +1673,13 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1665
1673
  for (const columnData of rowData.section ?? []) {
1666
1674
  switch (columnData.title) {
1667
1675
  case "Allergen Name":
1668
- data["allergen"] = columnData.text?.div ?? "";
1676
+ data["allergen"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1669
1677
  break;
1670
1678
  case "Criticality":
1671
- data["criticality"] = columnData.text?.div ?? "";
1679
+ data["criticality"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1672
1680
  break;
1673
1681
  case "Recorded Date":
1674
- data["recordedDate"] = columnData.text?.div ?? "";
1682
+ data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1675
1683
  break;
1676
1684
  default:
1677
1685
  break;
@@ -1792,11 +1800,11 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1792
1800
  for (const allergy of allergies) {
1793
1801
  html += `
1794
1802
  <tr id="${templateUtilities.narrativeLinkId(allergy.extension)}">
1795
- <td class="Name"><span class="AllergenName">${templateUtilities.codeableConcept(allergy.code)}</span></td>
1796
- <td class="Status">${templateUtilities.codeableConcept(allergy.clinicalStatus) || "-"}</td>
1797
- <td class="Category">${templateUtilities.safeConcat(allergy.category) || "-"}</td>
1798
- <td class="Reaction">${templateUtilities.concatReactionManifestation(allergy.reaction) || "-"}</td>
1799
- <td class="OnsetDate">${templateUtilities.renderTime(allergy.onsetDateTime, timezone) || "-"}</td>
1803
+ <td class="Name"><span class="AllergenName">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.code))}</span></td>
1804
+ <td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(allergy.clinicalStatus)) || "-"}</td>
1805
+ <td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || "-"}</td>
1806
+ <td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || "-"}</td>
1807
+ <td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || "-"}</td>
1800
1808
  <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
1801
1809
  if (includeResolved) {
1802
1810
  let endDate = "-";
@@ -1809,7 +1817,7 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1809
1817
  }
1810
1818
  }
1811
1819
  html += `
1812
- <td class="ResolvedDate">${endDate}</td>`;
1820
+ <td class="ResolvedDate">${templateUtilities.renderTextAsHtml(endDate)}</td>`;
1813
1821
  }
1814
1822
  html += `</tr>`;
1815
1823
  }
@@ -1832,17 +1840,21 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1832
1840
  * Generate HTML narrative for Medication resources using summary
1833
1841
  * @param resources - FHIR Composition resources
1834
1842
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1843
+ * @param now - Optional current date to use for calculations (defaults to new Date())
1835
1844
  * @returns HTML string for rendering
1836
1845
  */
1837
- generateSummaryNarrative(resources, timezone) {
1846
+ generateSummaryNarrative(resources, timezone, now) {
1838
1847
  const templateUtilities = new TemplateUtilities(resources);
1839
1848
  let isSummaryCreated = false;
1849
+ const currentDate = now || /* @__PURE__ */ new Date();
1850
+ const twelveMonthsAgo = new Date(currentDate.getFullYear(), currentDate.getMonth() - 12, currentDate.getDate());
1840
1851
  let html = `
1841
1852
  <div>
1842
1853
  <table>
1843
1854
  <thead>
1844
1855
  <tr>
1845
1856
  <th>Medication</th>
1857
+ <th>Status</th>
1846
1858
  <th>Sig</th>
1847
1859
  <th>Days of Supply</th>
1848
1860
  <th>Refills</th>
@@ -1856,40 +1868,48 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1856
1868
  for (const columnData of rowData.section ?? []) {
1857
1869
  switch (columnData.title) {
1858
1870
  case "Medication Name":
1859
- data["medication"] = columnData.text?.div ?? "";
1871
+ data["medication"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1860
1872
  break;
1861
1873
  case "Status":
1862
- data["status"] = columnData.text?.div ?? "";
1874
+ data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1863
1875
  break;
1864
1876
  case "Prescriber Instruction":
1865
- data["sig-prescriber"] = columnData.text?.div ?? "";
1877
+ data["sig-prescriber"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1866
1878
  break;
1867
1879
  case "Pharmacy Instruction":
1868
- data["sig-pharmacy"] = columnData.text?.div ?? "";
1880
+ data["sig-pharmacy"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1869
1881
  break;
1870
1882
  case "Days Of Supply":
1871
- data["daysOfSupply"] = columnData.text?.div ?? "";
1883
+ data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1872
1884
  break;
1873
1885
  case "Refills Remaining":
1874
- data["refills"] = columnData.text?.div ?? "";
1886
+ data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1875
1887
  break;
1876
1888
  case "Authored On Date":
1877
- data["startDate"] = columnData.text?.div ?? "";
1889
+ data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1878
1890
  break;
1879
1891
  default:
1880
1892
  break;
1881
1893
  }
1882
1894
  }
1883
- if (data["status"] === "active") {
1895
+ let startDateObj;
1896
+ if (data["startDate"]) {
1897
+ startDateObj = new Date(data["startDate"]);
1898
+ if (isNaN(startDateObj.getTime())) {
1899
+ startDateObj = void 0;
1900
+ }
1901
+ }
1902
+ if (data["status"] === "active" || startDateObj && startDateObj >= twelveMonthsAgo) {
1884
1903
  isSummaryCreated = true;
1885
1904
  html += `
1886
- <tr>
1887
- <td>${data["medication"]}</td>
1888
- <td>${data["sig-prescriber"] || data["sig-pharmacy"]}</td>
1889
- <td>${data["daysOfSupply"]}</td>
1890
- <td>${data["refills"]}</td>
1891
- <td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
1892
- </tr>`;
1905
+ <tr>
1906
+ <td>${templateUtilities.renderTextAsHtml(data["medication"])}</td>
1907
+ <td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
1908
+ <td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
1909
+ <td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
1910
+ <td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
1911
+ <td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
1912
+ </tr>`;
1893
1913
  }
1894
1914
  }
1895
1915
  }
@@ -2111,13 +2131,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2111
2131
  for (const columnData of rowData.section ?? []) {
2112
2132
  switch (columnData.title) {
2113
2133
  case "Immunization Name":
2114
- data["immunization"] = columnData.text?.div ?? "";
2134
+ data["immunization"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2115
2135
  break;
2116
2136
  case "Status":
2117
- data["status"] = columnData.text?.div ?? "";
2137
+ data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2118
2138
  break;
2119
2139
  case "occurrenceDateTime":
2120
- data["occurrenceDateTime"] = columnData.text?.div ?? "";
2140
+ data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2121
2141
  break;
2122
2142
  default:
2123
2143
  break;
@@ -2168,7 +2188,7 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2168
2188
  const imm = resourceItem;
2169
2189
  html += `
2170
2190
  <tr id="${templateUtilities.narrativeLinkId(imm)}">
2171
- <td>${templateUtilities.codeableConcept(imm.vaccineCode)}</td>
2191
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(imm.vaccineCode))}</td>
2172
2192
  <td>${imm.status || ""}</td>
2173
2193
  <td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
2174
2194
  <td>${templateUtilities.renderVaccineManufacturer(imm)}</td>
@@ -2224,7 +2244,7 @@ var ProblemListTemplate = class _ProblemListTemplate {
2224
2244
  <tbody>`;
2225
2245
  const addedConditionCodes = /* @__PURE__ */ new Set();
2226
2246
  for (const cond of activeConditions) {
2227
- const conditionCode = templateUtilities.codeableConcept(cond.code);
2247
+ const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
2228
2248
  if (!addedConditionCodes.has(conditionCode)) {
2229
2249
  addedConditionCodes.add(conditionCode);
2230
2250
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
@@ -2284,7 +2304,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2284
2304
  const vitalData = {};
2285
2305
  for (const component of columnData.section?.[0]?.section ?? []) {
2286
2306
  if (component.title) {
2287
- vitalData[component.title] = component.text?.div ?? "";
2307
+ vitalData[component.title] = templateUtilities.renderTextAsHtml(component.text?.div ?? "");
2288
2308
  }
2289
2309
  }
2290
2310
  const vitalValue = templateUtilities.extractObservationSummaryValue(
@@ -2296,7 +2316,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2296
2316
  data[dataKey] = vitalValue;
2297
2317
  }
2298
2318
  }
2299
- data[columnTitle] = columnData.text?.div ?? "";
2319
+ data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2300
2320
  }
2301
2321
  }
2302
2322
  isSummaryCreated = true;
@@ -2346,7 +2366,7 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2346
2366
  for (const obs of observations) {
2347
2367
  html += `
2348
2368
  <tr id="${templateUtilities.narrativeLinkId(obs)}">
2349
- <td>${templateUtilities.codeableConcept(obs.code, "display")}</td>
2369
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code, "display"))}</td>
2350
2370
  <td>${templateUtilities.extractObservationValue(obs)}</td>
2351
2371
  <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
2352
2372
  <td>${templateUtilities.firstFromCodeableConceptList(obs.interpretation)}</td>
@@ -2400,10 +2420,10 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
2400
2420
  for (const dus of deviceStatements) {
2401
2421
  html += `
2402
2422
  <tr id="${templateUtilities.narrativeLinkId(dus)}">
2403
- <td>${templateUtilities.renderDevice(dus.device)}</td>
2404
- <td>${dus.status || ""}</td>
2423
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device))}</td>
2424
+ <td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
2405
2425
  <td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
2406
- <td>${templateUtilities.renderRecorded(dus.recordedOn, timezone)}</td>
2426
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
2407
2427
  </tr>`;
2408
2428
  }
2409
2429
  html += `
@@ -2539,149 +2559,150 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2539
2559
  * Helper function to extract observation field data
2540
2560
  * @param column - Column data from the summary
2541
2561
  * @param targetData - Record to populate with extracted data
2562
+ * @param templateUtilities - Instance of TemplateUtilities for utility functions
2542
2563
  */
2543
- extractSummaryObservationFields(column, targetData) {
2564
+ extractSummaryObservationFields(column, targetData, templateUtilities) {
2544
2565
  switch (column.title) {
2545
2566
  case "Labs Name":
2546
- targetData["code"] = column.text?.div ?? "";
2567
+ targetData["code"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2547
2568
  break;
2548
2569
  case "effectiveDateTime":
2549
- targetData["effectiveDateTime"] = column.text?.div ?? "";
2570
+ targetData["effectiveDateTime"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2550
2571
  break;
2551
2572
  case "effectivePeriod.start":
2552
- targetData["effectivePeriodStart"] = column.text?.div ?? "";
2573
+ targetData["effectivePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2553
2574
  break;
2554
2575
  case "effectivePeriod.end":
2555
- targetData["effectivePeriodEnd"] = column.text?.div ?? "";
2576
+ targetData["effectivePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2556
2577
  break;
2557
2578
  // valueQuantity
2558
2579
  case "valueQuantity.value":
2559
- targetData["value"] = column.text?.div ?? "";
2580
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2560
2581
  targetData["valueType"] = "valueQuantity";
2561
2582
  break;
2562
2583
  case "valueQuantity.unit":
2563
- targetData["unit"] = column.text?.div ?? "";
2584
+ targetData["unit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2564
2585
  break;
2565
2586
  // valueCodeableConcept
2566
2587
  case "valueCodeableConcept.text":
2567
- targetData["value"] = column.text?.div ?? "";
2588
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2568
2589
  targetData["valueType"] = "valueCodeableConcept";
2569
2590
  break;
2570
2591
  case "valueCodeableConcept.coding.display":
2571
2592
  if (!targetData["value"]) {
2572
- targetData["value"] = column.text?.div ?? "";
2593
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2573
2594
  targetData["valueType"] = "valueCodeableConcept";
2574
2595
  }
2575
2596
  break;
2576
2597
  // valueString
2577
2598
  case "valueString":
2578
- targetData["value"] = column.text?.div ?? "";
2599
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2579
2600
  targetData["valueType"] = "valueString";
2580
2601
  break;
2581
2602
  // valueBoolean
2582
2603
  case "valueBoolean":
2583
- targetData["value"] = column.text?.div ?? "";
2604
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2584
2605
  targetData["valueType"] = "valueBoolean";
2585
2606
  break;
2586
2607
  // valueInteger
2587
2608
  case "valueInteger":
2588
- targetData["value"] = column.text?.div ?? "";
2609
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2589
2610
  targetData["valueType"] = "valueInteger";
2590
2611
  break;
2591
2612
  // valueDateTime
2592
2613
  case "valueDateTime":
2593
- targetData["value"] = column.text?.div ?? "";
2614
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2594
2615
  targetData["valueType"] = "valueDateTime";
2595
2616
  break;
2596
2617
  // valuePeriod
2597
2618
  case "valuePeriod.start":
2598
- targetData["valuePeriodStart"] = column.text?.div ?? "";
2619
+ targetData["valuePeriodStart"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2599
2620
  targetData["valueType"] = "valuePeriod";
2600
2621
  break;
2601
2622
  case "valuePeriod.end":
2602
- targetData["valuePeriodEnd"] = column.text?.div ?? "";
2623
+ targetData["valuePeriodEnd"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2603
2624
  targetData["valueType"] = "valuePeriod";
2604
2625
  break;
2605
2626
  // valueTime
2606
2627
  case "valueTime":
2607
- targetData["value"] = column.text?.div ?? "";
2628
+ targetData["value"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2608
2629
  targetData["valueType"] = "valueTime";
2609
2630
  break;
2610
2631
  // valueSampledData
2611
2632
  case "valueSampledData.origin.value":
2612
- targetData["sampledDataOriginValue"] = column.text?.div ?? "";
2633
+ targetData["sampledDataOriginValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2613
2634
  targetData["valueType"] = "valueSampledData";
2614
2635
  break;
2615
2636
  case "valueSampledData.origin.unit":
2616
- targetData["sampledDataOriginUnit"] = column.text?.div ?? "";
2637
+ targetData["sampledDataOriginUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2617
2638
  break;
2618
2639
  case "valueSampledData.period":
2619
- targetData["sampledDataPeriod"] = column.text?.div ?? "";
2640
+ targetData["sampledDataPeriod"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2620
2641
  break;
2621
2642
  case "valueSampledData.factor":
2622
- targetData["sampledDataFactor"] = column.text?.div ?? "";
2643
+ targetData["sampledDataFactor"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2623
2644
  break;
2624
2645
  case "valueSampledData.lowerLimit":
2625
- targetData["sampledDataLowerLimit"] = column.text?.div ?? "";
2646
+ targetData["sampledDataLowerLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2626
2647
  break;
2627
2648
  case "valueSampledData.upperLimit":
2628
- targetData["sampledDataUpperLimit"] = column.text?.div ?? "";
2649
+ targetData["sampledDataUpperLimit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2629
2650
  break;
2630
2651
  case "valueSampledData.data":
2631
- targetData["sampledDataData"] = column.text?.div ?? "";
2652
+ targetData["sampledDataData"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2632
2653
  break;
2633
2654
  // valueRange
2634
2655
  case "valueRange.low.value":
2635
- targetData["valueRangeLowValue"] = column.text?.div ?? "";
2656
+ targetData["valueRangeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2636
2657
  targetData["valueType"] = "valueRange";
2637
2658
  break;
2638
2659
  case "valueRange.low.unit":
2639
- targetData["valueRangeLowUnit"] = column.text?.div ?? "";
2660
+ targetData["valueRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2640
2661
  break;
2641
2662
  case "valueRange.high.value":
2642
- targetData["valueRangeHighValue"] = column.text?.div ?? "";
2663
+ targetData["valueRangeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2643
2664
  break;
2644
2665
  case "valueRange.high.unit":
2645
- targetData["valueRangeHighUnit"] = column.text?.div ?? "";
2666
+ targetData["valueRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2646
2667
  break;
2647
2668
  // valueRatio
2648
2669
  case "valueRatio.numerator.value":
2649
- targetData["valueRatioNumeratorValue"] = column.text?.div ?? "";
2670
+ targetData["valueRatioNumeratorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2650
2671
  targetData["valueType"] = "valueRatio";
2651
2672
  break;
2652
2673
  case "valueRatio.numerator.unit":
2653
- targetData["valueRatioNumeratorUnit"] = column.text?.div ?? "";
2674
+ targetData["valueRatioNumeratorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2654
2675
  break;
2655
2676
  case "valueRatio.denominator.value":
2656
- targetData["valueRatioDenominatorValue"] = column.text?.div ?? "";
2677
+ targetData["valueRatioDenominatorValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2657
2678
  break;
2658
2679
  case "valueRatio.denominator.unit":
2659
- targetData["valueRatioDenominatorUnit"] = column.text?.div ?? "";
2680
+ targetData["valueRatioDenominatorUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2660
2681
  break;
2661
2682
  // referenceRange
2662
2683
  case "referenceRange.low.value":
2663
- targetData["referenceRangeLow"] = column.text?.div ?? "";
2684
+ targetData["referenceRangeLow"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2664
2685
  break;
2665
2686
  case "referenceRange.low.unit":
2666
- targetData["referenceRangeLowUnit"] = column.text?.div ?? "";
2687
+ targetData["referenceRangeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2667
2688
  break;
2668
2689
  case "referenceRange.high.value":
2669
- targetData["referenceRangeHigh"] = column.text?.div ?? "";
2690
+ targetData["referenceRangeHigh"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2670
2691
  break;
2671
2692
  case "referenceRange.high.unit":
2672
- targetData["referenceRangeHighUnit"] = column.text?.div ?? "";
2693
+ targetData["referenceRangeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2673
2694
  break;
2674
2695
  case "referenceRange.age.low.value":
2675
- targetData["referenceRangeAgeLowValue"] = column.text?.div ?? "";
2696
+ targetData["referenceRangeAgeLowValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2676
2697
  break;
2677
2698
  case "referenceRange.age.low.unit":
2678
- targetData["referenceRangeAgeLowUnit"] = column.text?.div ?? "";
2699
+ targetData["referenceRangeAgeLowUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2679
2700
  break;
2680
2701
  case "referenceRange.age.high.value":
2681
- targetData["referenceRangeAgeHighValue"] = column.text?.div ?? "";
2702
+ targetData["referenceRangeAgeHighValue"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2682
2703
  break;
2683
2704
  case "referenceRange.age.high.unit":
2684
- targetData["referenceRangeAgeHighUnit"] = column.text?.div ?? "";
2705
+ targetData["referenceRangeAgeHighUnit"] = templateUtilities.renderTextAsHtml(column.text?.div ?? "");
2685
2706
  break;
2686
2707
  default:
2687
2708
  break;
@@ -2734,28 +2755,28 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2734
2755
  for (const componentSection of columnData.section) {
2735
2756
  const componentData = {};
2736
2757
  for (const nestedColumn of componentSection.section ?? []) {
2737
- this.extractSummaryObservationFields(nestedColumn, componentData);
2758
+ this.extractSummaryObservationFields(nestedColumn, componentData, templateUtilities);
2738
2759
  }
2739
2760
  if (Object.keys(componentData).length > 0) {
2740
2761
  components.push(componentData);
2741
2762
  }
2742
2763
  }
2743
2764
  } else {
2744
- this.extractSummaryObservationFields(columnData, data);
2765
+ this.extractSummaryObservationFields(columnData, data, templateUtilities);
2745
2766
  }
2746
2767
  } else if (resourceItem.title === "DiagnosticReportLab Summary Grouped by DiagnosticReport|Lab Code") {
2747
2768
  switch (columnData.title) {
2748
2769
  case "Diagnostic Report Name":
2749
- data["report"] = columnData.text?.div ?? "";
2770
+ data["report"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2750
2771
  break;
2751
2772
  case "Performer":
2752
- data["performer"] = columnData.text?.div ?? "";
2773
+ data["performer"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2753
2774
  break;
2754
2775
  case "Issued Date":
2755
- data["issued"] = columnData.text?.div ?? "";
2776
+ data["issued"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2756
2777
  break;
2757
2778
  case "Status":
2758
- data["status"] = columnData.text?.div ?? "";
2779
+ data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2759
2780
  break;
2760
2781
  default:
2761
2782
  break;
@@ -2780,8 +2801,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2780
2801
  observationhtml += `
2781
2802
  <tr>
2782
2803
  <td>${componentCode}</td>
2783
- <td>${component["formattedValue"] ?? "-"}</td>
2784
- <td>${component["referenceRange"]?.trim() ?? "-"}</td>
2804
+ <td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? "-"}</td>
2805
+ <td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? "-"}</td>
2785
2806
  <td>${date ?? "-"}</td>
2786
2807
  </tr>`;
2787
2808
  }
@@ -2794,8 +2815,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2794
2815
  observationhtml += `
2795
2816
  <tr>
2796
2817
  <td>${data["code"] ?? "-"}</td>
2797
- <td>${data["formattedValue"] ?? "-"}</td>
2798
- <td>${data["referenceRange"]?.trim() ?? "-"}</td>
2818
+ <td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? "-"}</td>
2819
+ <td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? "-"}</td>
2799
2820
  <td>${date ?? "-"}</td>
2800
2821
  </tr>`;
2801
2822
  }
@@ -2955,7 +2976,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2955
2976
  <tbody>`;
2956
2977
  const observationAdded = /* @__PURE__ */ new Set();
2957
2978
  for (const obs of observations) {
2958
- const obsCode = templateUtilities.codeableConcept(obs.code);
2979
+ const obsCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code));
2959
2980
  if (!observationAdded.has(obsCode)) {
2960
2981
  observationAdded.add(obsCode);
2961
2982
  html += `
@@ -2994,7 +3015,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2994
3015
  <tbody>`;
2995
3016
  const diagnosticReportAdded = /* @__PURE__ */ new Set();
2996
3017
  for (const report of reports) {
2997
- const reportName = templateUtilities.codeableConcept(report.code);
3018
+ const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(report.code));
2998
3019
  if (!diagnosticReportAdded.has(reportName)) {
2999
3020
  diagnosticReportAdded.add(reportName);
3000
3021
  let resultCount = "";
@@ -3108,7 +3129,7 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3108
3129
  const proc = resourceItem;
3109
3130
  html += `
3110
3131
  <tr id="${templateUtilities.narrativeLinkId(proc)}">
3111
- <td>${templateUtilities.codeableConcept(proc.code, "display")}</td>
3132
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(proc.code, "display"))}</td>
3112
3133
  <td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
3113
3134
  <td>${proc.performedDateTime ? templateUtilities.renderTime(proc.performedDateTime, timezone) : proc.performedPeriod ? templateUtilities.renderPeriod(proc.performedPeriod, timezone) : ""}</td>
3114
3135
  </tr>`;
@@ -3160,7 +3181,7 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
3160
3181
  for (const obs of observations) {
3161
3182
  html += `
3162
3183
  <tr id="${templateUtilities.narrativeLinkId(obs)}">
3163
- <td>${templateUtilities.codeableConcept(obs.code)}</td>
3184
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(obs.code))}</td>
3164
3185
  <td>${templateUtilities.extractObservationValue(obs)}</td>
3165
3186
  <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
3166
3187
  <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
@@ -3205,7 +3226,7 @@ var PastHistoryOfIllnessTemplate = class {
3205
3226
  <tbody>`;
3206
3227
  const addedConditionCodes = /* @__PURE__ */ new Set();
3207
3228
  for (const cond of resolvedConditions) {
3208
- const conditionCode = templateUtilities.codeableConcept(cond.code);
3229
+ const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
3209
3230
  if (!addedConditionCodes.has(conditionCode)) {
3210
3231
  addedConditionCodes.add(conditionCode);
3211
3232
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
@@ -3291,7 +3312,7 @@ var PlanOfCareTemplate = class {
3291
3312
  const data = {};
3292
3313
  for (const columnData of rowData.section ?? []) {
3293
3314
  if (columnData.title) {
3294
- data[columnData.title] = columnData.text?.div ?? "";
3315
+ data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3295
3316
  }
3296
3317
  }
3297
3318
  if (data["status"] !== "active") {
@@ -3367,7 +3388,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
3367
3388
  <tbody>`;
3368
3389
  const addedConditionCodes = /* @__PURE__ */ new Set();
3369
3390
  for (const cond of activeConditions) {
3370
- const conditionCode = templateUtilities.codeableConcept(cond.code);
3391
+ const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(cond.code));
3371
3392
  if (!addedConditionCodes.has(conditionCode)) {
3372
3393
  addedConditionCodes.add(conditionCode);
3373
3394
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
@@ -3412,7 +3433,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
3412
3433
  if (impression.finding && impression.finding.length > 0) {
3413
3434
  findingsHtml = "<ul>";
3414
3435
  for (const finding of impression.finding) {
3415
- const findingText = finding.itemCodeableConcept ? templateUtilities.codeableConcept(finding.itemCodeableConcept) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
3436
+ const findingText = finding.itemCodeableConcept ? templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(finding.itemCodeableConcept)) : finding.itemReference ? templateUtilities.renderReference(finding.itemReference) : "";
3416
3437
  const cause = finding.basis || "";
3417
3438
  findingsHtml += `<li>${findingText}${cause ? ` - ${cause}` : ""}</li>`;
3418
3439
  }
@@ -3473,9 +3494,9 @@ var PregnancyTemplate = class _PregnancyTemplate {
3473
3494
  const obs = resource;
3474
3495
  html += `
3475
3496
  <tr id="${templateUtilities.narrativeLinkId(obs)}">
3476
- <td>${templateUtilities.extractPregnancyStatus(obs)}</td>
3497
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.extractPregnancyStatus(obs))}</td>
3477
3498
  <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
3478
- <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3499
+ <td>${obs.effectiveDateTime ? templateUtilities.renderTextAsHtml(templateUtilities.renderTime(obs.effectiveDateTime, timezone)) : obs.effectivePeriod ? templateUtilities.renderTextAsHtml(templateUtilities.renderPeriod(obs.effectivePeriod, timezone)) : ""}</td>
3479
3500
  </tr>`;
3480
3501
  }
3481
3502
  html += `
@@ -3525,7 +3546,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
3525
3546
  const consent = resourceItem;
3526
3547
  html += `
3527
3548
  <tr id="${templateUtilities.narrativeLinkId(consent)}">
3528
- <td>${templateUtilities.codeableConcept(consent.scope, "display")}</td>
3549
+ <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConcept(consent.scope, "display"))}</td>
3529
3550
  <td>${consent.status || ""}</td>
3530
3551
  <td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
3531
3552
  <td>${consent.dateTime || ""}</td>
@@ -3546,16 +3567,18 @@ var TypeScriptTemplateMapper = class {
3546
3567
  * @param resources - FHIR resources
3547
3568
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
3548
3569
  * @param useSectionSummary - Whether to use the section summary for narrative generation
3570
+ * @param now - Optional current date to use for generating relative dates in the narrative
3549
3571
  * @returns HTML string for rendering
3550
3572
  */
3551
- static generateNarrative(section, resources, timezone, useSectionSummary = false) {
3573
+ static generateNarrative(section, resources, timezone, useSectionSummary = false, now) {
3552
3574
  const templateClass = this.sectionToTemplate[section];
3553
3575
  if (!templateClass) {
3554
3576
  throw new Error(`No template found for section: ${section}`);
3555
3577
  }
3556
3578
  return useSectionSummary ? templateClass.generateSummaryNarrative(
3557
3579
  resources,
3558
- timezone
3580
+ timezone,
3581
+ now
3559
3582
  ) : templateClass.generateNarrative(resources, timezone);
3560
3583
  }
3561
3584
  };
@@ -3613,14 +3636,15 @@ var NarrativeGenerator = class {
3613
3636
  * @param resources - Array of domain resources
3614
3637
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
3615
3638
  * @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
3639
+ * @param now - Optional date parameter
3616
3640
  * @returns Generated HTML content or undefined if no resources
3617
3641
  */
3618
- static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false) {
3642
+ static async generateNarrativeContentAsync(section, resources, timezone, useSectionSummary = false, now) {
3619
3643
  if (!resources || resources.length === 0) {
3620
3644
  return void 0;
3621
3645
  }
3622
3646
  try {
3623
- const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary);
3647
+ const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone, useSectionSummary, now);
3624
3648
  if (!content) {
3625
3649
  return void 0;
3626
3650
  }
@@ -3642,8 +3666,8 @@ var NarrativeGenerator = class {
3642
3666
  const options = aggressive ? AGGRESSIVE_MINIFY_OPTIONS : DEFAULT_MINIFY_OPTIONS;
3643
3667
  return await (0, import_html_minifier_terser.minify)(html, options);
3644
3668
  } catch (error) {
3645
- console.warn("HTML minification failed", error);
3646
- return html;
3669
+ console.warn("HTML minification failed", error, html);
3670
+ return `${error instanceof Error ? error.message : String(error)}`;
3647
3671
  }
3648
3672
  }
3649
3673
  /**
@@ -3672,10 +3696,11 @@ var NarrativeGenerator = class {
3672
3696
  * @param timezone - Optional timezone to use for date formatting
3673
3697
  * @param minify - Whether to minify the HTML content (default: true)
3674
3698
  * @param useSectionSummary - Whether to use section summary for narrative generation (default: false)
3699
+ * @param now - Optional date parameter
3675
3700
  * @returns Promise that resolves to a FHIR Narrative object or undefined if no resources
3676
3701
  */
3677
- static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false) {
3678
- const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary);
3702
+ static async generateNarrativeAsync(section, resources, timezone, minify = true, useSectionSummary = false, now) {
3703
+ const content = await this.generateNarrativeContentAsync(section, resources, timezone, useSectionSummary, now);
3679
3704
  if (!content) {
3680
3705
  return void 0;
3681
3706
  }
@@ -3833,6 +3858,12 @@ var ComprehensiveIPSCompositionBuilder = class {
3833
3858
  if (sectionType === "Patient" /* PATIENT */) {
3834
3859
  continue;
3835
3860
  }
3861
+ const summaryIPSCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryIPSCompositionFilterForSection(sectionType) : void 0;
3862
+ const sectionIPSSummary = summaryIPSCompositionFilter ? resources.filter((resource) => summaryIPSCompositionFilter(resource)) : [];
3863
+ if (sectionIPSSummary.length > 0) {
3864
+ await this.makeSectionFromSummaryAsync(sectionType, sectionIPSSummary, resources, timezone);
3865
+ continue;
3866
+ }
3836
3867
  const summaryCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryCompositionFilterForSection(sectionType) : void 0;
3837
3868
  const sectionSummary = summaryCompositionFilter ? resources.filter((resource) => summaryCompositionFilter(resource)) : [];
3838
3869
  if (sectionSummary.length > 0) {
@@ -3852,8 +3883,9 @@ var ComprehensiveIPSCompositionBuilder = class {
3852
3883
  * @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
3853
3884
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
3854
3885
  * @param patientId - Optional patient ID to use as primary patient for composition reference
3886
+ * @param now - Optional current date to use for composition date (defaults to new Date())
3855
3887
  */
3856
- async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId) {
3888
+ async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId, now) {
3857
3889
  if (baseUrl.endsWith("/")) {
3858
3890
  baseUrl = baseUrl.slice(0, -1);
3859
3891
  }
@@ -3880,20 +3912,22 @@ var ComprehensiveIPSCompositionBuilder = class {
3880
3912
  // Assuming patient is also a practitioner for simplicity
3881
3913
  display: authorOrganizationName
3882
3914
  }],
3883
- date: (/* @__PURE__ */ new Date()).toISOString(),
3915
+ date: (now || /* @__PURE__ */ new Date()).toISOString(),
3884
3916
  title: "International Patient Summary",
3885
3917
  section: this.sections,
3886
3918
  text: await NarrativeGenerator.generateNarrativeAsync(
3887
3919
  "Patient" /* PATIENT */,
3888
3920
  this.patients,
3889
3921
  timezone,
3890
- true
3922
+ true,
3923
+ false,
3924
+ now
3891
3925
  )
3892
3926
  };
3893
3927
  const bundle = {
3894
3928
  resourceType: "Bundle",
3895
3929
  type: "document",
3896
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3930
+ timestamp: (now || /* @__PURE__ */ new Date()).toISOString(),
3897
3931
  identifier: {
3898
3932
  "system": "urn:ietf:rfc:3986",
3899
3933
  "value": "urn:uuid:4dcfd353-49fd-4ab0-b521-c8d57ced74d6"