@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.js CHANGED
@@ -75,35 +75,28 @@ var SOCIAL_HISTORY_LOINC_CODES = {
75
75
  "72166-2": "Tobacco Use",
76
76
  "74013-4": "Alcohol Use"
77
77
  };
78
+ var BLOOD_PRESSURE_LOINC_CODES = {
79
+ OBSERVATION: "85354-9",
80
+ SYSTOLIC: "8480-6",
81
+ DIASTOLIC: "8462-4"
82
+ };
78
83
 
79
84
  // src/structures/ips_section_resource_map.ts
80
- var IPSSectionResourceMap = {
81
- ["Patient" /* PATIENT */]: ["Patient"],
82
- ["AllergyIntoleranceSection" /* ALLERGIES */]: ["AllergyIntolerance"],
83
- ["MedicationSummarySection" /* MEDICATIONS */]: ["MedicationRequest", "MedicationStatement", "Medication"],
84
- // Medication resource is needed for identifying name of medication
85
- ["ProblemSection" /* PROBLEMS */]: ["Condition"],
86
- ["ImmunizationSection" /* IMMUNIZATIONS */]: ["Immunization", "Organization"],
87
- // Immunization can include Organization as a related resource
88
- ["VitalSignsSection" /* VITAL_SIGNS */]: ["Observation"],
89
- ["MedicalDeviceSection" /* MEDICAL_DEVICES */]: ["DeviceUseStatement", "Device"],
90
- // Device resource is used for medical devices name
91
- ["ResultsSection" /* DIAGNOSTIC_REPORTS */]: ["DiagnosticReport", "Observation"],
92
- ["HistoryOfProceduresSection" /* PROCEDURES */]: ["Procedure"],
93
- ["SocialHistorySection" /* SOCIAL_HISTORY */]: ["Observation"],
94
- ["HistoryOfPregnancySection" /* PREGNANCY_HISTORY */]: ["Observation"],
95
- ["FunctionalStatusSection" /* FUNCTIONAL_STATUS */]: ["Condition", "ClinicalImpression"],
96
- ["HistoryOfPastIllnessSection" /* MEDICAL_HISTORY */]: ["Condition"],
97
- ["PlanOfCareSection" /* CARE_PLAN */]: ["CarePlan"],
98
- ["AdvanceDirectivesSection" /* ADVANCE_DIRECTIVES */]: ["Consent"]
99
- };
100
85
  var IPSSectionResourceFilters = {
86
+ // Patient section: only Patient resource
87
+ ["Patient" /* PATIENT */]: (resource) => resource.resourceType === "Patient",
88
+ // Only include allergies
89
+ ["AllergyIntoleranceSection" /* ALLERGIES */]: (resource) => resource.resourceType === "AllergyIntolerance",
90
+ // includes MedicationRequest, MedicationStatement. Medication is needed for medication names
91
+ ["MedicationSummarySection" /* MEDICATIONS */]: (resource) => ["MedicationRequest", "MedicationStatement", "Medication"].includes(resource.resourceType),
101
92
  // Only include active conditions
102
93
  ["ProblemSection" /* PROBLEMS */]: (resource) => resource.resourceType === "Condition" && resource.clinicalStatus?.coding?.some((c) => !["inactive", "resolved"].includes(c.code)),
103
94
  // Only include completed immunizations
104
95
  ["ImmunizationSection" /* IMMUNIZATIONS */]: (resource) => resource.resourceType === "Immunization" && resource.status === "completed" || resource.resourceType === "Organization",
105
96
  // Only include vital sign Observations (category.coding contains 'vital-signs')
106
97
  ["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Observation" && resource.category?.some((cat) => cat.coding?.some((c) => c.code === "vital-signs")),
98
+ // Includes DeviceUseStatement. Device is needed for linked device details
99
+ ["MedicalDeviceSection" /* MEDICAL_DEVICES */]: (resource) => ["DeviceUseStatement", "Device"].includes(resource.resourceType),
107
100
  // Only include finalized diagnostic reports
108
101
  ["ResultsSection" /* DIAGNOSTIC_REPORTS */]: (resource) => ["DiagnosticReport", "Observation"].includes(resource.resourceType) && resource.status === "final",
109
102
  // Only include completed procedures
@@ -119,14 +112,9 @@ var IPSSectionResourceFilters = {
119
112
  // Only include active care plans
120
113
  ["PlanOfCareSection" /* CARE_PLAN */]: (resource) => resource.resourceType === "CarePlan" && resource.status === "active",
121
114
  // Only include active advance directives (Consent resources)
122
- ["AdvanceDirectivesSection" /* ADVANCE_DIRECTIVES */]: (resource) => resource.resourceType === "Consent" && resource.status === "active",
123
- // Patient section: only Patient resource
124
- ["Patient" /* PATIENT */]: (resource) => resource.resourceType === "Patient"
115
+ ["AdvanceDirectivesSection" /* ADVANCE_DIRECTIVES */]: (resource) => resource.resourceType === "Consent" && resource.status === "active"
125
116
  };
126
117
  var IPSSectionResourceHelper = class {
127
- static getResourceTypesForSection(section) {
128
- return IPSSectionResourceMap[section] || [];
129
- }
130
118
  static getResourceFilterForSection(section) {
131
119
  return IPSSectionResourceFilters[section];
132
120
  }
@@ -136,11 +124,11 @@ var IPSSectionResourceHelper = class {
136
124
  import { DateTime } from "luxon";
137
125
  var TemplateUtilities = class {
138
126
  /**
139
- * Constructor to initialize the TemplateUtilities with a FHIR Bundle
140
- * @param bundle - FHIR Bundle containing resources
127
+ * Constructor to initialize the TemplateUtilities with a FHIR resources
128
+ * @param resources - FHIR resources
141
129
  */
142
- constructor(bundle) {
143
- this.bundle = bundle;
130
+ constructor(resources) {
131
+ this.resources = resources;
144
132
  }
145
133
  /**
146
134
  * Formats a CodeableConcept object
@@ -171,7 +159,7 @@ var TemplateUtilities = class {
171
159
  return "";
172
160
  }
173
161
  resolveReference(ref) {
174
- if (!ref || !this.bundle || !this.bundle.entry) {
162
+ if (!ref || !this.resources) {
175
163
  return null;
176
164
  }
177
165
  const referenceParts = ref.reference?.split("/");
@@ -180,10 +168,10 @@ var TemplateUtilities = class {
180
168
  }
181
169
  const referenceResourceType = referenceParts[0];
182
170
  const referenceResourceId = referenceParts[1];
183
- const resource = this.bundle.entry.find((entry) => {
184
- return entry.resource && entry.resource.resourceType === referenceResourceType && entry.resource.id === referenceResourceId;
171
+ const resource = this.resources.find((entry) => {
172
+ return entry.resourceType === referenceResourceType && entry.id === referenceResourceId;
185
173
  });
186
- return resource ? resource.resource : null;
174
+ return resource ? resource : null;
187
175
  }
188
176
  /**
189
177
  * Renders a Device reference
@@ -502,6 +490,28 @@ var TemplateUtilities = class {
502
490
  return "";
503
491
  }
504
492
  extractObservationValue(observation) {
493
+ if (observation.code && observation.code.coding && "component" in observation && Array.isArray(observation.component)) {
494
+ const bpCode = observation.code.coding.find(
495
+ (c) => c.code === BLOOD_PRESSURE_LOINC_CODES.OBSERVATION
496
+ );
497
+ if (bpCode) {
498
+ const systolicComponent = observation.component?.find(
499
+ (c) => c.code?.coding?.some(
500
+ (cc) => cc.code === BLOOD_PRESSURE_LOINC_CODES.SYSTOLIC
501
+ )
502
+ );
503
+ const diastolicComponent = observation.component?.find(
504
+ (c) => c.code?.coding?.some(
505
+ (cc) => cc.code === BLOOD_PRESSURE_LOINC_CODES.DIASTOLIC
506
+ )
507
+ );
508
+ if (systolicComponent && diastolicComponent) {
509
+ const systolic = this.extractObservationValue(systolicComponent);
510
+ const diastolic = this.extractObservationValue(diastolicComponent);
511
+ return `${systolic}/${diastolic}`;
512
+ }
513
+ }
514
+ }
505
515
  const valueFields = [
506
516
  "valueString",
507
517
  "valueInteger",
@@ -732,7 +742,7 @@ var TemplateUtilities = class {
732
742
  if (parts.length === 2) {
733
743
  const resourceType = parts[0];
734
744
  const resourceId = parts[1];
735
- const resource = this.bundle.entry?.find((entry) => entry.resource?.resourceType === resourceType && entry.resource?.id === resourceId);
745
+ const resource = this.resources?.find((resource2) => resource2.resourceType === resourceType && resource2.id === resourceId);
736
746
  if (resource) {
737
747
  return `${resourceType}/${resourceId}`;
738
748
  }
@@ -772,48 +782,96 @@ var TemplateUtilities = class {
772
782
  // src/narratives/templates/typescript/PatientTemplate.ts
773
783
  var PatientTemplate = class _PatientTemplate {
774
784
  /**
775
- * Generate HTML narrative for Patient resource
776
- * @param resource - FHIR Bundle containing Patient resource
785
+ * Generate HTML narrative for Patient resources
786
+ * @param resources - FHIR Patient resources
777
787
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
778
788
  * @returns HTML string for rendering
779
789
  */
780
- generateNarrative(resource, timezone) {
781
- return _PatientTemplate.generateStaticNarrative(resource, timezone);
790
+ generateNarrative(resources, timezone) {
791
+ return _PatientTemplate.generateStaticNarrative(resources, timezone);
782
792
  }
783
793
  /**
784
794
  * Internal static implementation that actually generates the narrative
785
- * @param resource - FHIR Bundle containing Patient resource
795
+ * @param resources - FHIR Patient resources
786
796
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
787
797
  * @returns HTML string for rendering
788
798
  */
789
799
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
790
- static generateStaticNarrative(resource, timezone) {
791
- const templateUtilities = new TemplateUtilities(resource);
792
- let html = "";
793
- for (const entry of resource.entry || []) {
794
- if (entry.resource?.resourceType === "Patient") {
795
- const patient = entry.resource;
796
- html += `
797
- <div>
798
- <ul>
799
- <li><strong>Name(s):</strong>${this.renderNames(patient)}</li>
800
- <li><strong>Gender:</strong>${patient.gender ? this.capitalize(patient.gender) : ""}</li>
801
- <li><strong>Date of Birth:</strong>${patient.birthDate || ""}</li>
802
- <li><strong>Identifier(s):</strong>${this.renderIdentifiers(patient)}</li>
803
- <li><strong>Telecom:</strong><ul>${this.renderTelecom(patient)}</ul></li>
804
- <li><strong>Address(es):</strong>${this.renderAddresses(patient)}</li>
805
- <li><strong>Marital Status:</strong> ${patient.maritalStatus?.text || ""}</li>
806
- <li><strong>Deceased:</strong>${this.renderDeceased(patient)}</li>
807
- <li><strong>Language(s):</strong>${this.renderCommunication(templateUtilities, patient)}</li>
808
- </ul>
809
- </div>`;
800
+ static generateStaticNarrative(resources, timezone) {
801
+ const templateUtilities = new TemplateUtilities(resources);
802
+ const combinedPatient = this.combinePatients(resources);
803
+ return `<div>
804
+ <ul>
805
+ <li><strong>Name(s):</strong>${this.renderNames(combinedPatient)}</li>
806
+ <li><strong>Gender:</strong>${combinedPatient.gender ? this.capitalize(combinedPatient.gender) : ""}</li>
807
+ <li><strong>Date of Birth:</strong>${combinedPatient.birthDate || ""}</li>
808
+ <li><strong>Identifier(s):</strong>${this.renderIdentifiers(combinedPatient)}</li>
809
+ <li><strong>Telecom:</strong><ul>${this.renderTelecom(combinedPatient)}</ul></li>
810
+ <li><strong>Address(es):</strong>${this.renderAddresses(combinedPatient)}</li>
811
+ <li><strong>Marital Status:</strong> ${combinedPatient.maritalStatus?.text || ""}</li>
812
+ <li><strong>Deceased:</strong>${this.renderDeceased(combinedPatient)}</li>
813
+ <li><strong>Language(s):</strong>${this.renderCommunication(templateUtilities, combinedPatient)}</li>
814
+ </ul>
815
+ </div>`;
816
+ }
817
+ /**
818
+ * Combines multiple patient resources into a single patient object
819
+ * Merges fields, preferring non-empty values
820
+ * @param patients - Array of patient resources
821
+ * @returns Combined patient resource
822
+ */
823
+ static combinePatients(patients) {
824
+ if (patients.length === 1) {
825
+ return patients[0];
826
+ }
827
+ const combined = patients[0];
828
+ const allNames = [];
829
+ const allIdentifiers = [];
830
+ const allTelecom = [];
831
+ const allAddresses = [];
832
+ const allCommunication = [];
833
+ patients.forEach((patient) => {
834
+ if (patient.name) {
835
+ allNames.push(...patient.name);
810
836
  }
811
- }
812
- return html;
837
+ if (patient.identifier) {
838
+ allIdentifiers.push(...patient.identifier);
839
+ }
840
+ if (patient.telecom) {
841
+ allTelecom.push(...patient.telecom);
842
+ }
843
+ if (patient.address) {
844
+ allAddresses.push(...patient.address);
845
+ }
846
+ if (patient.communication) {
847
+ allCommunication.push(...patient.communication);
848
+ }
849
+ if (!combined.gender && patient.gender) {
850
+ combined.gender = patient.gender;
851
+ }
852
+ if (!combined.birthDate && patient.birthDate) {
853
+ combined.birthDate = patient.birthDate;
854
+ }
855
+ if (!combined.maritalStatus && patient.maritalStatus) {
856
+ combined.maritalStatus = patient.maritalStatus;
857
+ }
858
+ if (!combined.deceasedBoolean && patient.deceasedBoolean !== void 0) {
859
+ combined.deceasedBoolean = patient.deceasedBoolean;
860
+ }
861
+ if (!combined.deceasedDateTime && patient.deceasedDateTime) {
862
+ combined.deceasedDateTime = patient.deceasedDateTime;
863
+ }
864
+ });
865
+ combined.name = allNames;
866
+ combined.identifier = allIdentifiers;
867
+ combined.telecom = allTelecom;
868
+ combined.address = allAddresses;
869
+ combined.communication = allCommunication;
870
+ return combined;
813
871
  }
814
872
  /**
815
873
  * Renders patient names as HTML list items
816
- * @param patient - Patient resource
874
+ * @param patient - Patient resources
817
875
  * @returns HTML string of list items
818
876
  */
819
877
  static renderNames(patient) {
@@ -824,14 +882,16 @@ var PatientTemplate = class _PatientTemplate {
824
882
  patient.name.forEach((name) => {
825
883
  if (name.use !== "old") {
826
884
  const nameText = name.text || ((name.given || []).join(" ") + " " + (name.family || "")).trim();
827
- uniqueNames.add(nameText);
885
+ if (nameText) {
886
+ uniqueNames.add(nameText);
887
+ }
828
888
  }
829
889
  });
830
890
  return Array.from(uniqueNames).map((nameText) => `<ul><li>${nameText}</li></ul>`).join("");
831
891
  }
832
892
  /**
833
893
  * Renders patient identifiers as HTML list items
834
- * @param patient - Patient resource
894
+ * @param patient - Patient resources
835
895
  * @returns HTML string of list items
836
896
  */
837
897
  static renderIdentifiers(patient) {
@@ -846,7 +906,7 @@ var PatientTemplate = class _PatientTemplate {
846
906
  }
847
907
  /**
848
908
  * Renders patient telecom information grouped by system
849
- * @param patient - Patient resource
909
+ * @param patient - Patient resources
850
910
  * @returns HTML string grouped by system
851
911
  */
852
912
  static renderTelecom(patient) {
@@ -854,9 +914,10 @@ var PatientTemplate = class _PatientTemplate {
854
914
  return "";
855
915
  }
856
916
  const systemPriority = ["email", "phone", "pager", "sms", "fax", "url", "other"];
917
+ const numberSystems = ["phone", "pager", "sms", "fax"];
857
918
  const telecomBySystem = /* @__PURE__ */ new Map();
858
919
  patient.telecom.forEach((telecom) => {
859
- if (telecom.system && telecom.value) {
920
+ if (telecom.system && telecom.value && telecom.use !== "old") {
860
921
  const system = telecom.system.toLowerCase();
861
922
  if (!telecomBySystem.has(system)) {
862
923
  telecomBySystem.set(system, /* @__PURE__ */ new Set());
@@ -864,6 +925,29 @@ var PatientTemplate = class _PatientTemplate {
864
925
  telecomBySystem.get(system).add(telecom.value);
865
926
  }
866
927
  });
928
+ for (const system of numberSystems) {
929
+ const currentNumbers = Array.from(telecomBySystem.get(system) || []);
930
+ if (currentNumbers.length <= 1) continue;
931
+ const numbersWithCleaned = currentNumbers.map((num) => ({
932
+ original: num,
933
+ cleaned: num.replace(/\D/g, "")
934
+ }));
935
+ const toRemove = /* @__PURE__ */ new Set();
936
+ for (let i = 0; i < numbersWithCleaned.length; i++) {
937
+ for (let j = i + 1; j < numbersWithCleaned.length; j++) {
938
+ const num1 = numbersWithCleaned[i];
939
+ const num2 = numbersWithCleaned[j];
940
+ if (num1.cleaned.endsWith(num2.cleaned)) {
941
+ toRemove.add(num2.original);
942
+ } else if (num2.cleaned.endsWith(num1.cleaned)) {
943
+ toRemove.add(num1.original);
944
+ }
945
+ }
946
+ }
947
+ toRemove.forEach((numberToRemove) => {
948
+ telecomBySystem.get(system)?.delete(numberToRemove);
949
+ });
950
+ }
867
951
  return Array.from(telecomBySystem.entries()).sort(([systemA], [systemB]) => {
868
952
  const priorityA = systemPriority.indexOf(systemA);
869
953
  const priorityB = systemPriority.indexOf(systemB);
@@ -881,7 +965,7 @@ var PatientTemplate = class _PatientTemplate {
881
965
  }
882
966
  /**
883
967
  * Renders patient addresses as HTML list items
884
- * @param patient - Patient resource
968
+ * @param patient - Patient resources
885
969
  * @returns HTML string of list items
886
970
  */
887
971
  static renderAddresses(patient) {
@@ -890,7 +974,33 @@ var PatientTemplate = class _PatientTemplate {
890
974
  }
891
975
  const uniqueAddresses = /* @__PURE__ */ new Set();
892
976
  patient.address.forEach((address) => {
893
- const addressText = address.text || ((address.line || []).join(", ") + ", " + (address.city || "") + ", " + (address.country || "")).trim();
977
+ if (address.use === "old") {
978
+ return;
979
+ }
980
+ const addressArray = [];
981
+ if (address.text) {
982
+ addressArray.push(address.text);
983
+ } else {
984
+ if (address.line) {
985
+ addressArray.push(...address.line);
986
+ }
987
+ if (address.city) {
988
+ addressArray.push(address.city);
989
+ }
990
+ if (address.district) {
991
+ addressArray.push(address.district);
992
+ }
993
+ if (address.state) {
994
+ addressArray.push(address.state);
995
+ }
996
+ if (address.country) {
997
+ addressArray.push(address.country);
998
+ }
999
+ if (address.postalCode) {
1000
+ addressArray.push(address.postalCode);
1001
+ }
1002
+ }
1003
+ const addressText = addressArray.join(", ").trim();
894
1004
  if (addressText) {
895
1005
  uniqueAddresses.add(addressText);
896
1006
  }
@@ -899,7 +1009,7 @@ var PatientTemplate = class _PatientTemplate {
899
1009
  }
900
1010
  /**
901
1011
  * Renders patient deceased status
902
- * @param patient - Patient resource
1012
+ * @param patient - Patient resources
903
1013
  * @returns HTML string for deceased status
904
1014
  */
905
1015
  static renderDeceased(patient) {
@@ -914,19 +1024,25 @@ var PatientTemplate = class _PatientTemplate {
914
1024
  /**
915
1025
  * Renders patient communication preferences as HTML list items
916
1026
  * @param templateUtilities - Instance of TemplateUtilities for utility functions
917
- * @param patient - Patient resource
1027
+ * @param patient - Patient resources
918
1028
  * @returns HTML string of list items
919
1029
  */
920
1030
  static renderCommunication(templateUtilities, patient) {
921
1031
  if (!patient.communication || patient.communication.length === 0) {
922
1032
  return "";
923
1033
  }
924
- return patient.communication.map((comm) => {
925
- if (!comm.language) return "";
1034
+ const uniqueLanguages = /* @__PURE__ */ new Set();
1035
+ const preferredLanguages = /* @__PURE__ */ new Set();
1036
+ patient.communication.forEach((comm) => {
926
1037
  const language = templateUtilities.codeableConcept(comm.language);
927
- const preferred = comm.preferred ? " (preferred)" : "";
928
- return `<ul><li>${language}${preferred}</li></ul>`;
929
- }).join("");
1038
+ if (language) {
1039
+ if (comm.preferred) {
1040
+ preferredLanguages.add(language);
1041
+ }
1042
+ uniqueLanguages.add(language);
1043
+ }
1044
+ });
1045
+ return Array.from(uniqueLanguages).map((language) => `<ul><li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li></ul>`).join("");
930
1046
  }
931
1047
  /**
932
1048
  * Capitalizes first letter of a string
@@ -943,32 +1059,30 @@ var PatientTemplate = class _PatientTemplate {
943
1059
  var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
944
1060
  /**
945
1061
  * Generate HTML narrative for AllergyIntolerance resources
946
- * @param resource - FHIR Bundle containing AllergyIntolerance resources
1062
+ * @param resources - FHIR resources array containing AllergyIntolerance resources
947
1063
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
948
1064
  * @returns HTML string for rendering
949
1065
  */
950
- generateNarrative(resource, timezone) {
951
- return _AllergyIntoleranceTemplate.generateStaticNarrative(resource, timezone);
1066
+ generateNarrative(resources, timezone) {
1067
+ return _AllergyIntoleranceTemplate.generateStaticNarrative(resources, timezone);
952
1068
  }
953
1069
  /**
954
1070
  * Internal static implementation that actually generates the narrative
955
- * @param resource - FHIR Bundle containing AllergyIntolerance resources
1071
+ * @param resources - FHIR resources array containing AllergyIntolerance resources
956
1072
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
957
1073
  * @returns HTML string for rendering
958
1074
  */
959
- static generateStaticNarrative(resource, timezone) {
960
- const templateUtilities = new TemplateUtilities(resource);
1075
+ static generateStaticNarrative(resources, timezone) {
1076
+ const templateUtilities = new TemplateUtilities(resources);
961
1077
  const activeAllergies = [];
962
1078
  const resolvedAllergies = [];
963
- if (resource.entry && Array.isArray(resource.entry)) {
964
- for (const entry of resource.entry) {
965
- const allergy = entry.resource;
966
- const isResolved = allergy.clinicalStatus?.coding?.some((c) => ["inactive", "resolved"].includes(c.code));
967
- if (isResolved) {
968
- resolvedAllergies.push(allergy);
969
- } else {
970
- activeAllergies.push(allergy);
971
- }
1079
+ for (const resourceItem of resources) {
1080
+ const allergy = resourceItem;
1081
+ const isResolved = allergy.clinicalStatus?.coding?.some((c) => ["inactive", "resolved"].includes(c.code));
1082
+ if (isResolved) {
1083
+ resolvedAllergies.push(allergy);
1084
+ } else {
1085
+ activeAllergies.push(allergy);
972
1086
  }
973
1087
  }
974
1088
  activeAllergies.sort((a, b) => {
@@ -992,7 +1106,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
992
1106
  <th>Status</th>
993
1107
  <th>Category</th>
994
1108
  <th>Reaction</th>
995
- <th>Severity</th>
996
1109
  <th>Onset Date</th>
997
1110
  <th>Comments</th>
998
1111
  </tr>
@@ -1020,7 +1133,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1020
1133
  <th>Status</th>
1021
1134
  <th>Category</th>
1022
1135
  <th>Reaction</th>
1023
- <th>Severity</th>
1024
1136
  <th>Onset Date</th>
1025
1137
  <th>Comments</th>
1026
1138
  <th>Resolved Date</th>
@@ -1058,7 +1170,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1058
1170
  <td class="Status">${templateUtilities.codeableConcept(allergy.clinicalStatus) || "-"}</td>
1059
1171
  <td class="Category">${templateUtilities.safeConcat(allergy.category) || "-"}</td>
1060
1172
  <td class="Reaction">${templateUtilities.concatReactionManifestation(allergy.reaction) || "-"}</td>
1061
- <td class="Severity">${templateUtilities.safeConcat(allergy.reaction, "severity") || "-"}</td>
1062
1173
  <td class="OnsetDate">${templateUtilities.renderTime(allergy.onsetDateTime, timezone) || "-"}</td>
1063
1174
  <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
1064
1175
  if (includeResolved) {
@@ -1084,12 +1195,12 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1084
1195
  var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1085
1196
  /**
1086
1197
  * Generate HTML narrative for Medication resources
1087
- * @param resource - FHIR Bundle containing Medication resources
1198
+ * @param resources - FHIR Medication resources
1088
1199
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1089
1200
  * @returns HTML string for rendering
1090
1201
  */
1091
- generateNarrative(resource, timezone) {
1092
- return _MedicationSummaryTemplate.generateStaticNarrative(resource, timezone);
1202
+ generateNarrative(resources, timezone) {
1203
+ return _MedicationSummaryTemplate.generateStaticNarrative(resources, timezone);
1093
1204
  }
1094
1205
  /**
1095
1206
  * Safely parse a date string and return a valid Date object or null
@@ -1154,16 +1265,16 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1154
1265
  }
1155
1266
  /**
1156
1267
  * Internal static implementation that actually generates the narrative
1157
- * @param resource - FHIR Bundle containing Medication resources
1268
+ * @param resources - FHIR Medication resources
1158
1269
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1159
1270
  * @returns HTML string for rendering
1160
1271
  */
1161
1272
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1162
- static generateStaticNarrative(resource, timezone) {
1163
- const templateUtilities = new TemplateUtilities(resource);
1273
+ static generateStaticNarrative(resources, timezone) {
1274
+ const templateUtilities = new TemplateUtilities(resources);
1164
1275
  let html = "";
1165
- const medicationRequests = this.getMedicationRequests(templateUtilities, resource);
1166
- const medicationStatements = this.getMedicationStatements(templateUtilities, resource);
1276
+ const medicationRequests = this.getMedicationRequests(templateUtilities, resources);
1277
+ const medicationStatements = this.getMedicationStatements(templateUtilities, resources);
1167
1278
  const allActiveMedications = [];
1168
1279
  const allInactiveMedications = [];
1169
1280
  medicationRequests.forEach((mr) => {
@@ -1208,42 +1319,42 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1208
1319
  };
1209
1320
  if (allActiveMedications.length > 0) {
1210
1321
  sortMedications(allActiveMedications);
1211
- html += this.renderCombinedMedications(templateUtilities, allActiveMedications, "Active Medications");
1322
+ html += this.renderCombinedMedications(templateUtilities, allActiveMedications, true);
1212
1323
  }
1213
1324
  if (allInactiveMedications.length > 0) {
1214
1325
  sortMedications(allInactiveMedications);
1215
- html += this.renderCombinedMedications(templateUtilities, allInactiveMedications, "Inactive Medications");
1326
+ html += this.renderCombinedMedications(templateUtilities, allInactiveMedications, false);
1216
1327
  }
1217
1328
  return html;
1218
1329
  }
1219
1330
  /**
1220
- * Extract MedicationRequest resources from the bundle
1331
+ * Extract MedicationRequest resources
1221
1332
  * @param templateUtilities - Instance of TemplateUtilities for utility functions
1222
- * @param resource - FHIR Bundle
1333
+ * @param resources - FHIR Medication resources
1223
1334
  * @returns Array of MedicationRequest resources
1224
1335
  */
1225
- static getMedicationRequests(templateUtilities, resource) {
1226
- if (!resource.entry || !Array.isArray(resource.entry)) {
1336
+ static getMedicationRequests(templateUtilities, resources) {
1337
+ if (resources.length === 0) {
1227
1338
  return [];
1228
1339
  }
1229
- return resource.entry.filter((entry) => entry.resource?.resourceType === "MedicationRequest").map((entry) => ({
1230
- resource: entry.resource,
1231
- extension: templateUtilities.narrativeLinkExtension(entry.resource)
1340
+ return resources.filter((entry) => entry.resourceType === "MedicationRequest").map((entry) => ({
1341
+ resource: entry,
1342
+ extension: templateUtilities.narrativeLinkExtension(entry)
1232
1343
  }));
1233
1344
  }
1234
1345
  /**
1235
- * Extract MedicationStatement resources from the bundle
1346
+ * Extract MedicationStatement resources
1236
1347
  * @param templateUtilities - Instance of TemplateUtilities for utility functions
1237
- * @param resource - FHIR Bundle
1348
+ * @param resources - FHIR Medication resources
1238
1349
  * @returns Array of MedicationStatement resources
1239
1350
  */
1240
- static getMedicationStatements(templateUtilities, resource) {
1241
- if (!resource.entry || !Array.isArray(resource.entry)) {
1351
+ static getMedicationStatements(templateUtilities, resources) {
1352
+ if (resources.length === 0) {
1242
1353
  return [];
1243
1354
  }
1244
- return resource.entry.filter((entry) => entry.resource?.resourceType === "MedicationStatement").map((entry) => ({
1245
- resource: entry.resource,
1246
- extension: templateUtilities.narrativeLinkExtension(entry.resource)
1355
+ return resources.filter((entry) => entry.resourceType === "MedicationStatement").map((entry) => ({
1356
+ resource: entry,
1357
+ extension: templateUtilities.narrativeLinkExtension(entry)
1247
1358
  }));
1248
1359
  }
1249
1360
  /**
@@ -1253,9 +1364,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1253
1364
  * @param sectionTitle - Title for the section
1254
1365
  * @returns HTML string for rendering
1255
1366
  */
1256
- static renderCombinedMedications(templateUtilities, medications, sectionTitle) {
1367
+ static renderCombinedMedications(templateUtilities, medications, isActiveSection) {
1257
1368
  let html = `
1258
- <h3>${sectionTitle}</h3>
1369
+ <h3>${isActiveSection ? "Active Medications" : "Inactive Medications"}</h3>
1259
1370
  <table>
1260
1371
  <thead>
1261
1372
  <tr>
@@ -1264,8 +1375,8 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1264
1375
  <th>Sig</th>
1265
1376
  <th>Dispense Quantity</th>
1266
1377
  <th>Refills</th>
1267
- <th>Start Date</th>
1268
- <th>End Date</th>
1378
+ <th>Start Date</th>${isActiveSection ? "" : `
1379
+ <th>End Date</th>`}
1269
1380
  <th>Status</th>
1270
1381
  </tr>
1271
1382
  </thead>
@@ -1323,8 +1434,8 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1323
1434
  <td>${sig}</td>
1324
1435
  <td>${dispenseQuantity}</td>
1325
1436
  <td>${refills}</td>
1326
- <td>${startDate}</td>
1327
- <td>${endDate}</td>
1437
+ <td>${startDate}</td>${isActiveSection ? "" : `
1438
+ <td>${endDate}</td>`}
1328
1439
  <td>${status}</td>
1329
1440
  </tr>`;
1330
1441
  }
@@ -1339,28 +1450,26 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1339
1450
  var ImmunizationsTemplate = class _ImmunizationsTemplate {
1340
1451
  /**
1341
1452
  * Generate HTML narrative for Immunization resources
1342
- * @param resource - FHIR Bundle containing Immunization resources
1453
+ * @param resources - FHIR resources array containing Immunization resources
1343
1454
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1344
1455
  * @returns HTML string for rendering
1345
1456
  */
1346
- generateNarrative(resource, timezone) {
1347
- if (resource.entry && Array.isArray(resource.entry)) {
1348
- resource.entry.sort((a, b) => {
1349
- const dateA = a.resource?.occurrenceDateTime;
1350
- const dateB = b.resource?.occurrenceDateTime;
1351
- return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1352
- });
1353
- }
1354
- return _ImmunizationsTemplate.generateStaticNarrative(resource, timezone);
1457
+ generateNarrative(resources, timezone) {
1458
+ resources.sort((a, b) => {
1459
+ const dateA = a.occurrenceDateTime;
1460
+ const dateB = b.occurrenceDateTime;
1461
+ return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1462
+ });
1463
+ return _ImmunizationsTemplate.generateStaticNarrative(resources, timezone);
1355
1464
  }
1356
1465
  /**
1357
1466
  * Internal static implementation that actually generates the narrative
1358
- * @param resource - FHIR Bundle containing Immunization resources
1467
+ * @param resources - FHIR resources array containing Immunization resources
1359
1468
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1360
1469
  * @returns HTML string for rendering
1361
1470
  */
1362
- static generateStaticNarrative(resource, timezone) {
1363
- const templateUtilities = new TemplateUtilities(resource);
1471
+ static generateStaticNarrative(resources, timezone) {
1472
+ const templateUtilities = new TemplateUtilities(resources);
1364
1473
  let html = `
1365
1474
  <table>
1366
1475
  <thead>
@@ -1375,21 +1484,20 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
1375
1484
  </tr>
1376
1485
  </thead>
1377
1486
  <tbody>`;
1378
- if (resource.entry && Array.isArray(resource.entry)) {
1379
- for (const entry of resource.entry) {
1380
- if (entry.resource?.resourceType === "Immunization") {
1381
- const imm = entry.resource;
1382
- html += `
1383
- <tr id="${templateUtilities.narrativeLinkId(imm)}">
1384
- <td>${templateUtilities.codeableConcept(imm.vaccineCode)}</td>
1385
- <td>${imm.status || ""}</td>
1386
- <td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
1387
- <td>${templateUtilities.renderVaccineManufacturer(imm)}</td>
1388
- <td>${imm.lotNumber || ""}</td>
1389
- <td>${templateUtilities.renderNotes(imm.note, timezone)}</td>
1390
- <td>${templateUtilities.renderTime(imm.occurrenceDateTime, timezone)}</td>
1391
- </tr>`;
1392
- }
1487
+ const immunizations = resources.filter((resourceItem) => resourceItem.resourceType === "Immunization");
1488
+ if (immunizations.length > 0) {
1489
+ for (const resourceItem of immunizations) {
1490
+ const imm = resourceItem;
1491
+ html += `
1492
+ <tr id="${templateUtilities.narrativeLinkId(imm)}">
1493
+ <td>${templateUtilities.codeableConcept(imm.vaccineCode)}</td>
1494
+ <td>${imm.status || ""}</td>
1495
+ <td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
1496
+ <td>${templateUtilities.renderVaccineManufacturer(imm)}</td>
1497
+ <td>${imm.lotNumber || ""}</td>
1498
+ <td>${templateUtilities.renderNotes(imm.note, timezone)}</td>
1499
+ <td>${templateUtilities.renderTime(imm.occurrenceDateTime, timezone)}</td>
1500
+ </tr>`;
1393
1501
  }
1394
1502
  }
1395
1503
  html += `
@@ -1403,23 +1511,23 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
1403
1511
  var ProblemListTemplate = class _ProblemListTemplate {
1404
1512
  /**
1405
1513
  * Generate HTML narrative for Problem List
1406
- * @param resource - FHIR Bundle containing Condition resources
1514
+ * @param resources - FHIR Condition resources
1407
1515
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1408
1516
  * @returns HTML string for rendering
1409
1517
  */
1410
- generateNarrative(resource, timezone) {
1411
- return _ProblemListTemplate.generateStaticNarrative(resource, timezone);
1518
+ generateNarrative(resources, timezone) {
1519
+ return _ProblemListTemplate.generateStaticNarrative(resources, timezone);
1412
1520
  }
1413
1521
  /**
1414
1522
  * Internal static implementation that actually generates the narrative
1415
- * @param resource - FHIR Bundle containing Condition resources
1523
+ * @param resources - FHIR Condition resources
1416
1524
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1417
1525
  * @returns HTML string for rendering
1418
1526
  */
1419
- static generateStaticNarrative(resource, timezone) {
1420
- const templateUtilities = new TemplateUtilities(resource);
1527
+ static generateStaticNarrative(resources, timezone) {
1528
+ const templateUtilities = new TemplateUtilities(resources);
1421
1529
  let html = ``;
1422
- const activeConditions = resource.entry?.map((entry) => entry.resource) || [];
1530
+ const activeConditions = resources.map((entry) => entry) || [];
1423
1531
  activeConditions.sort((a, b) => {
1424
1532
  const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
1425
1533
  const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
@@ -1430,7 +1538,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
1430
1538
  <thead>
1431
1539
  <tr>
1432
1540
  <th>Problem</th>
1433
- <th>Severity</th>
1434
1541
  <th>Onset Date</th>
1435
1542
  <th>Recorded Date</th>
1436
1543
  <th>Notes</th>
@@ -1440,7 +1547,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
1440
1547
  for (const cond of activeConditions) {
1441
1548
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
1442
1549
  <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
1443
- <td class="Severity">${templateUtilities.codeableConcept(cond.severity)}</td>
1444
1550
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
1445
1551
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
1446
1552
  <td class="Notes">${templateUtilities.renderNotes(cond.note, timezone)}</td>
@@ -1456,22 +1562,22 @@ var ProblemListTemplate = class _ProblemListTemplate {
1456
1562
  var VitalSignsTemplate = class _VitalSignsTemplate {
1457
1563
  /**
1458
1564
  * Generate HTML narrative for Vital Signs
1459
- * @param resource - FHIR Bundle containing Observation resources
1565
+ * @param resources - FHIR Observation resources
1460
1566
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1461
1567
  * @returns HTML string for rendering
1462
1568
  */
1463
- generateNarrative(resource, timezone) {
1464
- return _VitalSignsTemplate.generateStaticNarrative(resource, timezone);
1569
+ generateNarrative(resources, timezone) {
1570
+ return _VitalSignsTemplate.generateStaticNarrative(resources, timezone);
1465
1571
  }
1466
1572
  /**
1467
1573
  * Internal static implementation that actually generates the narrative
1468
- * @param resource - FHIR Bundle containing Observation resources
1574
+ * @param resources - FHIR Observation resources
1469
1575
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1470
1576
  * @returns HTML string for rendering
1471
1577
  */
1472
- static generateStaticNarrative(resource, timezone) {
1473
- const templateUtilities = new TemplateUtilities(resource);
1474
- const observations = resource.entry?.map((entry) => entry.resource) || [];
1578
+ static generateStaticNarrative(resources, timezone) {
1579
+ const templateUtilities = new TemplateUtilities(resources);
1580
+ const observations = resources.map((entry) => entry) || [];
1475
1581
  observations.sort((a, b) => {
1476
1582
  const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
1477
1583
  const dateB = b.effectiveDateTime || b.effectivePeriod?.start;
@@ -1514,28 +1620,21 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
1514
1620
  var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
1515
1621
  /**
1516
1622
  * Generate HTML narrative for Medical Device resources
1517
- * @param resource - FHIR Bundle containing Device resources
1623
+ * @param resources - FHIR resources array containing Device resources
1518
1624
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1519
1625
  * @returns HTML string for rendering
1520
1626
  */
1521
- generateNarrative(resource, timezone) {
1522
- if (resource.entry && Array.isArray(resource.entry)) {
1523
- resource.entry.sort((a, b) => {
1524
- const dateA = a.resource?.recordedOn;
1525
- const dateB = b.resource?.recordedOn;
1526
- return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1527
- });
1528
- }
1529
- return _MedicalDevicesTemplate.generateStaticNarrative(resource, timezone);
1627
+ generateNarrative(resources, timezone) {
1628
+ return _MedicalDevicesTemplate.generateStaticNarrative(resources, timezone);
1530
1629
  }
1531
1630
  /**
1532
1631
  * Internal static implementation that actually generates the narrative
1533
- * @param resource - FHIR Bundle containing Device resources
1632
+ * @param resources - FHIR resources array containing Device resources
1534
1633
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1535
1634
  * @returns HTML string for rendering
1536
1635
  */
1537
- static generateStaticNarrative(resource, timezone) {
1538
- const templateUtilities = new TemplateUtilities(resource);
1636
+ static generateStaticNarrative(resources, timezone) {
1637
+ const templateUtilities = new TemplateUtilities(resources);
1539
1638
  let html = `
1540
1639
  <table>
1541
1640
  <thead>
@@ -1547,19 +1646,19 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
1547
1646
  </tr>
1548
1647
  </thead>
1549
1648
  <tbody>`;
1550
- if (resource.entry && Array.isArray(resource.entry)) {
1551
- for (const entry of resource.entry) {
1552
- if (entry.resource?.resourceType === "DeviceUseStatement") {
1553
- const dus = entry.resource;
1554
- html += `
1555
- <tr id="${templateUtilities.narrativeLinkId(dus)}">
1556
- <td>${templateUtilities.renderDevice(dus.device)}</td>
1557
- <td>${dus.status || ""}</td>
1558
- <td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
1559
- <td>${templateUtilities.renderRecorded(dus.recordedOn, timezone)}</td>
1560
- </tr>`;
1561
- }
1562
- }
1649
+ const deviceStatements = resources.filter((resourceItem) => resourceItem.resourceType === "DeviceUseStatement").map((resourceItem) => resourceItem).sort((a, b) => {
1650
+ const dateA = a.recordedOn;
1651
+ const dateB = b.recordedOn;
1652
+ return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1653
+ });
1654
+ for (const dus of deviceStatements) {
1655
+ html += `
1656
+ <tr id="${templateUtilities.narrativeLinkId(dus)}">
1657
+ <td>${templateUtilities.renderDevice(dus.device)}</td>
1658
+ <td>${dus.status || ""}</td>
1659
+ <td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
1660
+ <td>${templateUtilities.renderRecorded(dus.recordedOn, timezone)}</td>
1661
+ </tr>`;
1563
1662
  }
1564
1663
  html += `
1565
1664
  </tbody>
@@ -1572,23 +1671,23 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
1572
1671
  var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1573
1672
  /**
1574
1673
  * Generate HTML narrative for Diagnostic Results
1575
- * @param resource - FHIR Bundle containing Observation and DiagnosticReport resources
1674
+ * @param resources - FHIR resources array containing Observation and DiagnosticReport resources
1576
1675
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1577
1676
  * @returns HTML string for rendering
1578
1677
  */
1579
- generateNarrative(resource, timezone) {
1580
- return _DiagnosticResultsTemplate.generateStaticNarrative(resource, timezone);
1678
+ generateNarrative(resources, timezone) {
1679
+ return _DiagnosticResultsTemplate.generateStaticNarrative(resources, timezone);
1581
1680
  }
1582
1681
  /**
1583
1682
  * Internal static implementation that actually generates the narrative
1584
- * @param resource - FHIR Bundle containing Observation and DiagnosticReport resources
1683
+ * @param resources - FHIR resources array containing Observation and DiagnosticReport resources
1585
1684
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1586
1685
  * @returns HTML string for rendering
1587
1686
  */
1588
- static generateStaticNarrative(resource, timezone) {
1589
- const templateUtilities = new TemplateUtilities(resource);
1687
+ static generateStaticNarrative(resources, timezone) {
1688
+ const templateUtilities = new TemplateUtilities(resources);
1590
1689
  let html = "";
1591
- const observations = this.getObservations(resource);
1690
+ const observations = this.getObservations(resources);
1592
1691
  if (observations.length > 0) {
1593
1692
  observations.sort((a, b) => {
1594
1693
  const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
@@ -1597,7 +1696,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1597
1696
  });
1598
1697
  html += this.renderObservations(templateUtilities, observations, timezone);
1599
1698
  }
1600
- const diagnosticReports = this.getDiagnosticReports(resource);
1699
+ const diagnosticReports = this.getDiagnosticReports(resources);
1601
1700
  if (diagnosticReports.length > 0) {
1602
1701
  diagnosticReports.sort((a, b) => {
1603
1702
  const dateA = a.issued;
@@ -1609,26 +1708,20 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1609
1708
  return html;
1610
1709
  }
1611
1710
  /**
1612
- * Extract Observation resources from the bundle
1613
- * @param resource - FHIR Bundle
1614
- * @returns Array of Observation resources
1615
- */
1616
- static getObservations(resource) {
1617
- if (!resource.entry || !Array.isArray(resource.entry)) {
1618
- return [];
1619
- }
1620
- return resource.entry.filter((entry) => entry.resource?.resourceType === "Observation").map((entry) => entry.resource);
1711
+ * Get all Observation resources from the resource array
1712
+ * @param resources - FHIR resources array
1713
+ * @returns Array of Observation resources
1714
+ */
1715
+ static getObservations(resources) {
1716
+ return resources.filter((resourceItem) => resourceItem.resourceType === "Observation").map((resourceItem) => resourceItem);
1621
1717
  }
1622
1718
  /**
1623
- * Extract DiagnosticReport resources from the bundle
1624
- * @param resource - FHIR Bundle
1719
+ * Get all DiagnosticReport resources from the resource array
1720
+ * @param resources - FHIR resources array
1625
1721
  * @returns Array of DiagnosticReport resources
1626
1722
  */
1627
- static getDiagnosticReports(resource) {
1628
- if (!resource.entry || !Array.isArray(resource.entry)) {
1629
- return [];
1630
- }
1631
- return resource.entry.filter((entry) => entry.resource?.resourceType === "DiagnosticReport").map((entry) => entry.resource);
1723
+ static getDiagnosticReports(resources) {
1724
+ return resources.filter((resourceItem) => resourceItem.resourceType === "DiagnosticReport").map((resourceItem) => resourceItem);
1632
1725
  }
1633
1726
  /**
1634
1727
  * Render HTML table for Observation resources
@@ -1684,7 +1777,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1684
1777
  <thead>
1685
1778
  <tr>
1686
1779
  <th>Report</th>
1687
- <th>Status</th>
1688
1780
  <th>Category</th>
1689
1781
  <th>Result</th>
1690
1782
  <th>Issued</th>
@@ -1699,7 +1791,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1699
1791
  html += `
1700
1792
  <tr id="${templateUtilities.narrativeLinkId(report)}">
1701
1793
  <td>${templateUtilities.codeableConcept(report.code)}</td>
1702
- <td>${report.status || ""}</td>
1703
1794
  <td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
1704
1795
  <td>${resultCount}</td>
1705
1796
  <td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
@@ -1716,26 +1807,26 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
1716
1807
  var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
1717
1808
  /**
1718
1809
  * Generate HTML narrative for Procedure resources
1719
- * @param resource - FHIR Bundle containing Procedure resources
1810
+ * @param resources - FHIR Procedure resources
1720
1811
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1721
1812
  * @returns HTML string for rendering
1722
1813
  */
1723
- generateNarrative(resource, timezone) {
1724
- resource.entry?.sort((a, b) => {
1725
- const dateA = a.resource.performedDateTime || a.resource.performedPeriod?.start;
1726
- const dateB = b.resource.performedDateTime || b.resource.performedPeriod?.start;
1814
+ generateNarrative(resources, timezone) {
1815
+ resources.sort((a, b) => {
1816
+ const dateA = a.performedDateTime || a.performedPeriod?.start;
1817
+ const dateB = b.performedDateTime || b.performedPeriod?.start;
1727
1818
  return dateA && dateB ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
1728
1819
  });
1729
- return _HistoryOfProceduresTemplate.generateStaticNarrative(resource, timezone);
1820
+ return _HistoryOfProceduresTemplate.generateStaticNarrative(resources, timezone);
1730
1821
  }
1731
1822
  /**
1732
1823
  * Internal static implementation that actually generates the narrative
1733
- * @param resource - FHIR Bundle containing Procedure resources
1824
+ * @param resources - FHIR Procedure resources
1734
1825
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1735
1826
  * @returns HTML string for rendering
1736
1827
  */
1737
- static generateStaticNarrative(resource, timezone) {
1738
- const templateUtilities = new TemplateUtilities(resource);
1828
+ static generateStaticNarrative(resources, timezone) {
1829
+ const templateUtilities = new TemplateUtilities(resources);
1739
1830
  let html = `
1740
1831
  <table>
1741
1832
  <thead>
@@ -1746,16 +1837,14 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
1746
1837
  </tr>
1747
1838
  </thead>
1748
1839
  <tbody>`;
1749
- if (resource.entry && Array.isArray(resource.entry)) {
1750
- for (const entry of resource.entry) {
1751
- const proc = entry.resource;
1752
- html += `
1753
- <tr id="${templateUtilities.narrativeLinkId(proc)}">
1754
- <td>${templateUtilities.codeableConcept(proc.code, "display")}</td>
1755
- <td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
1756
- <td>${proc.performedDateTime ? templateUtilities.renderTime(proc.performedDateTime, timezone) : proc.performedPeriod ? templateUtilities.renderPeriod(proc.performedPeriod, timezone) : ""}</td>
1757
- </tr>`;
1758
- }
1840
+ for (const resourceItem of resources) {
1841
+ const proc = resourceItem;
1842
+ html += `
1843
+ <tr id="${templateUtilities.narrativeLinkId(proc)}">
1844
+ <td>${templateUtilities.codeableConcept(proc.code, "display")}</td>
1845
+ <td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
1846
+ <td>${proc.performedDateTime ? templateUtilities.renderTime(proc.performedDateTime, timezone) : proc.performedPeriod ? templateUtilities.renderPeriod(proc.performedPeriod, timezone) : ""}</td>
1847
+ </tr>`;
1759
1848
  }
1760
1849
  html += `
1761
1850
  </tbody>
@@ -1768,22 +1857,22 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
1768
1857
  var SocialHistoryTemplate = class _SocialHistoryTemplate {
1769
1858
  /**
1770
1859
  * Generate HTML narrative for Social History
1771
- * @param resource - FHIR Bundle containing Observation resources
1860
+ * @param resources - FHIR Observation resources
1772
1861
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1773
1862
  * @returns HTML string for rendering
1774
1863
  */
1775
- generateNarrative(resource, timezone) {
1776
- return _SocialHistoryTemplate.generateStaticNarrative(resource, timezone);
1864
+ generateNarrative(resources, timezone) {
1865
+ return _SocialHistoryTemplate.generateStaticNarrative(resources, timezone);
1777
1866
  }
1778
1867
  /**
1779
1868
  * Internal static implementation that actually generates the narrative
1780
- * @param resource - FHIR Bundle containing Observation resources
1869
+ * @param resources - FHIR Observation resources
1781
1870
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1782
1871
  * @returns HTML string for rendering
1783
1872
  */
1784
- static generateStaticNarrative(resource, timezone) {
1785
- const templateUtilities = new TemplateUtilities(resource);
1786
- const observations = resource.entry?.map((entry) => entry.resource) || [];
1873
+ static generateStaticNarrative(resources, timezone) {
1874
+ const templateUtilities = new TemplateUtilities(resources);
1875
+ const observations = resources.map((entry) => entry) || [];
1787
1876
  observations.sort((a, b) => {
1788
1877
  const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
1789
1878
  const dateB = b.effectiveDateTime || b.effectivePeriod?.start;
@@ -1822,14 +1911,14 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
1822
1911
  var PastHistoryOfIllnessTemplate = class {
1823
1912
  /**
1824
1913
  * Generate HTML narrative for Past History of Illnesses
1825
- * @param resource - FHIR Bundle containing Condition resources
1914
+ * @param resources - FHIR Condition resources
1826
1915
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1827
1916
  * @returns HTML string for rendering
1828
1917
  */
1829
- generateNarrative(resource, timezone) {
1830
- const templateUtilities = new TemplateUtilities(resource);
1918
+ generateNarrative(resources, timezone) {
1919
+ const templateUtilities = new TemplateUtilities(resources);
1831
1920
  let html = ``;
1832
- const resolvedConditions = resource.entry?.map((entry) => entry.resource) || [];
1921
+ const resolvedConditions = resources.map((entry) => entry) || [];
1833
1922
  resolvedConditions.sort((a, b) => {
1834
1923
  const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
1835
1924
  const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
@@ -1840,7 +1929,6 @@ var PastHistoryOfIllnessTemplate = class {
1840
1929
  <thead>
1841
1930
  <tr>
1842
1931
  <th>Problem</th>
1843
- <th>Severity</th>
1844
1932
  <th>Onset Date</th>
1845
1933
  <th>Recorded Date</th>
1846
1934
  <th>Resolved Date</th>
@@ -1851,7 +1939,6 @@ var PastHistoryOfIllnessTemplate = class {
1851
1939
  for (const cond of resolvedConditions) {
1852
1940
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
1853
1941
  <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
1854
- <td class="Severity">${templateUtilities.codeableConcept(cond.severity)}</td>
1855
1942
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
1856
1943
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
1857
1944
  <td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
@@ -1868,13 +1955,13 @@ var PastHistoryOfIllnessTemplate = class {
1868
1955
  var PlanOfCareTemplate = class {
1869
1956
  /**
1870
1957
  * Generate HTML narrative for Plan of Care
1871
- * @param resource - FHIR Bundle containing CarePlan resources
1958
+ * @param resources - FHIR CarePlan resources
1872
1959
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1873
1960
  * @returns HTML string for rendering
1874
1961
  */
1875
- generateNarrative(resource, timezone) {
1876
- const templateUtilities = new TemplateUtilities(resource);
1877
- const carePlans = resource.entry?.map((entry) => entry.resource) || [];
1962
+ generateNarrative(resources, timezone) {
1963
+ const templateUtilities = new TemplateUtilities(resources);
1964
+ const carePlans = resources.map((entry) => entry) || [];
1878
1965
  carePlans.sort((a, b) => {
1879
1966
  const endA = a.period?.end ? new Date(a.period?.end).getTime() : 0;
1880
1967
  const endB = b.period?.end ? new Date(b.period?.end).getTime() : 0;
@@ -1913,37 +2000,35 @@ var PlanOfCareTemplate = class {
1913
2000
  var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
1914
2001
  /**
1915
2002
  * Generate HTML narrative for Functional Status
1916
- * @param resource - FHIR Bundle containing Observation resources
2003
+ * @param resources - FHIR resources array containing Observation resources
1917
2004
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1918
2005
  * @returns HTML string for rendering
1919
2006
  */
1920
- generateNarrative(resource, timezone) {
1921
- return _FunctionalStatusTemplate.generateStaticNarrative(resource, timezone);
2007
+ generateNarrative(resources, timezone) {
2008
+ return _FunctionalStatusTemplate.generateStaticNarrative(resources, timezone);
1922
2009
  }
1923
2010
  /**
1924
2011
  * Internal static implementation that actually generates the narrative
1925
- * @param resource - FHIR Bundle containing Observation resources
2012
+ * @param resources - FHIR resources array containing Observation resources
1926
2013
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1927
2014
  * @returns HTML string for rendering
1928
2015
  */
1929
- static generateStaticNarrative(resource, timezone) {
1930
- const templateUtilities = new TemplateUtilities(resource);
2016
+ static generateStaticNarrative(resources, timezone) {
2017
+ const templateUtilities = new TemplateUtilities(resources);
1931
2018
  let html = ``;
1932
2019
  const activeConditions = [];
1933
2020
  const clinicalImpressions = [];
1934
- if (resource.entry && Array.isArray(resource.entry)) {
1935
- for (const entry of resource.entry) {
1936
- if (entry.resource?.resourceType === "Condition") {
1937
- const cond = entry.resource;
1938
- const isResolved = cond.clinicalStatus?.coding?.some(
1939
- (c) => c.code === "resolved" || c.code === "inactive" || c.display?.toLowerCase().includes("resolved")
1940
- );
1941
- if (!isResolved) {
1942
- activeConditions.push(cond);
1943
- }
1944
- } else if (entry.resource?.resourceType === "ClinicalImpression") {
1945
- clinicalImpressions.push(entry.resource);
2021
+ for (const resourceItem of resources) {
2022
+ if (resourceItem.resourceType === "Condition") {
2023
+ const cond = resourceItem;
2024
+ const isResolved = cond.clinicalStatus?.coding?.some(
2025
+ (c) => c.code === "resolved" || c.code === "inactive" || c.display?.toLowerCase().includes("resolved")
2026
+ );
2027
+ if (!isResolved) {
2028
+ activeConditions.push(cond);
1946
2029
  }
2030
+ } else if (resourceItem.resourceType === "ClinicalImpression") {
2031
+ clinicalImpressions.push(resourceItem);
1947
2032
  }
1948
2033
  }
1949
2034
  activeConditions.sort((a, b) => {
@@ -1962,7 +2047,6 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
1962
2047
  <thead>
1963
2048
  <tr>
1964
2049
  <th>Problem</th>
1965
- <th>Severity</th>
1966
2050
  <th>Onset Date</th>
1967
2051
  <th>Recorded Date</th>
1968
2052
  <th>Notes</th>
@@ -1972,7 +2056,6 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
1972
2056
  for (const cond of activeConditions) {
1973
2057
  html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
1974
2058
  <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
1975
- <td class="Severity">${templateUtilities.codeableConcept(cond.severity)}</td>
1976
2059
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
1977
2060
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
1978
2061
  <td class="Notes">${templateUtilities.renderNotes(cond.note, timezone, { styled: true, warning: true })}</td>
@@ -2042,22 +2125,22 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
2042
2125
  var PregnancyTemplate = class _PregnancyTemplate {
2043
2126
  /**
2044
2127
  * Generate HTML narrative for Pregnancy
2045
- * @param resource - FHIR Bundle containing Observation resources
2128
+ * @param resources - FHIR Observation resources
2046
2129
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2047
2130
  * @returns HTML string for rendering
2048
2131
  */
2049
- generateNarrative(resource, timezone) {
2050
- return _PregnancyTemplate.generateStaticNarrative(resource, timezone);
2132
+ generateNarrative(resources, timezone) {
2133
+ return _PregnancyTemplate.generateStaticNarrative(resources, timezone);
2051
2134
  }
2052
2135
  /**
2053
2136
  * Internal static implementation that actually generates the narrative
2054
- * @param resource - FHIR Bundle containing Observation resources
2137
+ * @param resources - FHIR Observation resources
2055
2138
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2056
2139
  * @returns HTML string for rendering
2057
2140
  */
2058
- static generateStaticNarrative(resource, timezone) {
2059
- const templateUtilities = new TemplateUtilities(resource);
2060
- const observations = resource.entry?.map((entry) => entry.resource) || [];
2141
+ static generateStaticNarrative(resources, timezone) {
2142
+ const templateUtilities = new TemplateUtilities(resources);
2143
+ const observations = resources.map((entry) => entry) || [];
2061
2144
  observations.sort((a, b) => {
2062
2145
  const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
2063
2146
  const dateB = b.effectiveDateTime || b.effectivePeriod?.start;
@@ -2073,8 +2156,8 @@ var PregnancyTemplate = class _PregnancyTemplate {
2073
2156
  </tr>
2074
2157
  </thead>
2075
2158
  <tbody>`;
2076
- for (const resource2 of observations) {
2077
- const obs = resource2;
2159
+ for (const resource of observations) {
2160
+ const obs = resource;
2078
2161
  html += `
2079
2162
  <tr id="${templateUtilities.narrativeLinkId(obs)}">
2080
2163
  <td>${templateUtilities.extractPregnancyStatus(obs)}</td>
@@ -2093,29 +2176,27 @@ var PregnancyTemplate = class _PregnancyTemplate {
2093
2176
  var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
2094
2177
  /**
2095
2178
  * Generate HTML narrative for Advance Directives
2096
- * @param resource - FHIR Bundle containing Advance Directive resources
2179
+ * @param resources - FHIR Consent resources
2097
2180
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2098
2181
  * @returns HTML string for rendering
2099
2182
  */
2100
- generateNarrative(resource, timezone) {
2101
- if (resource.entry && Array.isArray(resource.entry)) {
2102
- resource.entry.sort((a, b) => {
2103
- const dateA = new Date(a.resource.dateTime || 0);
2104
- const dateB = new Date(b.resource.dateTime || 0);
2105
- return dateB.getTime() - dateA.getTime();
2106
- });
2107
- }
2108
- return _AdvanceDirectivesTemplate.generateStaticNarrative(resource, timezone);
2183
+ generateNarrative(resources, timezone) {
2184
+ resources.sort((a, b) => {
2185
+ const dateA = new Date(a.dateTime || 0);
2186
+ const dateB = new Date(b.dateTime || 0);
2187
+ return dateB.getTime() - dateA.getTime();
2188
+ });
2189
+ return _AdvanceDirectivesTemplate.generateStaticNarrative(resources, timezone);
2109
2190
  }
2110
2191
  /**
2111
2192
  * Internal static implementation that actually generates the narrative
2112
- * @param resource - FHIR Bundle containing Advance Directive resources
2193
+ * @param resources - FHIR Consent resources
2113
2194
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2114
2195
  * @returns HTML string for rendering
2115
2196
  */
2116
2197
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2117
- static generateStaticNarrative(resource, timezone) {
2118
- const templateUtilities = new TemplateUtilities(resource);
2198
+ static generateStaticNarrative(resources, timezone) {
2199
+ const templateUtilities = new TemplateUtilities(resources);
2119
2200
  let html = `
2120
2201
  <table>
2121
2202
  <thead>
@@ -2127,17 +2208,15 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
2127
2208
  </tr>
2128
2209
  </thead>
2129
2210
  <tbody>`;
2130
- if (resource.entry && Array.isArray(resource.entry)) {
2131
- for (const entry of resource.entry) {
2132
- const consent = entry.resource;
2133
- html += `
2134
- <tr id="${templateUtilities.narrativeLinkId(consent)}">
2135
- <td>${templateUtilities.codeableConcept(consent.scope, "display")}</td>
2136
- <td>${consent.status || ""}</td>
2137
- <td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
2138
- <td>${consent.dateTime || ""}</td>
2139
- </tr>`;
2140
- }
2211
+ for (const resourceItem of resources) {
2212
+ const consent = resourceItem;
2213
+ html += `
2214
+ <tr id="${templateUtilities.narrativeLinkId(consent)}">
2215
+ <td>${templateUtilities.codeableConcept(consent.scope, "display")}</td>
2216
+ <td>${consent.status || ""}</td>
2217
+ <td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
2218
+ <td>${consent.dateTime || ""}</td>
2219
+ </tr>`;
2141
2220
  }
2142
2221
  html += `
2143
2222
  </tbody>
@@ -2151,16 +2230,16 @@ var TypeScriptTemplateMapper = class {
2151
2230
  /**
2152
2231
  * Generates HTML narrative for a specific IPS section
2153
2232
  * @param section - The IPS section
2154
- * @param resource - FHIR Bundle containing resources
2233
+ * @param resources - FHIR resources
2155
2234
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2156
2235
  * @returns HTML string for rendering
2157
2236
  */
2158
- static generateNarrative(section, resource, timezone) {
2237
+ static generateNarrative(section, resources, timezone) {
2159
2238
  const templateClass = this.sectionToTemplate[section];
2160
2239
  if (!templateClass) {
2161
2240
  throw new Error(`No template found for section: ${section}`);
2162
2241
  }
2163
- return templateClass.generateNarrative(resource, timezone);
2242
+ return templateClass.generateNarrative(resources, timezone);
2164
2243
  }
2165
2244
  };
2166
2245
  // Map of section types to their template classes
@@ -2223,14 +2302,7 @@ var NarrativeGenerator = class {
2223
2302
  return void 0;
2224
2303
  }
2225
2304
  try {
2226
- const bundle = {
2227
- resourceType: "Bundle",
2228
- type: "collection",
2229
- entry: resources.map((resource) => ({
2230
- resource
2231
- }))
2232
- };
2233
- const content = TypeScriptTemplateMapper.generateNarrative(section, bundle, timezone);
2305
+ const content = TypeScriptTemplateMapper.generateNarrative(section, resources, timezone);
2234
2306
  if (!content) {
2235
2307
  return void 0;
2236
2308
  }
@@ -2315,13 +2387,16 @@ var ComprehensiveIPSCompositionBuilder = class {
2315
2387
  /**
2316
2388
  * sets the patient resource for the IPS Composition.
2317
2389
  * This is not needed if you are calling read_bundle, but can be used to set the patient resource directly.
2318
- * @param patient - FHIR Patient resource to set
2390
+ * @param patients - FHIR Patient resource to set
2319
2391
  */
2320
- setPatient(patient) {
2321
- if (!patient || patient.resourceType !== "Patient") {
2392
+ setPatient(patients) {
2393
+ if (!Array.isArray(patients)) {
2394
+ patients = [patients];
2395
+ }
2396
+ if (patients.length === 0 || !patients.every((patient) => patient.resourceType === "Patient")) {
2322
2397
  throw new Error("Invalid Patient resource");
2323
2398
  }
2324
- this.patient = patient;
2399
+ this.patients = patients;
2325
2400
  return this;
2326
2401
  }
2327
2402
  /**
@@ -2379,21 +2454,26 @@ var ComprehensiveIPSCompositionBuilder = class {
2379
2454
  if (!bundle.entry) {
2380
2455
  return this;
2381
2456
  }
2382
- const patientEntry = bundle.entry.find((e) => e.resource?.resourceType === "Patient");
2383
- if (!patientEntry || !patientEntry.resource) {
2457
+ const patientEntries = [];
2458
+ const resources = [];
2459
+ bundle.entry.forEach((e) => {
2460
+ if (e.resource?.resourceType === "Patient") {
2461
+ patientEntries.push(e.resource);
2462
+ this.resources.add(e.resource);
2463
+ } else if (e.resource) {
2464
+ resources.push(e.resource);
2465
+ }
2466
+ });
2467
+ if (patientEntries.length === 0) {
2384
2468
  throw new Error("Patient resource not found in the bundle");
2385
2469
  }
2386
- this.patient = patientEntry.resource;
2387
- const resources = bundle.entry.map((e) => e.resource);
2470
+ this.patients = patientEntries;
2388
2471
  for (const sectionType of Object.values(IPSSections)) {
2389
- const resourceTypesForSection = IPSSectionResourceHelper.getResourceTypesForSection(sectionType);
2390
- const customFilter = IPSSectionResourceHelper.getResourceFilterForSection(sectionType);
2391
- let sectionResources = resources.filter(
2392
- (r) => r && typeof r.resourceType === "string" && resourceTypesForSection.includes(r.resourceType)
2393
- );
2394
- if (customFilter) {
2395
- sectionResources = sectionResources.filter((resource) => resource && customFilter(resource));
2472
+ if (sectionType === "Patient" /* PATIENT */) {
2473
+ continue;
2396
2474
  }
2475
+ const sectionFilter = IPSSectionResourceHelper.getResourceFilterForSection(sectionType);
2476
+ const sectionResources = resources.filter((resource) => sectionFilter(resource));
2397
2477
  await this.addSectionAsync(sectionType, sectionResources, timezone);
2398
2478
  }
2399
2479
  return this;
@@ -2404,16 +2484,18 @@ var ComprehensiveIPSCompositionBuilder = class {
2404
2484
  * @param authorOrganizationName - Name of the authoring organization
2405
2485
  * @param baseUrl - Base URL for the FHIR server (e.g., 'https://example.com/fhir')
2406
2486
  * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
2487
+ * @param patientId - Optional patient ID to use as primary patient for composition reference
2407
2488
  */
2408
- async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone) {
2489
+ async buildBundleAsync(authorOrganizationId, authorOrganizationName, baseUrl, timezone, patientId) {
2409
2490
  if (baseUrl.endsWith("/")) {
2410
2491
  baseUrl = baseUrl.slice(0, -1);
2411
2492
  }
2412
- if (!this.patient) {
2493
+ if (!this.patients) {
2413
2494
  throw new Error("Patient resource must be set before building the bundle");
2414
2495
  }
2496
+ const primaryPatientId = patientId ?? this.patients[0].id;
2415
2497
  const composition = {
2416
- id: `Composition-${this.patient.id}`,
2498
+ id: `Composition-${primaryPatientId}`,
2417
2499
  resourceType: "Composition",
2418
2500
  status: "final",
2419
2501
  type: {
@@ -2424,7 +2506,7 @@ var ComprehensiveIPSCompositionBuilder = class {
2424
2506
  }]
2425
2507
  },
2426
2508
  subject: {
2427
- reference: `Patient/${this.patient.id}`
2509
+ reference: `Patient/${primaryPatientId}`
2428
2510
  },
2429
2511
  author: [{
2430
2512
  reference: `Organization/${authorOrganizationId}`,
@@ -2436,7 +2518,7 @@ var ComprehensiveIPSCompositionBuilder = class {
2436
2518
  section: this.sections,
2437
2519
  text: await NarrativeGenerator.generateNarrativeAsync(
2438
2520
  "Patient" /* PATIENT */,
2439
- [this.patient],
2521
+ this.patients,
2440
2522
  timezone,
2441
2523
  true
2442
2524
  )
@@ -2455,9 +2537,11 @@ var ComprehensiveIPSCompositionBuilder = class {
2455
2537
  fullUrl: `${baseUrl}/Composition/${composition.id}`,
2456
2538
  resource: composition
2457
2539
  });
2458
- bundle.entry?.push({
2459
- fullUrl: `${baseUrl}/Patient/${this.patient.id}`,
2460
- resource: this.patient
2540
+ this.patients.forEach((patient) => {
2541
+ bundle.entry?.push({
2542
+ fullUrl: `${baseUrl}/Patient/${patient.id}`,
2543
+ resource: patient
2544
+ });
2461
2545
  });
2462
2546
  this.resources.forEach((resource) => {
2463
2547
  if (resource.resourceType !== "Patient") {