@imranq2/fhirpatientsummary 1.0.15 → 1.0.17

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
@@ -103,35 +103,28 @@ var SOCIAL_HISTORY_LOINC_CODES = {
103
103
  "72166-2": "Tobacco Use",
104
104
  "74013-4": "Alcohol Use"
105
105
  };
106
+ var BLOOD_PRESSURE_LOINC_CODES = {
107
+ OBSERVATION: "85354-9",
108
+ SYSTOLIC: "8480-6",
109
+ DIASTOLIC: "8462-4"
110
+ };
106
111
 
107
112
  // src/structures/ips_section_resource_map.ts
108
- var IPSSectionResourceMap = {
109
- ["Patient" /* PATIENT */]: ["Patient"],
110
- ["AllergyIntoleranceSection" /* ALLERGIES */]: ["AllergyIntolerance"],
111
- ["MedicationSummarySection" /* MEDICATIONS */]: ["MedicationRequest", "MedicationStatement", "Medication"],
112
- // Medication resource is needed for identifying name of medication
113
- ["ProblemSection" /* PROBLEMS */]: ["Condition"],
114
- ["ImmunizationSection" /* IMMUNIZATIONS */]: ["Immunization", "Organization"],
115
- // Immunization can include Organization as a related resource
116
- ["VitalSignsSection" /* VITAL_SIGNS */]: ["Observation"],
117
- ["MedicalDeviceSection" /* MEDICAL_DEVICES */]: ["DeviceUseStatement", "Device"],
118
- // Device resource is used for medical devices name
119
- ["ResultsSection" /* DIAGNOSTIC_REPORTS */]: ["DiagnosticReport", "Observation"],
120
- ["HistoryOfProceduresSection" /* PROCEDURES */]: ["Procedure"],
121
- ["SocialHistorySection" /* SOCIAL_HISTORY */]: ["Observation"],
122
- ["HistoryOfPregnancySection" /* PREGNANCY_HISTORY */]: ["Observation"],
123
- ["FunctionalStatusSection" /* FUNCTIONAL_STATUS */]: ["Condition", "ClinicalImpression"],
124
- ["HistoryOfPastIllnessSection" /* MEDICAL_HISTORY */]: ["Condition"],
125
- ["PlanOfCareSection" /* CARE_PLAN */]: ["CarePlan"],
126
- ["AdvanceDirectivesSection" /* ADVANCE_DIRECTIVES */]: ["Consent"]
127
- };
128
113
  var IPSSectionResourceFilters = {
114
+ // Patient section: only Patient resource
115
+ ["Patient" /* PATIENT */]: (resource) => resource.resourceType === "Patient",
116
+ // Only include allergies
117
+ ["AllergyIntoleranceSection" /* ALLERGIES */]: (resource) => resource.resourceType === "AllergyIntolerance",
118
+ // includes MedicationRequest, MedicationStatement. Medication is needed for medication names
119
+ ["MedicationSummarySection" /* MEDICATIONS */]: (resource) => ["MedicationRequest", "MedicationStatement", "Medication"].includes(resource.resourceType),
129
120
  // Only include active conditions
130
121
  ["ProblemSection" /* PROBLEMS */]: (resource) => resource.resourceType === "Condition" && resource.clinicalStatus?.coding?.some((c) => !["inactive", "resolved"].includes(c.code)),
131
122
  // Only include completed immunizations
132
123
  ["ImmunizationSection" /* IMMUNIZATIONS */]: (resource) => resource.resourceType === "Immunization" && resource.status === "completed" || resource.resourceType === "Organization",
133
124
  // Only include vital sign Observations (category.coding contains 'vital-signs')
134
125
  ["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Observation" && resource.category?.some((cat) => cat.coding?.some((c) => c.code === "vital-signs")),
126
+ // Includes DeviceUseStatement. Device is needed for linked device details
127
+ ["MedicalDeviceSection" /* MEDICAL_DEVICES */]: (resource) => ["DeviceUseStatement", "Device"].includes(resource.resourceType),
135
128
  // Only include finalized diagnostic reports
136
129
  ["ResultsSection" /* DIAGNOSTIC_REPORTS */]: (resource) => ["DiagnosticReport", "Observation"].includes(resource.resourceType) && resource.status === "final",
137
130
  // Only include completed procedures
@@ -147,14 +140,9 @@ var IPSSectionResourceFilters = {
147
140
  // Only include active care plans
148
141
  ["PlanOfCareSection" /* CARE_PLAN */]: (resource) => resource.resourceType === "CarePlan" && resource.status === "active",
149
142
  // Only include active advance directives (Consent resources)
150
- ["AdvanceDirectivesSection" /* ADVANCE_DIRECTIVES */]: (resource) => resource.resourceType === "Consent" && resource.status === "active",
151
- // Patient section: only Patient resource
152
- ["Patient" /* PATIENT */]: (resource) => resource.resourceType === "Patient"
143
+ ["AdvanceDirectivesSection" /* ADVANCE_DIRECTIVES */]: (resource) => resource.resourceType === "Consent" && resource.status === "active"
153
144
  };
154
145
  var IPSSectionResourceHelper = class {
155
- static getResourceTypesForSection(section) {
156
- return IPSSectionResourceMap[section] || [];
157
- }
158
146
  static getResourceFilterForSection(section) {
159
147
  return IPSSectionResourceFilters[section];
160
148
  }
@@ -164,11 +152,11 @@ var IPSSectionResourceHelper = class {
164
152
  var import_luxon = require("luxon");
165
153
  var TemplateUtilities = class {
166
154
  /**
167
- * Constructor to initialize the TemplateUtilities with a FHIR Bundle
168
- * @param bundle - FHIR Bundle containing resources
155
+ * Constructor to initialize the TemplateUtilities with a FHIR resources
156
+ * @param resources - FHIR resources
169
157
  */
170
- constructor(bundle) {
171
- this.bundle = bundle;
158
+ constructor(resources) {
159
+ this.resources = resources;
172
160
  }
173
161
  /**
174
162
  * Formats a CodeableConcept object
@@ -199,7 +187,7 @@ var TemplateUtilities = class {
199
187
  return "";
200
188
  }
201
189
  resolveReference(ref) {
202
- if (!ref || !this.bundle || !this.bundle.entry) {
190
+ if (!ref || !this.resources) {
203
191
  return null;
204
192
  }
205
193
  const referenceParts = ref.reference?.split("/");
@@ -208,10 +196,10 @@ var TemplateUtilities = class {
208
196
  }
209
197
  const referenceResourceType = referenceParts[0];
210
198
  const referenceResourceId = referenceParts[1];
211
- const resource = this.bundle.entry.find((entry) => {
212
- return entry.resource && entry.resource.resourceType === referenceResourceType && entry.resource.id === referenceResourceId;
199
+ const resource = this.resources.find((entry) => {
200
+ return entry.resourceType === referenceResourceType && entry.id === referenceResourceId;
213
201
  });
214
- return resource ? resource.resource : null;
202
+ return resource ? resource : null;
215
203
  }
216
204
  /**
217
205
  * Renders a Device reference
@@ -530,6 +518,28 @@ var TemplateUtilities = class {
530
518
  return "";
531
519
  }
532
520
  extractObservationValue(observation) {
521
+ if (observation.code && observation.code.coding && "component" in observation && Array.isArray(observation.component)) {
522
+ const bpCode = observation.code.coding.find(
523
+ (c) => c.code === BLOOD_PRESSURE_LOINC_CODES.OBSERVATION
524
+ );
525
+ if (bpCode) {
526
+ const systolicComponent = observation.component?.find(
527
+ (c) => c.code?.coding?.some(
528
+ (cc) => cc.code === BLOOD_PRESSURE_LOINC_CODES.SYSTOLIC
529
+ )
530
+ );
531
+ const diastolicComponent = observation.component?.find(
532
+ (c) => c.code?.coding?.some(
533
+ (cc) => cc.code === BLOOD_PRESSURE_LOINC_CODES.DIASTOLIC
534
+ )
535
+ );
536
+ if (systolicComponent && diastolicComponent) {
537
+ const systolic = this.extractObservationValue(systolicComponent);
538
+ const diastolic = this.extractObservationValue(diastolicComponent);
539
+ return `${systolic}/${diastolic}`;
540
+ }
541
+ }
542
+ }
533
543
  const valueFields = [
534
544
  "valueString",
535
545
  "valueInteger",
@@ -760,7 +770,7 @@ var TemplateUtilities = class {
760
770
  if (parts.length === 2) {
761
771
  const resourceType = parts[0];
762
772
  const resourceId = parts[1];
763
- const resource = this.bundle.entry?.find((entry) => entry.resource?.resourceType === resourceType && entry.resource?.id === resourceId);
773
+ const resource = this.resources?.find((resource2) => resource2.resourceType === resourceType && resource2.id === resourceId);
764
774
  if (resource) {
765
775
  return `${resourceType}/${resourceId}`;
766
776
  }
@@ -800,48 +810,96 @@ var TemplateUtilities = class {
800
810
  // src/narratives/templates/typescript/PatientTemplate.ts
801
811
  var PatientTemplate = class _PatientTemplate {
802
812
  /**
803
- * Generate HTML narrative for Patient resource
804
- * @param resource - FHIR Bundle containing Patient resource
813
+ * Generate HTML narrative for Patient resources
814
+ * @param resources - FHIR Patient resources
805
815
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
806
816
  * @returns HTML string for rendering
807
817
  */
808
- generateNarrative(resource, timezone) {
809
- return _PatientTemplate.generateStaticNarrative(resource, timezone);
818
+ generateNarrative(resources, timezone) {
819
+ return _PatientTemplate.generateStaticNarrative(resources, timezone);
810
820
  }
811
821
  /**
812
822
  * Internal static implementation that actually generates the narrative
813
- * @param resource - FHIR Bundle containing Patient resource
823
+ * @param resources - FHIR Patient resources
814
824
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
815
825
  * @returns HTML string for rendering
816
826
  */
817
827
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
818
- static generateStaticNarrative(resource, timezone) {
819
- const templateUtilities = new TemplateUtilities(resource);
820
- let html = "";
821
- for (const entry of resource.entry || []) {
822
- if (entry.resource?.resourceType === "Patient") {
823
- const patient = entry.resource;
824
- html += `
825
- <div>
826
- <ul>
827
- <li><strong>Name(s):</strong>${this.renderNames(patient)}</li>
828
- <li><strong>Gender:</strong>${patient.gender ? this.capitalize(patient.gender) : ""}</li>
829
- <li><strong>Date of Birth:</strong>${patient.birthDate || ""}</li>
830
- <li><strong>Identifier(s):</strong>${this.renderIdentifiers(patient)}</li>
831
- <li><strong>Telecom:</strong><ul>${this.renderTelecom(patient)}</ul></li>
832
- <li><strong>Address(es):</strong>${this.renderAddresses(patient)}</li>
833
- <li><strong>Marital Status:</strong> ${patient.maritalStatus?.text || ""}</li>
834
- <li><strong>Deceased:</strong>${this.renderDeceased(patient)}</li>
835
- <li><strong>Language(s):</strong>${this.renderCommunication(templateUtilities, patient)}</li>
836
- </ul>
837
- </div>`;
828
+ static generateStaticNarrative(resources, timezone) {
829
+ const templateUtilities = new TemplateUtilities(resources);
830
+ const combinedPatient = this.combinePatients(resources);
831
+ return `<div>
832
+ <ul>
833
+ <li><strong>Name(s):</strong>${this.renderNames(combinedPatient)}</li>
834
+ <li><strong>Gender:</strong>${combinedPatient.gender ? this.capitalize(combinedPatient.gender) : ""}</li>
835
+ <li><strong>Date of Birth:</strong>${combinedPatient.birthDate || ""}</li>
836
+ <li><strong>Identifier(s):</strong>${this.renderIdentifiers(combinedPatient)}</li>
837
+ <li><strong>Telecom:</strong><ul>${this.renderTelecom(combinedPatient)}</ul></li>
838
+ <li><strong>Address(es):</strong>${this.renderAddresses(combinedPatient)}</li>
839
+ <li><strong>Marital Status:</strong> ${combinedPatient.maritalStatus?.text || ""}</li>
840
+ <li><strong>Deceased:</strong>${this.renderDeceased(combinedPatient)}</li>
841
+ <li><strong>Language(s):</strong>${this.renderCommunication(templateUtilities, combinedPatient)}</li>
842
+ </ul>
843
+ </div>`;
844
+ }
845
+ /**
846
+ * Combines multiple patient resources into a single patient object
847
+ * Merges fields, preferring non-empty values
848
+ * @param patients - Array of patient resources
849
+ * @returns Combined patient resource
850
+ */
851
+ static combinePatients(patients) {
852
+ if (patients.length === 1) {
853
+ return patients[0];
854
+ }
855
+ const combined = patients[0];
856
+ const allNames = [];
857
+ const allIdentifiers = [];
858
+ const allTelecom = [];
859
+ const allAddresses = [];
860
+ const allCommunication = [];
861
+ patients.forEach((patient) => {
862
+ if (patient.name) {
863
+ allNames.push(...patient.name);
838
864
  }
839
- }
840
- return html;
865
+ if (patient.identifier) {
866
+ allIdentifiers.push(...patient.identifier);
867
+ }
868
+ if (patient.telecom) {
869
+ allTelecom.push(...patient.telecom);
870
+ }
871
+ if (patient.address) {
872
+ allAddresses.push(...patient.address);
873
+ }
874
+ if (patient.communication) {
875
+ allCommunication.push(...patient.communication);
876
+ }
877
+ if (!combined.gender && patient.gender) {
878
+ combined.gender = patient.gender;
879
+ }
880
+ if (!combined.birthDate && patient.birthDate) {
881
+ combined.birthDate = patient.birthDate;
882
+ }
883
+ if (!combined.maritalStatus && patient.maritalStatus) {
884
+ combined.maritalStatus = patient.maritalStatus;
885
+ }
886
+ if (!combined.deceasedBoolean && patient.deceasedBoolean !== void 0) {
887
+ combined.deceasedBoolean = patient.deceasedBoolean;
888
+ }
889
+ if (!combined.deceasedDateTime && patient.deceasedDateTime) {
890
+ combined.deceasedDateTime = patient.deceasedDateTime;
891
+ }
892
+ });
893
+ combined.name = allNames;
894
+ combined.identifier = allIdentifiers;
895
+ combined.telecom = allTelecom;
896
+ combined.address = allAddresses;
897
+ combined.communication = allCommunication;
898
+ return combined;
841
899
  }
842
900
  /**
843
901
  * Renders patient names as HTML list items
844
- * @param patient - Patient resource
902
+ * @param patient - Patient resources
845
903
  * @returns HTML string of list items
846
904
  */
847
905
  static renderNames(patient) {
@@ -852,14 +910,16 @@ var PatientTemplate = class _PatientTemplate {
852
910
  patient.name.forEach((name) => {
853
911
  if (name.use !== "old") {
854
912
  const nameText = name.text || ((name.given || []).join(" ") + " " + (name.family || "")).trim();
855
- uniqueNames.add(nameText);
913
+ if (nameText) {
914
+ uniqueNames.add(nameText);
915
+ }
856
916
  }
857
917
  });
858
918
  return Array.from(uniqueNames).map((nameText) => `<ul><li>${nameText}</li></ul>`).join("");
859
919
  }
860
920
  /**
861
921
  * Renders patient identifiers as HTML list items
862
- * @param patient - Patient resource
922
+ * @param patient - Patient resources
863
923
  * @returns HTML string of list items
864
924
  */
865
925
  static renderIdentifiers(patient) {
@@ -874,7 +934,7 @@ var PatientTemplate = class _PatientTemplate {
874
934
  }
875
935
  /**
876
936
  * Renders patient telecom information grouped by system
877
- * @param patient - Patient resource
937
+ * @param patient - Patient resources
878
938
  * @returns HTML string grouped by system
879
939
  */
880
940
  static renderTelecom(patient) {
@@ -882,9 +942,10 @@ var PatientTemplate = class _PatientTemplate {
882
942
  return "";
883
943
  }
884
944
  const systemPriority = ["email", "phone", "pager", "sms", "fax", "url", "other"];
945
+ const numberSystems = ["phone", "pager", "sms", "fax"];
885
946
  const telecomBySystem = /* @__PURE__ */ new Map();
886
947
  patient.telecom.forEach((telecom) => {
887
- if (telecom.system && telecom.value) {
948
+ if (telecom.system && telecom.value && telecom.use !== "old") {
888
949
  const system = telecom.system.toLowerCase();
889
950
  if (!telecomBySystem.has(system)) {
890
951
  telecomBySystem.set(system, /* @__PURE__ */ new Set());
@@ -892,6 +953,29 @@ var PatientTemplate = class _PatientTemplate {
892
953
  telecomBySystem.get(system).add(telecom.value);
893
954
  }
894
955
  });
956
+ for (const system of numberSystems) {
957
+ const currentNumbers = Array.from(telecomBySystem.get(system) || []);
958
+ if (currentNumbers.length <= 1) continue;
959
+ const numbersWithCleaned = currentNumbers.map((num) => ({
960
+ original: num,
961
+ cleaned: num.replace(/\D/g, "")
962
+ }));
963
+ const toRemove = /* @__PURE__ */ new Set();
964
+ for (let i = 0; i < numbersWithCleaned.length; i++) {
965
+ for (let j = i + 1; j < numbersWithCleaned.length; j++) {
966
+ const num1 = numbersWithCleaned[i];
967
+ const num2 = numbersWithCleaned[j];
968
+ if (num1.cleaned.endsWith(num2.cleaned)) {
969
+ toRemove.add(num2.original);
970
+ } else if (num2.cleaned.endsWith(num1.cleaned)) {
971
+ toRemove.add(num1.original);
972
+ }
973
+ }
974
+ }
975
+ toRemove.forEach((numberToRemove) => {
976
+ telecomBySystem.get(system)?.delete(numberToRemove);
977
+ });
978
+ }
895
979
  return Array.from(telecomBySystem.entries()).sort(([systemA], [systemB]) => {
896
980
  const priorityA = systemPriority.indexOf(systemA);
897
981
  const priorityB = systemPriority.indexOf(systemB);
@@ -909,7 +993,7 @@ var PatientTemplate = class _PatientTemplate {
909
993
  }
910
994
  /**
911
995
  * Renders patient addresses as HTML list items
912
- * @param patient - Patient resource
996
+ * @param patient - Patient resources
913
997
  * @returns HTML string of list items
914
998
  */
915
999
  static renderAddresses(patient) {
@@ -918,7 +1002,33 @@ var PatientTemplate = class _PatientTemplate {
918
1002
  }
919
1003
  const uniqueAddresses = /* @__PURE__ */ new Set();
920
1004
  patient.address.forEach((address) => {
921
- const addressText = address.text || ((address.line || []).join(", ") + ", " + (address.city || "") + ", " + (address.country || "")).trim();
1005
+ if (address.use === "old") {
1006
+ return;
1007
+ }
1008
+ const addressArray = [];
1009
+ if (address.text) {
1010
+ addressArray.push(address.text);
1011
+ } else {
1012
+ if (address.line) {
1013
+ addressArray.push(...address.line);
1014
+ }
1015
+ if (address.city) {
1016
+ addressArray.push(address.city);
1017
+ }
1018
+ if (address.district) {
1019
+ addressArray.push(address.district);
1020
+ }
1021
+ if (address.state) {
1022
+ addressArray.push(address.state);
1023
+ }
1024
+ if (address.country) {
1025
+ addressArray.push(address.country);
1026
+ }
1027
+ if (address.postalCode) {
1028
+ addressArray.push(address.postalCode);
1029
+ }
1030
+ }
1031
+ const addressText = addressArray.join(", ").trim();
922
1032
  if (addressText) {
923
1033
  uniqueAddresses.add(addressText);
924
1034
  }
@@ -927,7 +1037,7 @@ var PatientTemplate = class _PatientTemplate {
927
1037
  }
928
1038
  /**
929
1039
  * Renders patient deceased status
930
- * @param patient - Patient resource
1040
+ * @param patient - Patient resources
931
1041
  * @returns HTML string for deceased status
932
1042
  */
933
1043
  static renderDeceased(patient) {
@@ -942,19 +1052,25 @@ var PatientTemplate = class _PatientTemplate {
942
1052
  /**
943
1053
  * Renders patient communication preferences as HTML list items
944
1054
  * @param templateUtilities - Instance of TemplateUtilities for utility functions
945
- * @param patient - Patient resource
1055
+ * @param patient - Patient resources
946
1056
  * @returns HTML string of list items
947
1057
  */
948
1058
  static renderCommunication(templateUtilities, patient) {
949
1059
  if (!patient.communication || patient.communication.length === 0) {
950
1060
  return "";
951
1061
  }
952
- return patient.communication.map((comm) => {
953
- if (!comm.language) return "";
1062
+ const uniqueLanguages = /* @__PURE__ */ new Set();
1063
+ const preferredLanguages = /* @__PURE__ */ new Set();
1064
+ patient.communication.forEach((comm) => {
954
1065
  const language = templateUtilities.codeableConcept(comm.language);
955
- const preferred = comm.preferred ? " (preferred)" : "";
956
- return `<ul><li>${language}${preferred}</li></ul>`;
957
- }).join("");
1066
+ if (language) {
1067
+ if (comm.preferred) {
1068
+ preferredLanguages.add(language);
1069
+ }
1070
+ uniqueLanguages.add(language);
1071
+ }
1072
+ });
1073
+ return Array.from(uniqueLanguages).map((language) => `<ul><li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li></ul>`).join("");
958
1074
  }
959
1075
  /**
960
1076
  * Capitalizes first letter of a string
@@ -971,32 +1087,30 @@ var PatientTemplate = class _PatientTemplate {
971
1087
  var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
972
1088
  /**
973
1089
  * Generate HTML narrative for AllergyIntolerance resources
974
- * @param resource - FHIR Bundle containing AllergyIntolerance resources
1090
+ * @param resources - FHIR resources array containing AllergyIntolerance resources
975
1091
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
976
1092
  * @returns HTML string for rendering
977
1093
  */
978
- generateNarrative(resource, timezone) {
979
- return _AllergyIntoleranceTemplate.generateStaticNarrative(resource, timezone);
1094
+ generateNarrative(resources, timezone) {
1095
+ return _AllergyIntoleranceTemplate.generateStaticNarrative(resources, timezone);
980
1096
  }
981
1097
  /**
982
1098
  * Internal static implementation that actually generates the narrative
983
- * @param resource - FHIR Bundle containing AllergyIntolerance resources
1099
+ * @param resources - FHIR resources array containing AllergyIntolerance resources
984
1100
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
985
1101
  * @returns HTML string for rendering
986
1102
  */
987
- static generateStaticNarrative(resource, timezone) {
988
- const templateUtilities = new TemplateUtilities(resource);
1103
+ static generateStaticNarrative(resources, timezone) {
1104
+ const templateUtilities = new TemplateUtilities(resources);
989
1105
  const activeAllergies = [];
990
1106
  const resolvedAllergies = [];
991
- if (resource.entry && Array.isArray(resource.entry)) {
992
- for (const entry of resource.entry) {
993
- const allergy = entry.resource;
994
- const isResolved = allergy.clinicalStatus?.coding?.some((c) => ["inactive", "resolved"].includes(c.code));
995
- if (isResolved) {
996
- resolvedAllergies.push(allergy);
997
- } else {
998
- activeAllergies.push(allergy);
999
- }
1107
+ for (const resourceItem of resources) {
1108
+ const allergy = resourceItem;
1109
+ const isResolved = allergy.clinicalStatus?.coding?.some((c) => ["inactive", "resolved"].includes(c.code));
1110
+ if (isResolved) {
1111
+ resolvedAllergies.push(allergy);
1112
+ } else {
1113
+ activeAllergies.push(allergy);
1000
1114
  }
1001
1115
  }
1002
1116
  activeAllergies.sort((a, b) => {
@@ -1020,7 +1134,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1020
1134
  <th>Status</th>
1021
1135
  <th>Category</th>
1022
1136
  <th>Reaction</th>
1023
- <th>Severity</th>
1024
1137
  <th>Onset Date</th>
1025
1138
  <th>Comments</th>
1026
1139
  </tr>
@@ -1048,7 +1161,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1048
1161
  <th>Status</th>
1049
1162
  <th>Category</th>
1050
1163
  <th>Reaction</th>
1051
- <th>Severity</th>
1052
1164
  <th>Onset Date</th>
1053
1165
  <th>Comments</th>
1054
1166
  <th>Resolved Date</th>
@@ -1086,7 +1198,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1086
1198
  <td class="Status">${templateUtilities.codeableConcept(allergy.clinicalStatus) || "-"}</td>
1087
1199
  <td class="Category">${templateUtilities.safeConcat(allergy.category) || "-"}</td>
1088
1200
  <td class="Reaction">${templateUtilities.concatReactionManifestation(allergy.reaction) || "-"}</td>
1089
- <td class="Severity">${templateUtilities.safeConcat(allergy.reaction, "severity") || "-"}</td>
1090
1201
  <td class="OnsetDate">${templateUtilities.renderTime(allergy.onsetDateTime, timezone) || "-"}</td>
1091
1202
  <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
1092
1203
  if (includeResolved) {
@@ -1112,12 +1223,12 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1112
1223
  var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1113
1224
  /**
1114
1225
  * Generate HTML narrative for Medication resources
1115
- * @param resource - FHIR Bundle containing Medication resources
1226
+ * @param resources - FHIR Medication resources
1116
1227
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1117
1228
  * @returns HTML string for rendering
1118
1229
  */
1119
- generateNarrative(resource, timezone) {
1120
- return _MedicationSummaryTemplate.generateStaticNarrative(resource, timezone);
1230
+ generateNarrative(resources, timezone) {
1231
+ return _MedicationSummaryTemplate.generateStaticNarrative(resources, timezone);
1121
1232
  }
1122
1233
  /**
1123
1234
  * Safely parse a date string and return a valid Date object or null
@@ -1182,16 +1293,16 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1182
1293
  }
1183
1294
  /**
1184
1295
  * Internal static implementation that actually generates the narrative
1185
- * @param resource - FHIR Bundle containing Medication resources
1296
+ * @param resources - FHIR Medication resources
1186
1297
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1187
1298
  * @returns HTML string for rendering
1188
1299
  */
1189
1300
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1190
- static generateStaticNarrative(resource, timezone) {
1191
- const templateUtilities = new TemplateUtilities(resource);
1301
+ static generateStaticNarrative(resources, timezone) {
1302
+ const templateUtilities = new TemplateUtilities(resources);
1192
1303
  let html = "";
1193
- const medicationRequests = this.getMedicationRequests(templateUtilities, resource);
1194
- const medicationStatements = this.getMedicationStatements(templateUtilities, resource);
1304
+ const medicationRequests = this.getMedicationRequests(templateUtilities, resources);
1305
+ const medicationStatements = this.getMedicationStatements(templateUtilities, resources);
1195
1306
  const allActiveMedications = [];
1196
1307
  const allInactiveMedications = [];
1197
1308
  medicationRequests.forEach((mr) => {
@@ -1236,42 +1347,42 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1236
1347
  };
1237
1348
  if (allActiveMedications.length > 0) {
1238
1349
  sortMedications(allActiveMedications);
1239
- html += this.renderCombinedMedications(templateUtilities, allActiveMedications, "Active Medications");
1350
+ html += this.renderCombinedMedications(templateUtilities, allActiveMedications, true);
1240
1351
  }
1241
1352
  if (allInactiveMedications.length > 0) {
1242
1353
  sortMedications(allInactiveMedications);
1243
- html += this.renderCombinedMedications(templateUtilities, allInactiveMedications, "Inactive Medications");
1354
+ html += this.renderCombinedMedications(templateUtilities, allInactiveMedications, false);
1244
1355
  }
1245
1356
  return html;
1246
1357
  }
1247
1358
  /**
1248
- * Extract MedicationRequest resources from the bundle
1359
+ * Extract MedicationRequest resources
1249
1360
  * @param templateUtilities - Instance of TemplateUtilities for utility functions
1250
- * @param resource - FHIR Bundle
1361
+ * @param resources - FHIR Medication resources
1251
1362
  * @returns Array of MedicationRequest resources
1252
1363
  */
1253
- static getMedicationRequests(templateUtilities, resource) {
1254
- if (!resource.entry || !Array.isArray(resource.entry)) {
1364
+ static getMedicationRequests(templateUtilities, resources) {
1365
+ if (resources.length === 0) {
1255
1366
  return [];
1256
1367
  }
1257
- return resource.entry.filter((entry) => entry.resource?.resourceType === "MedicationRequest").map((entry) => ({
1258
- resource: entry.resource,
1259
- extension: templateUtilities.narrativeLinkExtension(entry.resource)
1368
+ return resources.filter((entry) => entry.resourceType === "MedicationRequest").map((entry) => ({
1369
+ resource: entry,
1370
+ extension: templateUtilities.narrativeLinkExtension(entry)
1260
1371
  }));
1261
1372
  }
1262
1373
  /**
1263
- * Extract MedicationStatement resources from the bundle
1374
+ * Extract MedicationStatement resources
1264
1375
  * @param templateUtilities - Instance of TemplateUtilities for utility functions
1265
- * @param resource - FHIR Bundle
1376
+ * @param resources - FHIR Medication resources
1266
1377
  * @returns Array of MedicationStatement resources
1267
1378
  */
1268
- static getMedicationStatements(templateUtilities, resource) {
1269
- if (!resource.entry || !Array.isArray(resource.entry)) {
1379
+ static getMedicationStatements(templateUtilities, resources) {
1380
+ if (resources.length === 0) {
1270
1381
  return [];
1271
1382
  }
1272
- return resource.entry.filter((entry) => entry.resource?.resourceType === "MedicationStatement").map((entry) => ({
1273
- resource: entry.resource,
1274
- extension: templateUtilities.narrativeLinkExtension(entry.resource)
1383
+ return resources.filter((entry) => entry.resourceType === "MedicationStatement").map((entry) => ({
1384
+ resource: entry,
1385
+ extension: templateUtilities.narrativeLinkExtension(entry)
1275
1386
  }));
1276
1387
  }
1277
1388
  /**
@@ -1281,9 +1392,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1281
1392
  * @param sectionTitle - Title for the section
1282
1393
  * @returns HTML string for rendering
1283
1394
  */
1284
- static renderCombinedMedications(templateUtilities, medications, sectionTitle) {
1395
+ static renderCombinedMedications(templateUtilities, medications, isActiveSection) {
1285
1396
  let html = `
1286
- <h3>${sectionTitle}</h3>
1397
+ <h3>${isActiveSection ? "Active Medications" : "Inactive Medications"}</h3>
1287
1398
  <table>
1288
1399
  <thead>
1289
1400
  <tr>
@@ -1292,8 +1403,8 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1292
1403
  <th>Sig</th>
1293
1404
  <th>Dispense Quantity</th>
1294
1405
  <th>Refills</th>
1295
- <th>Start Date</th>
1296
- <th>End Date</th>
1406
+ <th>Start Date</th>${isActiveSection ? "" : `
1407
+ <th>End Date</th>`}
1297
1408
  <th>Status</th>
1298
1409
  </tr>
1299
1410
  </thead>
@@ -1351,8 +1462,8 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1351
1462
  <td>${sig}</td>
1352
1463
  <td>${dispenseQuantity}</td>
1353
1464
  <td>${refills}</td>
1354
- <td>${startDate}</td>
1355
- <td>${endDate}</td>
1465
+ <td>${startDate}</td>${isActiveSection ? "" : `
1466
+ <td>${endDate}</td>`}
1356
1467
  <td>${status}</td>
1357
1468
  </tr>`;
1358
1469
  }
@@ -1367,28 +1478,26 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1367
1478
  var ImmunizationsTemplate = class _ImmunizationsTemplate {
1368
1479
  /**
1369
1480
  * Generate HTML narrative for Immunization resources
1370
- * @param resource - FHIR Bundle containing Immunization resources
1481
+ * @param resources - FHIR resources array containing Immunization resources
1371
1482
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1372
1483
  * @returns HTML string for rendering
1373
1484
  */
1374
- generateNarrative(resource, timezone) {
1375
- if (resource.entry && Array.isArray(resource.entry)) {
1376
- resource.entry.sort((a, b) => {
1377
- const dateA = a.resource?.occurrenceDateTime;
1378
- const dateB = b.resource?.occurrenceDateTime;
1379
- return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1380
- });
1381
- }
1382
- return _ImmunizationsTemplate.generateStaticNarrative(resource, timezone);
1485
+ generateNarrative(resources, timezone) {
1486
+ resources.sort((a, b) => {
1487
+ const dateA = a.occurrenceDateTime;
1488
+ const dateB = b.occurrenceDateTime;
1489
+ return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1490
+ });
1491
+ return _ImmunizationsTemplate.generateStaticNarrative(resources, timezone);
1383
1492
  }
1384
1493
  /**
1385
1494
  * Internal static implementation that actually generates the narrative
1386
- * @param resource - FHIR Bundle containing Immunization resources
1495
+ * @param resources - FHIR resources array containing Immunization resources
1387
1496
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1388
1497
  * @returns HTML string for rendering
1389
1498
  */
1390
- static generateStaticNarrative(resource, timezone) {
1391
- const templateUtilities = new TemplateUtilities(resource);
1499
+ static generateStaticNarrative(resources, timezone) {
1500
+ const templateUtilities = new TemplateUtilities(resources);
1392
1501
  let html = `
1393
1502
  <table>
1394
1503
  <thead>
@@ -1403,21 +1512,20 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
1403
1512
  </tr>
1404
1513
  </thead>
1405
1514
  <tbody>`;
1406
- if (resource.entry && Array.isArray(resource.entry)) {
1407
- for (const entry of resource.entry) {
1408
- if (entry.resource?.resourceType === "Immunization") {
1409
- const imm = entry.resource;
1410
- html += `
1411
- <tr id="${templateUtilities.narrativeLinkId(imm)}">
1412
- <td>${templateUtilities.codeableConcept(imm.vaccineCode)}</td>
1413
- <td>${imm.status || ""}</td>
1414
- <td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
1415
- <td>${templateUtilities.renderVaccineManufacturer(imm)}</td>
1416
- <td>${imm.lotNumber || ""}</td>
1417
- <td>${templateUtilities.renderNotes(imm.note, timezone)}</td>
1418
- <td>${templateUtilities.renderTime(imm.occurrenceDateTime, timezone)}</td>
1419
- </tr>`;
1420
- }
1515
+ const immunizations = resources.filter((resourceItem) => resourceItem.resourceType === "Immunization");
1516
+ if (immunizations.length > 0) {
1517
+ for (const resourceItem of immunizations) {
1518
+ const imm = resourceItem;
1519
+ html += `
1520
+ <tr id="${templateUtilities.narrativeLinkId(imm)}">
1521
+ <td>${templateUtilities.codeableConcept(imm.vaccineCode)}</td>
1522
+ <td>${imm.status || ""}</td>
1523
+ <td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
1524
+ <td>${templateUtilities.renderVaccineManufacturer(imm)}</td>
1525
+ <td>${imm.lotNumber || ""}</td>
1526
+ <td>${templateUtilities.renderNotes(imm.note, timezone)}</td>
1527
+ <td>${templateUtilities.renderTime(imm.occurrenceDateTime, timezone)}</td>
1528
+ </tr>`;
1421
1529
  }
1422
1530
  }
1423
1531
  html += `
@@ -1431,23 +1539,23 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
1431
1539
  var ProblemListTemplate = class _ProblemListTemplate {
1432
1540
  /**
1433
1541
  * Generate HTML narrative for Problem List
1434
- * @param resource - FHIR Bundle containing Condition resources
1542
+ * @param resources - FHIR Condition resources
1435
1543
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1436
1544
  * @returns HTML string for rendering
1437
1545
  */
1438
- generateNarrative(resource, timezone) {
1439
- return _ProblemListTemplate.generateStaticNarrative(resource, timezone);
1546
+ generateNarrative(resources, timezone) {
1547
+ return _ProblemListTemplate.generateStaticNarrative(resources, timezone);
1440
1548
  }
1441
1549
  /**
1442
1550
  * Internal static implementation that actually generates the narrative
1443
- * @param resource - FHIR Bundle containing Condition resources
1551
+ * @param resources - FHIR Condition resources
1444
1552
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1445
1553
  * @returns HTML string for rendering
1446
1554
  */
1447
- static generateStaticNarrative(resource, timezone) {
1448
- const templateUtilities = new TemplateUtilities(resource);
1555
+ static generateStaticNarrative(resources, timezone) {
1556
+ const templateUtilities = new TemplateUtilities(resources);
1449
1557
  let html = ``;
1450
- const activeConditions = resource.entry?.map((entry) => entry.resource) || [];
1558
+ const activeConditions = resources.map((entry) => entry) || [];
1451
1559
  activeConditions.sort((a, b) => {
1452
1560
  const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
1453
1561
  const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
@@ -1458,7 +1566,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
1458
1566
  <thead>
1459
1567
  <tr>
1460
1568
  <th>Problem</th>
1461
- <th>Severity</th>
1462
1569
  <th>Onset Date</th>
1463
1570
  <th>Recorded Date</th>
1464
1571
  <th>Notes</th>
@@ -1468,7 +1575,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
1468
1575
  for (const cond of activeConditions) {
1469
1576
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
1470
1577
  <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
1471
- <td class="Severity">${templateUtilities.codeableConcept(cond.severity)}</td>
1472
1578
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
1473
1579
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
1474
1580
  <td class="Notes">${templateUtilities.renderNotes(cond.note, timezone)}</td>
@@ -1484,22 +1590,22 @@ var ProblemListTemplate = class _ProblemListTemplate {
1484
1590
  var VitalSignsTemplate = class _VitalSignsTemplate {
1485
1591
  /**
1486
1592
  * Generate HTML narrative for Vital Signs
1487
- * @param resource - FHIR Bundle containing Observation resources
1593
+ * @param resources - FHIR Observation resources
1488
1594
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1489
1595
  * @returns HTML string for rendering
1490
1596
  */
1491
- generateNarrative(resource, timezone) {
1492
- return _VitalSignsTemplate.generateStaticNarrative(resource, timezone);
1597
+ generateNarrative(resources, timezone) {
1598
+ return _VitalSignsTemplate.generateStaticNarrative(resources, timezone);
1493
1599
  }
1494
1600
  /**
1495
1601
  * Internal static implementation that actually generates the narrative
1496
- * @param resource - FHIR Bundle containing Observation resources
1602
+ * @param resources - FHIR Observation resources
1497
1603
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1498
1604
  * @returns HTML string for rendering
1499
1605
  */
1500
- static generateStaticNarrative(resource, timezone) {
1501
- const templateUtilities = new TemplateUtilities(resource);
1502
- const observations = resource.entry?.map((entry) => entry.resource) || [];
1606
+ static generateStaticNarrative(resources, timezone) {
1607
+ const templateUtilities = new TemplateUtilities(resources);
1608
+ const observations = resources.map((entry) => entry) || [];
1503
1609
  observations.sort((a, b) => {
1504
1610
  const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
1505
1611
  const dateB = b.effectiveDateTime || b.effectivePeriod?.start;
@@ -1542,28 +1648,21 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
1542
1648
  var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
1543
1649
  /**
1544
1650
  * Generate HTML narrative for Medical Device resources
1545
- * @param resource - FHIR Bundle containing Device resources
1651
+ * @param resources - FHIR resources array containing Device resources
1546
1652
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1547
1653
  * @returns HTML string for rendering
1548
1654
  */
1549
- generateNarrative(resource, timezone) {
1550
- if (resource.entry && Array.isArray(resource.entry)) {
1551
- resource.entry.sort((a, b) => {
1552
- const dateA = a.resource?.recordedOn;
1553
- const dateB = b.resource?.recordedOn;
1554
- return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1555
- });
1556
- }
1557
- return _MedicalDevicesTemplate.generateStaticNarrative(resource, timezone);
1655
+ generateNarrative(resources, timezone) {
1656
+ return _MedicalDevicesTemplate.generateStaticNarrative(resources, timezone);
1558
1657
  }
1559
1658
  /**
1560
1659
  * Internal static implementation that actually generates the narrative
1561
- * @param resource - FHIR Bundle containing Device resources
1660
+ * @param resources - FHIR resources array containing Device resources
1562
1661
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1563
1662
  * @returns HTML string for rendering
1564
1663
  */
1565
- static generateStaticNarrative(resource, timezone) {
1566
- const templateUtilities = new TemplateUtilities(resource);
1664
+ static generateStaticNarrative(resources, timezone) {
1665
+ const templateUtilities = new TemplateUtilities(resources);
1567
1666
  let html = `
1568
1667
  <table>
1569
1668
  <thead>
@@ -1575,19 +1674,19 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
1575
1674
  </tr>
1576
1675
  </thead>
1577
1676
  <tbody>`;
1578
- if (resource.entry && Array.isArray(resource.entry)) {
1579
- for (const entry of resource.entry) {
1580
- if (entry.resource?.resourceType === "DeviceUseStatement") {
1581
- const dus = entry.resource;
1582
- html += `
1583
- <tr id="${templateUtilities.narrativeLinkId(dus)}">
1584
- <td>${templateUtilities.renderDevice(dus.device)}</td>
1585
- <td>${dus.status || ""}</td>
1586
- <td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
1587
- <td>${templateUtilities.renderRecorded(dus.recordedOn, timezone)}</td>
1588
- </tr>`;
1589
- }
1590
- }
1677
+ const deviceStatements = resources.filter((resourceItem) => resourceItem.resourceType === "DeviceUseStatement").map((resourceItem) => resourceItem).sort((a, b) => {
1678
+ const dateA = a.recordedOn;
1679
+ const dateB = b.recordedOn;
1680
+ return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1681
+ });
1682
+ for (const dus of deviceStatements) {
1683
+ html += `
1684
+ <tr id="${templateUtilities.narrativeLinkId(dus)}">
1685
+ <td>${templateUtilities.renderDevice(dus.device)}</td>
1686
+ <td>${dus.status || ""}</td>
1687
+ <td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
1688
+ <td>${templateUtilities.renderRecorded(dus.recordedOn, timezone)}</td>
1689
+ </tr>`;
1591
1690
  }
1592
1691
  html += `
1593
1692
  </tbody>
@@ -1600,23 +1699,23 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
1600
1699
  var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1601
1700
  /**
1602
1701
  * Generate HTML narrative for Diagnostic Results
1603
- * @param resource - FHIR Bundle containing Observation and DiagnosticReport resources
1702
+ * @param resources - FHIR resources array containing Observation and DiagnosticReport resources
1604
1703
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1605
1704
  * @returns HTML string for rendering
1606
1705
  */
1607
- generateNarrative(resource, timezone) {
1608
- return _DiagnosticResultsTemplate.generateStaticNarrative(resource, timezone);
1706
+ generateNarrative(resources, timezone) {
1707
+ return _DiagnosticResultsTemplate.generateStaticNarrative(resources, timezone);
1609
1708
  }
1610
1709
  /**
1611
1710
  * Internal static implementation that actually generates the narrative
1612
- * @param resource - FHIR Bundle containing Observation and DiagnosticReport resources
1711
+ * @param resources - FHIR resources array containing Observation and DiagnosticReport resources
1613
1712
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1614
1713
  * @returns HTML string for rendering
1615
1714
  */
1616
- static generateStaticNarrative(resource, timezone) {
1617
- const templateUtilities = new TemplateUtilities(resource);
1715
+ static generateStaticNarrative(resources, timezone) {
1716
+ const templateUtilities = new TemplateUtilities(resources);
1618
1717
  let html = "";
1619
- const observations = this.getObservations(resource);
1718
+ const observations = this.getObservations(resources);
1620
1719
  if (observations.length > 0) {
1621
1720
  observations.sort((a, b) => {
1622
1721
  const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
@@ -1625,7 +1724,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1625
1724
  });
1626
1725
  html += this.renderObservations(templateUtilities, observations, timezone);
1627
1726
  }
1628
- const diagnosticReports = this.getDiagnosticReports(resource);
1727
+ const diagnosticReports = this.getDiagnosticReports(resources);
1629
1728
  if (diagnosticReports.length > 0) {
1630
1729
  diagnosticReports.sort((a, b) => {
1631
1730
  const dateA = a.issued;
@@ -1637,26 +1736,20 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1637
1736
  return html;
1638
1737
  }
1639
1738
  /**
1640
- * Extract Observation resources from the bundle
1641
- * @param resource - FHIR Bundle
1642
- * @returns Array of Observation resources
1643
- */
1644
- static getObservations(resource) {
1645
- if (!resource.entry || !Array.isArray(resource.entry)) {
1646
- return [];
1647
- }
1648
- return resource.entry.filter((entry) => entry.resource?.resourceType === "Observation").map((entry) => entry.resource);
1739
+ * Get all Observation resources from the resource array
1740
+ * @param resources - FHIR resources array
1741
+ * @returns Array of Observation resources
1742
+ */
1743
+ static getObservations(resources) {
1744
+ return resources.filter((resourceItem) => resourceItem.resourceType === "Observation").map((resourceItem) => resourceItem);
1649
1745
  }
1650
1746
  /**
1651
- * Extract DiagnosticReport resources from the bundle
1652
- * @param resource - FHIR Bundle
1747
+ * Get all DiagnosticReport resources from the resource array
1748
+ * @param resources - FHIR resources array
1653
1749
  * @returns Array of DiagnosticReport resources
1654
1750
  */
1655
- static getDiagnosticReports(resource) {
1656
- if (!resource.entry || !Array.isArray(resource.entry)) {
1657
- return [];
1658
- }
1659
- return resource.entry.filter((entry) => entry.resource?.resourceType === "DiagnosticReport").map((entry) => entry.resource);
1751
+ static getDiagnosticReports(resources) {
1752
+ return resources.filter((resourceItem) => resourceItem.resourceType === "DiagnosticReport").map((resourceItem) => resourceItem);
1660
1753
  }
1661
1754
  /**
1662
1755
  * Render HTML table for Observation resources
@@ -1712,7 +1805,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1712
1805
  <thead>
1713
1806
  <tr>
1714
1807
  <th>Report</th>
1715
- <th>Status</th>
1716
1808
  <th>Category</th>
1717
1809
  <th>Result</th>
1718
1810
  <th>Issued</th>
@@ -1727,7 +1819,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1727
1819
  html += `
1728
1820
  <tr id="${templateUtilities.narrativeLinkId(report)}">
1729
1821
  <td>${templateUtilities.codeableConcept(report.code)}</td>
1730
- <td>${report.status || ""}</td>
1731
1822
  <td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
1732
1823
  <td>${resultCount}</td>
1733
1824
  <td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
@@ -1744,26 +1835,26 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1744
1835
  var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
1745
1836
  /**
1746
1837
  * Generate HTML narrative for Procedure resources
1747
- * @param resource - FHIR Bundle containing Procedure resources
1838
+ * @param resources - FHIR Procedure resources
1748
1839
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1749
1840
  * @returns HTML string for rendering
1750
1841
  */
1751
- generateNarrative(resource, timezone) {
1752
- resource.entry?.sort((a, b) => {
1753
- const dateA = a.resource.performedDateTime || a.resource.performedPeriod?.start;
1754
- const dateB = b.resource.performedDateTime || b.resource.performedPeriod?.start;
1842
+ generateNarrative(resources, timezone) {
1843
+ resources.sort((a, b) => {
1844
+ const dateA = a.performedDateTime || a.performedPeriod?.start;
1845
+ const dateB = b.performedDateTime || b.performedPeriod?.start;
1755
1846
  return dateA && dateB ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1756
1847
  });
1757
- return _HistoryOfProceduresTemplate.generateStaticNarrative(resource, timezone);
1848
+ return _HistoryOfProceduresTemplate.generateStaticNarrative(resources, timezone);
1758
1849
  }
1759
1850
  /**
1760
1851
  * Internal static implementation that actually generates the narrative
1761
- * @param resource - FHIR Bundle containing Procedure resources
1852
+ * @param resources - FHIR Procedure resources
1762
1853
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1763
1854
  * @returns HTML string for rendering
1764
1855
  */
1765
- static generateStaticNarrative(resource, timezone) {
1766
- const templateUtilities = new TemplateUtilities(resource);
1856
+ static generateStaticNarrative(resources, timezone) {
1857
+ const templateUtilities = new TemplateUtilities(resources);
1767
1858
  let html = `
1768
1859
  <table>
1769
1860
  <thead>
@@ -1774,16 +1865,14 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
1774
1865
  </tr>
1775
1866
  </thead>
1776
1867
  <tbody>`;
1777
- if (resource.entry && Array.isArray(resource.entry)) {
1778
- for (const entry of resource.entry) {
1779
- const proc = entry.resource;
1780
- html += `
1781
- <tr id="${templateUtilities.narrativeLinkId(proc)}">
1782
- <td>${templateUtilities.codeableConcept(proc.code, "display")}</td>
1783
- <td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
1784
- <td>${proc.performedDateTime ? templateUtilities.renderTime(proc.performedDateTime, timezone) : proc.performedPeriod ? templateUtilities.renderPeriod(proc.performedPeriod, timezone) : ""}</td>
1785
- </tr>`;
1786
- }
1868
+ for (const resourceItem of resources) {
1869
+ const proc = resourceItem;
1870
+ html += `
1871
+ <tr id="${templateUtilities.narrativeLinkId(proc)}">
1872
+ <td>${templateUtilities.codeableConcept(proc.code, "display")}</td>
1873
+ <td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
1874
+ <td>${proc.performedDateTime ? templateUtilities.renderTime(proc.performedDateTime, timezone) : proc.performedPeriod ? templateUtilities.renderPeriod(proc.performedPeriod, timezone) : ""}</td>
1875
+ </tr>`;
1787
1876
  }
1788
1877
  html += `
1789
1878
  </tbody>
@@ -1796,22 +1885,22 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
1796
1885
  var SocialHistoryTemplate = class _SocialHistoryTemplate {
1797
1886
  /**
1798
1887
  * Generate HTML narrative for Social History
1799
- * @param resource - FHIR Bundle containing Observation resources
1888
+ * @param resources - FHIR Observation resources
1800
1889
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1801
1890
  * @returns HTML string for rendering
1802
1891
  */
1803
- generateNarrative(resource, timezone) {
1804
- return _SocialHistoryTemplate.generateStaticNarrative(resource, timezone);
1892
+ generateNarrative(resources, timezone) {
1893
+ return _SocialHistoryTemplate.generateStaticNarrative(resources, timezone);
1805
1894
  }
1806
1895
  /**
1807
1896
  * Internal static implementation that actually generates the narrative
1808
- * @param resource - FHIR Bundle containing Observation resources
1897
+ * @param resources - FHIR Observation resources
1809
1898
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1810
1899
  * @returns HTML string for rendering
1811
1900
  */
1812
- static generateStaticNarrative(resource, timezone) {
1813
- const templateUtilities = new TemplateUtilities(resource);
1814
- const observations = resource.entry?.map((entry) => entry.resource) || [];
1901
+ static generateStaticNarrative(resources, timezone) {
1902
+ const templateUtilities = new TemplateUtilities(resources);
1903
+ const observations = resources.map((entry) => entry) || [];
1815
1904
  observations.sort((a, b) => {
1816
1905
  const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
1817
1906
  const dateB = b.effectiveDateTime || b.effectivePeriod?.start;
@@ -1850,14 +1939,14 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
1850
1939
  var PastHistoryOfIllnessTemplate = class {
1851
1940
  /**
1852
1941
  * Generate HTML narrative for Past History of Illnesses
1853
- * @param resource - FHIR Bundle containing Condition resources
1942
+ * @param resources - FHIR Condition resources
1854
1943
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1855
1944
  * @returns HTML string for rendering
1856
1945
  */
1857
- generateNarrative(resource, timezone) {
1858
- const templateUtilities = new TemplateUtilities(resource);
1946
+ generateNarrative(resources, timezone) {
1947
+ const templateUtilities = new TemplateUtilities(resources);
1859
1948
  let html = ``;
1860
- const resolvedConditions = resource.entry?.map((entry) => entry.resource) || [];
1949
+ const resolvedConditions = resources.map((entry) => entry) || [];
1861
1950
  resolvedConditions.sort((a, b) => {
1862
1951
  const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
1863
1952
  const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
@@ -1868,7 +1957,6 @@ var PastHistoryOfIllnessTemplate = class {
1868
1957
  <thead>
1869
1958
  <tr>
1870
1959
  <th>Problem</th>
1871
- <th>Severity</th>
1872
1960
  <th>Onset Date</th>
1873
1961
  <th>Recorded Date</th>
1874
1962
  <th>Resolved Date</th>
@@ -1879,7 +1967,6 @@ var PastHistoryOfIllnessTemplate = class {
1879
1967
  for (const cond of resolvedConditions) {
1880
1968
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
1881
1969
  <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
1882
- <td class="Severity">${templateUtilities.codeableConcept(cond.severity)}</td>
1883
1970
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
1884
1971
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
1885
1972
  <td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
@@ -1896,13 +1983,13 @@ var PastHistoryOfIllnessTemplate = class {
1896
1983
  var PlanOfCareTemplate = class {
1897
1984
  /**
1898
1985
  * Generate HTML narrative for Plan of Care
1899
- * @param resource - FHIR Bundle containing CarePlan resources
1986
+ * @param resources - FHIR CarePlan resources
1900
1987
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1901
1988
  * @returns HTML string for rendering
1902
1989
  */
1903
- generateNarrative(resource, timezone) {
1904
- const templateUtilities = new TemplateUtilities(resource);
1905
- const carePlans = resource.entry?.map((entry) => entry.resource) || [];
1990
+ generateNarrative(resources, timezone) {
1991
+ const templateUtilities = new TemplateUtilities(resources);
1992
+ const carePlans = resources.map((entry) => entry) || [];
1906
1993
  carePlans.sort((a, b) => {
1907
1994
  const endA = a.period?.end ? new Date(a.period?.end).getTime() : 0;
1908
1995
  const endB = b.period?.end ? new Date(b.period?.end).getTime() : 0;
@@ -1941,37 +2028,35 @@ var PlanOfCareTemplate = class {
1941
2028
  var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
1942
2029
  /**
1943
2030
  * Generate HTML narrative for Functional Status
1944
- * @param resource - FHIR Bundle containing Observation resources
2031
+ * @param resources - FHIR resources array containing Observation resources
1945
2032
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1946
2033
  * @returns HTML string for rendering
1947
2034
  */
1948
- generateNarrative(resource, timezone) {
1949
- return _FunctionalStatusTemplate.generateStaticNarrative(resource, timezone);
2035
+ generateNarrative(resources, timezone) {
2036
+ return _FunctionalStatusTemplate.generateStaticNarrative(resources, timezone);
1950
2037
  }
1951
2038
  /**
1952
2039
  * Internal static implementation that actually generates the narrative
1953
- * @param resource - FHIR Bundle containing Observation resources
2040
+ * @param resources - FHIR resources array containing Observation resources
1954
2041
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1955
2042
  * @returns HTML string for rendering
1956
2043
  */
1957
- static generateStaticNarrative(resource, timezone) {
1958
- const templateUtilities = new TemplateUtilities(resource);
2044
+ static generateStaticNarrative(resources, timezone) {
2045
+ const templateUtilities = new TemplateUtilities(resources);
1959
2046
  let html = ``;
1960
2047
  const activeConditions = [];
1961
2048
  const clinicalImpressions = [];
1962
- if (resource.entry && Array.isArray(resource.entry)) {
1963
- for (const entry of resource.entry) {
1964
- if (entry.resource?.resourceType === "Condition") {
1965
- const cond = entry.resource;
1966
- const isResolved = cond.clinicalStatus?.coding?.some(
1967
- (c) => c.code === "resolved" || c.code === "inactive" || c.display?.toLowerCase().includes("resolved")
1968
- );
1969
- if (!isResolved) {
1970
- activeConditions.push(cond);
1971
- }
1972
- } else if (entry.resource?.resourceType === "ClinicalImpression") {
1973
- clinicalImpressions.push(entry.resource);
2049
+ for (const resourceItem of resources) {
2050
+ if (resourceItem.resourceType === "Condition") {
2051
+ const cond = resourceItem;
2052
+ const isResolved = cond.clinicalStatus?.coding?.some(
2053
+ (c) => c.code === "resolved" || c.code === "inactive" || c.display?.toLowerCase().includes("resolved")
2054
+ );
2055
+ if (!isResolved) {
2056
+ activeConditions.push(cond);
1974
2057
  }
2058
+ } else if (resourceItem.resourceType === "ClinicalImpression") {
2059
+ clinicalImpressions.push(resourceItem);
1975
2060
  }
1976
2061
  }
1977
2062
  activeConditions.sort((a, b) => {
@@ -1990,7 +2075,6 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
1990
2075
  <thead>
1991
2076
  <tr>
1992
2077
  <th>Problem</th>
1993
- <th>Severity</th>
1994
2078
  <th>Onset Date</th>
1995
2079
  <th>Recorded Date</th>
1996
2080
  <th>Notes</th>
@@ -2000,7 +2084,6 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
2000
2084
  for (const cond of activeConditions) {
2001
2085
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
2002
2086
  <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
2003
- <td class="Severity">${templateUtilities.codeableConcept(cond.severity)}</td>
2004
2087
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2005
2088
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2006
2089
  <td class="Notes">${templateUtilities.renderNotes(cond.note, timezone, { styled: true, warning: true })}</td>
@@ -2070,22 +2153,22 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
2070
2153
  var PregnancyTemplate = class _PregnancyTemplate {
2071
2154
  /**
2072
2155
  * Generate HTML narrative for Pregnancy
2073
- * @param resource - FHIR Bundle containing Observation resources
2156
+ * @param resources - FHIR Observation resources
2074
2157
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2075
2158
  * @returns HTML string for rendering
2076
2159
  */
2077
- generateNarrative(resource, timezone) {
2078
- return _PregnancyTemplate.generateStaticNarrative(resource, timezone);
2160
+ generateNarrative(resources, timezone) {
2161
+ return _PregnancyTemplate.generateStaticNarrative(resources, timezone);
2079
2162
  }
2080
2163
  /**
2081
2164
  * Internal static implementation that actually generates the narrative
2082
- * @param resource - FHIR Bundle containing Observation resources
2165
+ * @param resources - FHIR Observation resources
2083
2166
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2084
2167
  * @returns HTML string for rendering
2085
2168
  */
2086
- static generateStaticNarrative(resource, timezone) {
2087
- const templateUtilities = new TemplateUtilities(resource);
2088
- const observations = resource.entry?.map((entry) => entry.resource) || [];
2169
+ static generateStaticNarrative(resources, timezone) {
2170
+ const templateUtilities = new TemplateUtilities(resources);
2171
+ const observations = resources.map((entry) => entry) || [];
2089
2172
  observations.sort((a, b) => {
2090
2173
  const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
2091
2174
  const dateB = b.effectiveDateTime || b.effectivePeriod?.start;
@@ -2101,8 +2184,8 @@ var PregnancyTemplate = class _PregnancyTemplate {
2101
2184
  </tr>
2102
2185
  </thead>
2103
2186
  <tbody>`;
2104
- for (const resource2 of observations) {
2105
- const obs = resource2;
2187
+ for (const resource of observations) {
2188
+ const obs = resource;
2106
2189
  html += `
2107
2190
  <tr id="${templateUtilities.narrativeLinkId(obs)}">
2108
2191
  <td>${templateUtilities.extractPregnancyStatus(obs)}</td>
@@ -2121,29 +2204,27 @@ var PregnancyTemplate = class _PregnancyTemplate {
2121
2204
  var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
2122
2205
  /**
2123
2206
  * Generate HTML narrative for Advance Directives
2124
- * @param resource - FHIR Bundle containing Advance Directive resources
2207
+ * @param resources - FHIR Consent resources
2125
2208
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2126
2209
  * @returns HTML string for rendering
2127
2210
  */
2128
- generateNarrative(resource, timezone) {
2129
- if (resource.entry && Array.isArray(resource.entry)) {
2130
- resource.entry.sort((a, b) => {
2131
- const dateA = new Date(a.resource.dateTime || 0);
2132
- const dateB = new Date(b.resource.dateTime || 0);
2133
- return dateB.getTime() - dateA.getTime();
2134
- });
2135
- }
2136
- return _AdvanceDirectivesTemplate.generateStaticNarrative(resource, timezone);
2211
+ generateNarrative(resources, timezone) {
2212
+ resources.sort((a, b) => {
2213
+ const dateA = new Date(a.dateTime || 0);
2214
+ const dateB = new Date(b.dateTime || 0);
2215
+ return dateB.getTime() - dateA.getTime();
2216
+ });
2217
+ return _AdvanceDirectivesTemplate.generateStaticNarrative(resources, timezone);
2137
2218
  }
2138
2219
  /**
2139
2220
  * Internal static implementation that actually generates the narrative
2140
- * @param resource - FHIR Bundle containing Advance Directive resources
2221
+ * @param resources - FHIR Consent resources
2141
2222
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2142
2223
  * @returns HTML string for rendering
2143
2224
  */
2144
2225
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2145
- static generateStaticNarrative(resource, timezone) {
2146
- const templateUtilities = new TemplateUtilities(resource);
2226
+ static generateStaticNarrative(resources, timezone) {
2227
+ const templateUtilities = new TemplateUtilities(resources);
2147
2228
  let html = `
2148
2229
  <table>
2149
2230
  <thead>
@@ -2155,17 +2236,15 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
2155
2236
  </tr>
2156
2237
  </thead>
2157
2238
  <tbody>`;
2158
- if (resource.entry && Array.isArray(resource.entry)) {
2159
- for (const entry of resource.entry) {
2160
- const consent = entry.resource;
2161
- html += `
2162
- <tr id="${templateUtilities.narrativeLinkId(consent)}">
2163
- <td>${templateUtilities.codeableConcept(consent.scope, "display")}</td>
2164
- <td>${consent.status || ""}</td>
2165
- <td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
2166
- <td>${consent.dateTime || ""}</td>
2167
- </tr>`;
2168
- }
2239
+ for (const resourceItem of resources) {
2240
+ const consent = resourceItem;
2241
+ html += `
2242
+ <tr id="${templateUtilities.narrativeLinkId(consent)}">
2243
+ <td>${templateUtilities.codeableConcept(consent.scope, "display")}</td>
2244
+ <td>${consent.status || ""}</td>
2245
+ <td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
2246
+ <td>${consent.dateTime || ""}</td>
2247
+ </tr>`;
2169
2248
  }
2170
2249
  html += `
2171
2250
  </tbody>
@@ -2179,16 +2258,16 @@ var TypeScriptTemplateMapper = class {
2179
2258
  /**
2180
2259
  * Generates HTML narrative for a specific IPS section
2181
2260
  * @param section - The IPS section
2182
- * @param resource - FHIR Bundle containing resources
2261
+ * @param resources - FHIR resources
2183
2262
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2184
2263
  * @returns HTML string for rendering
2185
2264
  */
2186
- static generateNarrative(section, resource, timezone) {
2265
+ static generateNarrative(section, resources, timezone) {
2187
2266
  const templateClass = this.sectionToTemplate[section];
2188
2267
  if (!templateClass) {
2189
2268
  throw new Error(`No template found for section: ${section}`);
2190
2269
  }
2191
- return templateClass.generateNarrative(resource, timezone);
2270
+ return templateClass.generateNarrative(resources, timezone);
2192
2271
  }
2193
2272
  };
2194
2273
  // Map of section types to their template classes
@@ -2251,14 +2330,7 @@ var NarrativeGenerator = class {
2251
2330
  return void 0;
2252
2331
  }
2253
2332
  try {
2254
- const bundle = {
2255
- resourceType: "Bundle",
2256
- type: "collection",
2257
- entry: resources.map((resource) => ({
2258
- resource
2259
- }))
2260
- };
2261
- const content = TypeScriptTemplateMapper.generateNarrative(section, bundle, timezone);
2333
+ const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone);
2262
2334
  if (!content) {
2263
2335
  return void 0;
2264
2336
  }
@@ -2343,13 +2415,16 @@ var ComprehensiveIPSCompositionBuilder = class {
2343
2415
  /**
2344
2416
  * sets the patient resource for the IPS Composition.
2345
2417
  * This is not needed if you are calling read_bundle, but can be used to set the patient resource directly.
2346
- * @param patient - FHIR Patient resource to set
2418
+ * @param patients - FHIR Patient resource to set
2347
2419
  */
2348
- setPatient(patient) {
2349
- if (!patient || patient.resourceType !== "Patient") {
2420
+ setPatient(patients) {
2421
+ if (!Array.isArray(patients)) {
2422
+ patients = [patients];
2423
+ }
2424
+ if (patients.length === 0 || !patients.every((patient) => patient.resourceType === "Patient")) {
2350
2425
  throw new Error("Invalid Patient resource");
2351
2426
  }
2352
- this.patient = patient;
2427
+ this.patients = patients;
2353
2428
  return this;
2354
2429
  }
2355
2430
  /**
@@ -2407,21 +2482,26 @@ var ComprehensiveIPSCompositionBuilder = class {
2407
2482
  if (!bundle.entry) {
2408
2483
  return this;
2409
2484
  }
2410
- const patientEntry = bundle.entry.find((e) => e.resource?.resourceType === "Patient");
2411
- if (!patientEntry || !patientEntry.resource) {
2485
+ const patientEntries = [];
2486
+ const resources = [];
2487
+ bundle.entry.forEach((e) => {
2488
+ if (e.resource?.resourceType === "Patient") {
2489
+ patientEntries.push(e.resource);
2490
+ this.resources.add(e.resource);
2491
+ } else if (e.resource) {
2492
+ resources.push(e.resource);
2493
+ }
2494
+ });
2495
+ if (patientEntries.length === 0) {
2412
2496
  throw new Error("Patient resource not found in the bundle");
2413
2497
  }
2414
- this.patient = patientEntry.resource;
2415
- const resources = bundle.entry.map((e) => e.resource);
2498
+ this.patients = patientEntries;
2416
2499
  for (const sectionType of Object.values(IPSSections)) {
2417
- const resourceTypesForSection = IPSSectionResourceHelper.getResourceTypesForSection(sectionType);
2418
- const customFilter = IPSSectionResourceHelper.getResourceFilterForSection(sectionType);
2419
- let sectionResources = resources.filter(
2420
- (r) => r && typeof r.resourceType === "string" && resourceTypesForSection.includes(r.resourceType)
2421
- );
2422
- if (customFilter) {
2423
- sectionResources = sectionResources.filter((resource) => resource && customFilter(resource));
2500
+ if (sectionType === "Patient" /* PATIENT */) {
2501
+ continue;
2424
2502
  }
2503
+ const sectionFilter = IPSSectionResourceHelper.getResourceFilterForSection(sectionType);
2504
+ const sectionResources = resources.filter((resource) => sectionFilter(resource));
2425
2505
  await this.addSectionAsync(sectionType, sectionResources, timezone);
2426
2506
  }
2427
2507
  return this;
@@ -2432,16 +2512,18 @@ var ComprehensiveIPSCompositionBuilder = class {
2432
2512
  * @param authorOrganizationName - Name of the authoring organization
2433
2513
  * @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
2434
2514
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2515
+ * @param patientId - Optional patient ID to use as primary patient for composition reference
2435
2516
  */
2436
- async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone) {
2517
+ async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId) {
2437
2518
  if (baseUrl.endsWith("/")) {
2438
2519
  baseUrl = baseUrl.slice(0, -1);
2439
2520
  }
2440
- if (!this.patient) {
2521
+ if (!this.patients) {
2441
2522
  throw new Error("Patient resource must be set before building the bundle");
2442
2523
  }
2524
+ const primaryPatientId = patientId ?? this.patients[0].id;
2443
2525
  const composition = {
2444
- id: `Composition-${this.patient.id}`,
2526
+ id: `Composition-${primaryPatientId}`,
2445
2527
  resourceType: "Composition",
2446
2528
  status: "final",
2447
2529
  type: {
@@ -2452,7 +2534,7 @@ var ComprehensiveIPSCompositionBuilder = class {
2452
2534
  }]
2453
2535
  },
2454
2536
  subject: {
2455
- reference: `Patient/${this.patient.id}`
2537
+ reference: `Patient/${primaryPatientId}`
2456
2538
  },
2457
2539
  author: [{
2458
2540
  reference: `Organization/${authorOrganizationId}`,
@@ -2464,7 +2546,7 @@ var ComprehensiveIPSCompositionBuilder = class {
2464
2546
  section: this.sections,
2465
2547
  text: await NarrativeGenerator.generateNarrativeAsync(
2466
2548
  "Patient" /* PATIENT */,
2467
- [this.patient],
2549
+ this.patients,
2468
2550
  timezone,
2469
2551
  true
2470
2552
  )
@@ -2483,9 +2565,11 @@ var ComprehensiveIPSCompositionBuilder = class {
2483
2565
  fullUrl: `${baseUrl}/Composition/${composition.id}`,
2484
2566
  resource: composition
2485
2567
  });
2486
- bundle.entry?.push({
2487
- fullUrl: `${baseUrl}/Patient/${this.patient.id}`,
2488
- resource: this.patient
2568
+ this.patients.forEach((patient) => {
2569
+ bundle.entry?.push({
2570
+ fullUrl: `${baseUrl}/Patient/${patient.id}`,
2571
+ resource: patient
2572
+ });
2489
2573
  });
2490
2574
  this.resources.forEach((resource) => {
2491
2575
  if (resource.resourceType !== "Patient") {