@blackcode_sa/metaestetics-api 1.5.44 → 1.5.46

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.
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/types/notifications/index.ts
2
9
  var NotificationType = /* @__PURE__ */ ((NotificationType2) => {
3
10
  NotificationType2["PRE_REQUIREMENT"] = "preRequirement";
@@ -1512,9 +1519,73 @@ var PatientAggregationService = class {
1512
1519
 
1513
1520
  // src/admin/mailing/base.mailing.service.ts
1514
1521
  import * as admin6 from "firebase-admin";
1522
+
1523
+ // src/admin/logger/index.ts
1524
+ var firebaseFunctionsLogger;
1525
+ try {
1526
+ firebaseFunctionsLogger = __require("firebase-functions/logger");
1527
+ __require("firebase-functions/logger/compat");
1528
+ } catch (e) {
1529
+ }
1530
+ var Logger = class {
1531
+ /**
1532
+ * Log an error message
1533
+ * @param message Message to log
1534
+ * @param data Optional data to include
1535
+ */
1536
+ static error(message, data) {
1537
+ if (firebaseFunctionsLogger) {
1538
+ firebaseFunctionsLogger.error(message, data);
1539
+ } else {
1540
+ console.error(message, data !== void 0 ? data : "");
1541
+ }
1542
+ }
1543
+ /**
1544
+ * Log a warning message
1545
+ * @param message Message to log
1546
+ * @param data Optional data to include
1547
+ */
1548
+ static warn(message, data) {
1549
+ if (firebaseFunctionsLogger) {
1550
+ firebaseFunctionsLogger.warn(message, data);
1551
+ } else {
1552
+ console.warn(message, data !== void 0 ? data : "");
1553
+ }
1554
+ }
1555
+ /**
1556
+ * Log an info message
1557
+ * @param message Message to log
1558
+ * @param data Optional data to include
1559
+ */
1560
+ static info(message, data) {
1561
+ if (firebaseFunctionsLogger) {
1562
+ firebaseFunctionsLogger.info(message, data);
1563
+ } else {
1564
+ console.info(message, data !== void 0 ? data : "");
1565
+ }
1566
+ }
1567
+ /**
1568
+ * Log a debug message
1569
+ * @param message Message to log
1570
+ * @param data Optional data to include
1571
+ */
1572
+ static debug(message, data) {
1573
+ if (firebaseFunctionsLogger) {
1574
+ firebaseFunctionsLogger.debug(message, data);
1575
+ } else {
1576
+ console.debug(message, data !== void 0 ? data : "");
1577
+ }
1578
+ }
1579
+ };
1580
+
1581
+ // src/admin/mailing/base.mailing.service.ts
1515
1582
  var BaseMailingService = class {
1516
1583
  // Removed config property as it's no longer managed here
1517
- // protected config: MailgunConfig;
1584
+ // import {
1585
+ // getMailgunConfig,
1586
+ // createMailgunClient,
1587
+ // MailgunConfig,
1588
+ // } from "./mailgun.config";
1518
1589
  /**
1519
1590
  * Constructor for BaseMailingService
1520
1591
  * @param firestore Firestore instance provided by the caller
@@ -1523,6 +1594,15 @@ var BaseMailingService = class {
1523
1594
  constructor(firestore8, mailgunClient) {
1524
1595
  this.db = firestore8;
1525
1596
  this.mailgunClient = mailgunClient;
1597
+ if (!this.db) {
1598
+ Logger.error("[BaseMailingService] No Firestore instance provided");
1599
+ throw new Error("Firestore instance is required");
1600
+ }
1601
+ if (!this.mailgunClient) {
1602
+ Logger.error("[BaseMailingService] No Mailgun client provided");
1603
+ throw new Error("Mailgun client is required");
1604
+ }
1605
+ Logger.info("[BaseMailingService] Service initialized successfully");
1526
1606
  }
1527
1607
  /**
1528
1608
  * Sends an email using Mailgun
@@ -1531,29 +1611,69 @@ var BaseMailingService = class {
1531
1611
  */
1532
1612
  async sendEmail(data) {
1533
1613
  try {
1614
+ if (!data) {
1615
+ throw new Error("Email data object is required");
1616
+ }
1617
+ if (!data.to) {
1618
+ throw new Error("Email 'to' address is required");
1619
+ }
1534
1620
  if (!data.from) {
1535
1621
  throw new Error(
1536
1622
  "Email 'from' address must be provided in sendEmail data."
1537
1623
  );
1538
1624
  }
1625
+ if (!data.subject) {
1626
+ throw new Error("Email 'subject' is required");
1627
+ }
1628
+ if (!data.html && !data.text) {
1629
+ throw new Error("Email must have either 'html' or 'text' content");
1630
+ }
1631
+ Logger.info("[BaseMailingService] Sending email via Mailgun", {
1632
+ to: data.to,
1633
+ from: data.from,
1634
+ subject: data.subject,
1635
+ hasHtml: !!data.html,
1636
+ hasText: !!data.text
1637
+ });
1539
1638
  return await new Promise(
1540
1639
  (resolve, reject) => {
1541
- this.mailgunClient.messages().send(data, (error, body) => {
1542
- if (error) {
1543
- console.error("[BaseMailingService] Error sending email:", error);
1544
- reject(error);
1545
- } else {
1546
- console.log(
1547
- "[BaseMailingService] Email sent successfully:",
1548
- body
1549
- );
1550
- resolve(body);
1640
+ try {
1641
+ const messagesApi = this.mailgunClient.messages();
1642
+ if (!messagesApi) {
1643
+ throw new Error("Could not get Mailgun messages API");
1551
1644
  }
1552
- });
1645
+ messagesApi.send(data, (error, body) => {
1646
+ if (error) {
1647
+ Logger.error("[BaseMailingService] Mailgun API error:", {
1648
+ error: error instanceof Error ? error.message : error,
1649
+ stack: error instanceof Error ? error.stack : void 0
1650
+ });
1651
+ reject(error);
1652
+ } else {
1653
+ Logger.info(
1654
+ "[BaseMailingService] Email sent successfully:",
1655
+ body
1656
+ );
1657
+ resolve(body);
1658
+ }
1659
+ });
1660
+ } catch (sendError) {
1661
+ Logger.error(
1662
+ "[BaseMailingService] Error in mailgun.messages().send():",
1663
+ {
1664
+ error: sendError instanceof Error ? sendError.message : sendError,
1665
+ stack: sendError instanceof Error ? sendError.stack : void 0
1666
+ }
1667
+ );
1668
+ reject(sendError);
1669
+ }
1553
1670
  }
1554
1671
  );
1555
1672
  } catch (error) {
1556
- console.error("[BaseMailingService] Error in sendEmail:", error);
1673
+ Logger.error("[BaseMailingService] Error in sendEmail:", {
1674
+ error: error instanceof Error ? error.message : error,
1675
+ stack: error instanceof Error ? error.stack : void 0
1676
+ });
1557
1677
  throw error;
1558
1678
  }
1559
1679
  }
@@ -1571,14 +1691,17 @@ var BaseMailingService = class {
1571
1691
  subject: emailData.subject,
1572
1692
  templateName: emailData.templateName,
1573
1693
  success,
1574
- error: error ? JSON.stringify(error) : null,
1694
+ error: error ? error instanceof Error ? { message: error.message, stack: error.stack } : JSON.stringify(error) : null,
1575
1695
  sentAt: admin6.firestore.FieldValue.serverTimestamp()
1576
1696
  });
1577
- } catch (logError) {
1578
- console.error(
1579
- "[BaseMailingService] Error logging email attempt:",
1580
- logError
1697
+ Logger.info(
1698
+ `[BaseMailingService] Email log recorded. Success: ${success}`
1581
1699
  );
1700
+ } catch (logError) {
1701
+ Logger.error("[BaseMailingService] Error logging email attempt:", {
1702
+ error: logError instanceof Error ? logError.message : logError,
1703
+ stack: logError instanceof Error ? logError.stack : void 0
1704
+ });
1582
1705
  }
1583
1706
  }
1584
1707
  /**
@@ -1588,12 +1711,24 @@ var BaseMailingService = class {
1588
1711
  * @returns Rendered HTML string
1589
1712
  */
1590
1713
  renderTemplate(template, variables) {
1591
- let rendered = template;
1592
- Object.entries(variables).forEach(([key, value]) => {
1593
- const regex = new RegExp(`{{\\s*${key}\\s*}}`, "g");
1594
- rendered = rendered.replace(regex, value);
1595
- });
1596
- return rendered;
1714
+ if (!template) {
1715
+ throw new Error("Email template is required");
1716
+ }
1717
+ try {
1718
+ let rendered = template;
1719
+ Object.entries(variables).forEach(([key, value]) => {
1720
+ const regex = new RegExp(`{{\\s*${key}\\s*}}`, "g");
1721
+ rendered = rendered.replace(regex, value || "");
1722
+ });
1723
+ return rendered;
1724
+ } catch (renderError) {
1725
+ Logger.error("[BaseMailingService] Error rendering template:", {
1726
+ error: renderError instanceof Error ? renderError.message : renderError
1727
+ });
1728
+ throw new Error(
1729
+ `Template rendering failed: ${renderError instanceof Error ? renderError.message : "Unknown error"}`
1730
+ );
1731
+ }
1597
1732
  }
1598
1733
  };
1599
1734
 
@@ -1706,9 +1841,9 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1706
1841
  */
1707
1842
  constructor(firestore8, mailgunClient) {
1708
1843
  super(firestore8, mailgunClient);
1709
- this.DEFAULT_REGISTRATION_URL = "https://app.medclinic.com/register";
1844
+ this.DEFAULT_REGISTRATION_URL = "https://metaestetics.net/register";
1710
1845
  this.DEFAULT_SUBJECT = "You've Been Invited to Join as a Practitioner";
1711
- this.DEFAULT_FROM_ADDRESS = "MedClinic <no-reply@your-domain.com>";
1846
+ this.DEFAULT_FROM_ADDRESS = "MedClinic <no-reply@mg.metaestetics.net>";
1712
1847
  }
1713
1848
  /**
1714
1849
  * Sends a practitioner invitation email
@@ -1718,7 +1853,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1718
1853
  async sendInvitationEmail(data) {
1719
1854
  var _a, _b, _c, _d;
1720
1855
  try {
1721
- console.log(
1856
+ Logger.info(
1722
1857
  "[PractitionerInviteMailingService] Sending invitation email to",
1723
1858
  data.token.email
1724
1859
  );
@@ -1745,6 +1880,16 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1745
1880
  contactEmail,
1746
1881
  currentYear
1747
1882
  };
1883
+ Logger.info("[PractitionerInviteMailingService] Template variables:", {
1884
+ clinicName: templateVariables.clinicName,
1885
+ practitionerName: templateVariables.practitionerName,
1886
+ expirationDate: templateVariables.expirationDate,
1887
+ registrationUrl: templateVariables.registrationUrl,
1888
+ contactName: templateVariables.contactName,
1889
+ contactEmail: templateVariables.contactEmail,
1890
+ // Don't log the invite token for security
1891
+ hasInviteToken: !!templateVariables.inviteToken
1892
+ });
1748
1893
  const html = this.renderTemplate(
1749
1894
  practitionerInvitationTemplate,
1750
1895
  templateVariables
@@ -1755,6 +1900,15 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1755
1900
  subject,
1756
1901
  html
1757
1902
  };
1903
+ Logger.info(
1904
+ "[PractitionerInviteMailingService] Sending email with data:",
1905
+ {
1906
+ to: emailData.to,
1907
+ from: emailData.from,
1908
+ subject: emailData.subject,
1909
+ hasHtml: !!emailData.html
1910
+ }
1911
+ );
1758
1912
  const result = await this.sendEmail(emailData);
1759
1913
  await this.logEmailAttempt(
1760
1914
  {
@@ -1766,9 +1920,12 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1766
1920
  );
1767
1921
  return result;
1768
1922
  } catch (error) {
1769
- console.error(
1923
+ Logger.error(
1770
1924
  "[PractitionerInviteMailingService] Error sending invitation email:",
1771
- error
1925
+ {
1926
+ error: error instanceof Error ? error.message : error,
1927
+ stack: error instanceof Error ? error.stack : void 0
1928
+ }
1772
1929
  );
1773
1930
  await this.logEmailAttempt(
1774
1931
  {
@@ -1792,22 +1949,66 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1792
1949
  */
1793
1950
  async handleTokenCreationEvent(tokenData, fromAddress) {
1794
1951
  try {
1795
- console.log(
1952
+ Logger.info(
1796
1953
  "[PractitionerInviteMailingService] Handling token creation event for token:",
1797
1954
  tokenData.id
1798
1955
  );
1956
+ if (!tokenData || !tokenData.id || !tokenData.token || !tokenData.email) {
1957
+ throw new Error(
1958
+ `Invalid token data: Missing required properties. Token ID: ${tokenData == null ? void 0 : tokenData.id}`
1959
+ );
1960
+ }
1961
+ if (!tokenData.practitionerId) {
1962
+ throw new Error(
1963
+ `Token ${tokenData.id} is missing practitionerId reference`
1964
+ );
1965
+ }
1966
+ if (!tokenData.clinicId) {
1967
+ throw new Error(`Token ${tokenData.id} is missing clinicId reference`);
1968
+ }
1969
+ if (!tokenData.expiresAt) {
1970
+ throw new Error(`Token ${tokenData.id} is missing expiration date`);
1971
+ }
1972
+ Logger.info(
1973
+ `[PractitionerInviteMailingService] Fetching practitioner data: ${tokenData.practitionerId}`
1974
+ );
1799
1975
  const practitionerRef = this.db.collection(PRACTITIONERS_COLLECTION).doc(tokenData.practitionerId);
1800
1976
  const practitionerDoc = await practitionerRef.get();
1801
1977
  if (!practitionerDoc.exists) {
1802
1978
  throw new Error(`Practitioner ${tokenData.practitionerId} not found`);
1803
1979
  }
1804
1980
  const practitionerData = practitionerDoc.data();
1981
+ if (!practitionerData || !practitionerData.basicInfo) {
1982
+ throw new Error(
1983
+ `Practitioner ${tokenData.practitionerId} has invalid data structure`
1984
+ );
1985
+ }
1986
+ Logger.info(
1987
+ `[PractitionerInviteMailingService] Practitioner found: ${practitionerData.basicInfo.firstName} ${practitionerData.basicInfo.lastName}`
1988
+ );
1989
+ Logger.info(
1990
+ `[PractitionerInviteMailingService] Fetching clinic data: ${tokenData.clinicId}`
1991
+ );
1805
1992
  const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(tokenData.clinicId);
1806
1993
  const clinicDoc = await clinicRef.get();
1807
1994
  if (!clinicDoc.exists) {
1808
1995
  throw new Error(`Clinic ${tokenData.clinicId} not found`);
1809
1996
  }
1810
1997
  const clinicData = clinicDoc.data();
1998
+ if (!clinicData || !clinicData.contactInfo) {
1999
+ throw new Error(
2000
+ `Clinic ${tokenData.clinicId} has invalid data structure`
2001
+ );
2002
+ }
2003
+ Logger.info(
2004
+ `[PractitionerInviteMailingService] Clinic found: ${clinicData.name}`
2005
+ );
2006
+ if (!fromAddress) {
2007
+ Logger.warn(
2008
+ "[PractitionerInviteMailingService] No fromAddress provided, using default"
2009
+ );
2010
+ fromAddress = this.DEFAULT_FROM_ADDRESS;
2011
+ }
1811
2012
  const emailData = {
1812
2013
  token: {
1813
2014
  id: tokenData.id,
@@ -1823,20 +2024,28 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1823
2024
  },
1824
2025
  clinic: {
1825
2026
  name: clinicData.name || "Medical Clinic",
1826
- contactEmail: clinicData.contactInfo.email || "contact@medclinic.com"
2027
+ contactEmail: clinicData.contactInfo.email || "contact@medclinic.com",
2028
+ // Since there's no contactPerson in the Clinic model, we'll just use "Clinic Admin"
2029
+ contactName: "Clinic Admin"
1827
2030
  },
1828
2031
  options: {
1829
2032
  fromAddress
1830
2033
  }
1831
2034
  };
2035
+ Logger.info(
2036
+ "[PractitionerInviteMailingService] Email data prepared, sending invitation"
2037
+ );
1832
2038
  await this.sendInvitationEmail(emailData);
1833
- console.log(
2039
+ Logger.info(
1834
2040
  "[PractitionerInviteMailingService] Invitation email sent successfully"
1835
2041
  );
1836
2042
  } catch (error) {
1837
- console.error(
2043
+ Logger.error(
1838
2044
  "[PractitionerInviteMailingService] Error handling token creation event:",
1839
- error
2045
+ {
2046
+ error: error instanceof Error ? error.message : error,
2047
+ stack: error instanceof Error ? error.stack : void 0
2048
+ }
1840
2049
  );
1841
2050
  throw error;
1842
2051
  }
package/dist/index.d.mts CHANGED
@@ -4743,8 +4743,8 @@ declare class PatientService extends BaseService {
4743
4743
  uploadProfilePhoto(patientId: string, file: File): Promise<string>;
4744
4744
  updateProfilePhoto(patientId: string, file: File): Promise<string>;
4745
4745
  deleteProfilePhoto(patientId: string): Promise<void>;
4746
- updatePatientProfile(patientId: string, data: Partial<Omit<PatientProfile, 'id' | 'createdAt' | 'updatedAt'>>): Promise<PatientProfile>;
4747
- updatePatientProfileByUserRef(userRef: string, data: Partial<Omit<PatientProfile, 'id' | 'createdAt' | 'updatedAt'>>): Promise<PatientProfile>;
4746
+ updatePatientProfile(patientId: string, data: Partial<Omit<PatientProfile, "id" | "createdAt" | "updatedAt">>): Promise<PatientProfile>;
4747
+ updatePatientProfileByUserRef(userRef: string, data: Partial<Omit<PatientProfile, "id" | "createdAt" | "updatedAt">>): Promise<PatientProfile>;
4748
4748
  /**
4749
4749
  * Searches for patient profiles based on clinic/practitioner association.
4750
4750
  * Requires information about the requester for security checks.
@@ -4766,6 +4766,32 @@ declare class PatientService extends BaseService {
4766
4766
  limit?: number;
4767
4767
  startAfter?: string;
4768
4768
  }): Promise<PatientProfile[]>;
4769
+ /**
4770
+ * Gets all patients associated with a specific practitioner.
4771
+ *
4772
+ * @param {string} practitionerId - ID of the practitioner whose patients to retrieve
4773
+ * @param {Object} options - Optional parameters for pagination
4774
+ * @param {number} options.limit - Maximum number of profiles to return
4775
+ * @param {string} options.startAfter - The ID of the document to start after (for pagination)
4776
+ * @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
4777
+ */
4778
+ getPatientsByPractitioner(practitionerId: string, options?: {
4779
+ limit?: number;
4780
+ startAfter?: string;
4781
+ }): Promise<PatientProfile[]>;
4782
+ /**
4783
+ * Gets all patients associated with a specific clinic.
4784
+ *
4785
+ * @param {string} clinicId - ID of the clinic whose patients to retrieve
4786
+ * @param {Object} options - Optional parameters for pagination
4787
+ * @param {number} options.limit - Maximum number of profiles to return
4788
+ * @param {string} options.startAfter - The ID of the document to start after (for pagination)
4789
+ * @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
4790
+ */
4791
+ getPatientsByClinic(clinicId: string, options?: {
4792
+ limit?: number;
4793
+ startAfter?: string;
4794
+ }): Promise<PatientProfile[]>;
4769
4795
  }
4770
4796
 
4771
4797
  declare class ClinicGroupService extends BaseService {
package/dist/index.d.ts CHANGED
@@ -4743,8 +4743,8 @@ declare class PatientService extends BaseService {
4743
4743
  uploadProfilePhoto(patientId: string, file: File): Promise<string>;
4744
4744
  updateProfilePhoto(patientId: string, file: File): Promise<string>;
4745
4745
  deleteProfilePhoto(patientId: string): Promise<void>;
4746
- updatePatientProfile(patientId: string, data: Partial<Omit<PatientProfile, 'id' | 'createdAt' | 'updatedAt'>>): Promise<PatientProfile>;
4747
- updatePatientProfileByUserRef(userRef: string, data: Partial<Omit<PatientProfile, 'id' | 'createdAt' | 'updatedAt'>>): Promise<PatientProfile>;
4746
+ updatePatientProfile(patientId: string, data: Partial<Omit<PatientProfile, "id" | "createdAt" | "updatedAt">>): Promise<PatientProfile>;
4747
+ updatePatientProfileByUserRef(userRef: string, data: Partial<Omit<PatientProfile, "id" | "createdAt" | "updatedAt">>): Promise<PatientProfile>;
4748
4748
  /**
4749
4749
  * Searches for patient profiles based on clinic/practitioner association.
4750
4750
  * Requires information about the requester for security checks.
@@ -4766,6 +4766,32 @@ declare class PatientService extends BaseService {
4766
4766
  limit?: number;
4767
4767
  startAfter?: string;
4768
4768
  }): Promise<PatientProfile[]>;
4769
+ /**
4770
+ * Gets all patients associated with a specific practitioner.
4771
+ *
4772
+ * @param {string} practitionerId - ID of the practitioner whose patients to retrieve
4773
+ * @param {Object} options - Optional parameters for pagination
4774
+ * @param {number} options.limit - Maximum number of profiles to return
4775
+ * @param {string} options.startAfter - The ID of the document to start after (for pagination)
4776
+ * @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
4777
+ */
4778
+ getPatientsByPractitioner(practitionerId: string, options?: {
4779
+ limit?: number;
4780
+ startAfter?: string;
4781
+ }): Promise<PatientProfile[]>;
4782
+ /**
4783
+ * Gets all patients associated with a specific clinic.
4784
+ *
4785
+ * @param {string} clinicId - ID of the clinic whose patients to retrieve
4786
+ * @param {Object} options - Optional parameters for pagination
4787
+ * @param {number} options.limit - Maximum number of profiles to return
4788
+ * @param {string} options.startAfter - The ID of the document to start after (for pagination)
4789
+ * @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
4790
+ */
4791
+ getPatientsByClinic(clinicId: string, options?: {
4792
+ limit?: number;
4793
+ startAfter?: string;
4794
+ }): Promise<PatientProfile[]>;
4769
4795
  }
4770
4796
 
4771
4797
  declare class ClinicGroupService extends BaseService {