@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.
@@ -1559,9 +1559,73 @@ var PatientAggregationService = class {
1559
1559
 
1560
1560
  // src/admin/mailing/base.mailing.service.ts
1561
1561
  var admin6 = __toESM(require("firebase-admin"));
1562
+
1563
+ // src/admin/logger/index.ts
1564
+ var firebaseFunctionsLogger;
1565
+ try {
1566
+ firebaseFunctionsLogger = require("firebase-functions/logger");
1567
+ require("firebase-functions/logger/compat");
1568
+ } catch (e) {
1569
+ }
1570
+ var Logger = class {
1571
+ /**
1572
+ * Log an error message
1573
+ * @param message Message to log
1574
+ * @param data Optional data to include
1575
+ */
1576
+ static error(message, data) {
1577
+ if (firebaseFunctionsLogger) {
1578
+ firebaseFunctionsLogger.error(message, data);
1579
+ } else {
1580
+ console.error(message, data !== void 0 ? data : "");
1581
+ }
1582
+ }
1583
+ /**
1584
+ * Log a warning message
1585
+ * @param message Message to log
1586
+ * @param data Optional data to include
1587
+ */
1588
+ static warn(message, data) {
1589
+ if (firebaseFunctionsLogger) {
1590
+ firebaseFunctionsLogger.warn(message, data);
1591
+ } else {
1592
+ console.warn(message, data !== void 0 ? data : "");
1593
+ }
1594
+ }
1595
+ /**
1596
+ * Log an info message
1597
+ * @param message Message to log
1598
+ * @param data Optional data to include
1599
+ */
1600
+ static info(message, data) {
1601
+ if (firebaseFunctionsLogger) {
1602
+ firebaseFunctionsLogger.info(message, data);
1603
+ } else {
1604
+ console.info(message, data !== void 0 ? data : "");
1605
+ }
1606
+ }
1607
+ /**
1608
+ * Log a debug message
1609
+ * @param message Message to log
1610
+ * @param data Optional data to include
1611
+ */
1612
+ static debug(message, data) {
1613
+ if (firebaseFunctionsLogger) {
1614
+ firebaseFunctionsLogger.debug(message, data);
1615
+ } else {
1616
+ console.debug(message, data !== void 0 ? data : "");
1617
+ }
1618
+ }
1619
+ };
1620
+
1621
+ // src/admin/mailing/base.mailing.service.ts
1562
1622
  var BaseMailingService = class {
1563
1623
  // Removed config property as it's no longer managed here
1564
- // protected config: MailgunConfig;
1624
+ // import {
1625
+ // getMailgunConfig,
1626
+ // createMailgunClient,
1627
+ // MailgunConfig,
1628
+ // } from "./mailgun.config";
1565
1629
  /**
1566
1630
  * Constructor for BaseMailingService
1567
1631
  * @param firestore Firestore instance provided by the caller
@@ -1570,6 +1634,15 @@ var BaseMailingService = class {
1570
1634
  constructor(firestore8, mailgunClient) {
1571
1635
  this.db = firestore8;
1572
1636
  this.mailgunClient = mailgunClient;
1637
+ if (!this.db) {
1638
+ Logger.error("[BaseMailingService] No Firestore instance provided");
1639
+ throw new Error("Firestore instance is required");
1640
+ }
1641
+ if (!this.mailgunClient) {
1642
+ Logger.error("[BaseMailingService] No Mailgun client provided");
1643
+ throw new Error("Mailgun client is required");
1644
+ }
1645
+ Logger.info("[BaseMailingService] Service initialized successfully");
1573
1646
  }
1574
1647
  /**
1575
1648
  * Sends an email using Mailgun
@@ -1578,29 +1651,69 @@ var BaseMailingService = class {
1578
1651
  */
1579
1652
  async sendEmail(data) {
1580
1653
  try {
1654
+ if (!data) {
1655
+ throw new Error("Email data object is required");
1656
+ }
1657
+ if (!data.to) {
1658
+ throw new Error("Email 'to' address is required");
1659
+ }
1581
1660
  if (!data.from) {
1582
1661
  throw new Error(
1583
1662
  "Email 'from' address must be provided in sendEmail data."
1584
1663
  );
1585
1664
  }
1665
+ if (!data.subject) {
1666
+ throw new Error("Email 'subject' is required");
1667
+ }
1668
+ if (!data.html && !data.text) {
1669
+ throw new Error("Email must have either 'html' or 'text' content");
1670
+ }
1671
+ Logger.info("[BaseMailingService] Sending email via Mailgun", {
1672
+ to: data.to,
1673
+ from: data.from,
1674
+ subject: data.subject,
1675
+ hasHtml: !!data.html,
1676
+ hasText: !!data.text
1677
+ });
1586
1678
  return await new Promise(
1587
1679
  (resolve, reject) => {
1588
- this.mailgunClient.messages().send(data, (error, body) => {
1589
- if (error) {
1590
- console.error("[BaseMailingService] Error sending email:", error);
1591
- reject(error);
1592
- } else {
1593
- console.log(
1594
- "[BaseMailingService] Email sent successfully:",
1595
- body
1596
- );
1597
- resolve(body);
1680
+ try {
1681
+ const messagesApi = this.mailgunClient.messages();
1682
+ if (!messagesApi) {
1683
+ throw new Error("Could not get Mailgun messages API");
1598
1684
  }
1599
- });
1685
+ messagesApi.send(data, (error, body) => {
1686
+ if (error) {
1687
+ Logger.error("[BaseMailingService] Mailgun API error:", {
1688
+ error: error instanceof Error ? error.message : error,
1689
+ stack: error instanceof Error ? error.stack : void 0
1690
+ });
1691
+ reject(error);
1692
+ } else {
1693
+ Logger.info(
1694
+ "[BaseMailingService] Email sent successfully:",
1695
+ body
1696
+ );
1697
+ resolve(body);
1698
+ }
1699
+ });
1700
+ } catch (sendError) {
1701
+ Logger.error(
1702
+ "[BaseMailingService] Error in mailgun.messages().send():",
1703
+ {
1704
+ error: sendError instanceof Error ? sendError.message : sendError,
1705
+ stack: sendError instanceof Error ? sendError.stack : void 0
1706
+ }
1707
+ );
1708
+ reject(sendError);
1709
+ }
1600
1710
  }
1601
1711
  );
1602
1712
  } catch (error) {
1603
- console.error("[BaseMailingService] Error in sendEmail:", error);
1713
+ Logger.error("[BaseMailingService] Error in sendEmail:", {
1714
+ error: error instanceof Error ? error.message : error,
1715
+ stack: error instanceof Error ? error.stack : void 0
1716
+ });
1604
1717
  throw error;
1605
1718
  }
1606
1719
  }
@@ -1618,14 +1731,17 @@ var BaseMailingService = class {
1618
1731
  subject: emailData.subject,
1619
1732
  templateName: emailData.templateName,
1620
1733
  success,
1621
- error: error ? JSON.stringify(error) : null,
1734
+ error: error ? error instanceof Error ? { message: error.message, stack: error.stack } : JSON.stringify(error) : null,
1622
1735
  sentAt: admin6.firestore.FieldValue.serverTimestamp()
1623
1736
  });
1624
- } catch (logError) {
1625
- console.error(
1626
- "[BaseMailingService] Error logging email attempt:",
1627
- logError
1737
+ Logger.info(
1738
+ `[BaseMailingService] Email log recorded. Success: ${success}`
1628
1739
  );
1740
+ } catch (logError) {
1741
+ Logger.error("[BaseMailingService] Error logging email attempt:", {
1742
+ error: logError instanceof Error ? logError.message : logError,
1743
+ stack: logError instanceof Error ? logError.stack : void 0
1744
+ });
1629
1745
  }
1630
1746
  }
1631
1747
  /**
@@ -1635,12 +1751,24 @@ var BaseMailingService = class {
1635
1751
  * @returns Rendered HTML string
1636
1752
  */
1637
1753
  renderTemplate(template, variables) {
1638
- let rendered = template;
1639
- Object.entries(variables).forEach(([key, value]) => {
1640
- const regex = new RegExp(`{{\\s*${key}\\s*}}`, "g");
1641
- rendered = rendered.replace(regex, value);
1642
- });
1643
- return rendered;
1754
+ if (!template) {
1755
+ throw new Error("Email template is required");
1756
+ }
1757
+ try {
1758
+ let rendered = template;
1759
+ Object.entries(variables).forEach(([key, value]) => {
1760
+ const regex = new RegExp(`{{\\s*${key}\\s*}}`, "g");
1761
+ rendered = rendered.replace(regex, value || "");
1762
+ });
1763
+ return rendered;
1764
+ } catch (renderError) {
1765
+ Logger.error("[BaseMailingService] Error rendering template:", {
1766
+ error: renderError instanceof Error ? renderError.message : renderError
1767
+ });
1768
+ throw new Error(
1769
+ `Template rendering failed: ${renderError instanceof Error ? renderError.message : "Unknown error"}`
1770
+ );
1771
+ }
1644
1772
  }
1645
1773
  };
1646
1774
 
@@ -1753,9 +1881,9 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1753
1881
  */
1754
1882
  constructor(firestore8, mailgunClient) {
1755
1883
  super(firestore8, mailgunClient);
1756
- this.DEFAULT_REGISTRATION_URL = "https://app.medclinic.com/register";
1884
+ this.DEFAULT_REGISTRATION_URL = "https://metaestetics.net/register";
1757
1885
  this.DEFAULT_SUBJECT = "You've Been Invited to Join as a Practitioner";
1758
- this.DEFAULT_FROM_ADDRESS = "MedClinic <no-reply@your-domain.com>";
1886
+ this.DEFAULT_FROM_ADDRESS = "MedClinic <no-reply@mg.metaestetics.net>";
1759
1887
  }
1760
1888
  /**
1761
1889
  * Sends a practitioner invitation email
@@ -1765,7 +1893,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1765
1893
  async sendInvitationEmail(data) {
1766
1894
  var _a, _b, _c, _d;
1767
1895
  try {
1768
- console.log(
1896
+ Logger.info(
1769
1897
  "[PractitionerInviteMailingService] Sending invitation email to",
1770
1898
  data.token.email
1771
1899
  );
@@ -1792,6 +1920,16 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1792
1920
  contactEmail,
1793
1921
  currentYear
1794
1922
  };
1923
+ Logger.info("[PractitionerInviteMailingService] Template variables:", {
1924
+ clinicName: templateVariables.clinicName,
1925
+ practitionerName: templateVariables.practitionerName,
1926
+ expirationDate: templateVariables.expirationDate,
1927
+ registrationUrl: templateVariables.registrationUrl,
1928
+ contactName: templateVariables.contactName,
1929
+ contactEmail: templateVariables.contactEmail,
1930
+ // Don't log the invite token for security
1931
+ hasInviteToken: !!templateVariables.inviteToken
1932
+ });
1795
1933
  const html = this.renderTemplate(
1796
1934
  practitionerInvitationTemplate,
1797
1935
  templateVariables
@@ -1802,6 +1940,15 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1802
1940
  subject,
1803
1941
  html
1804
1942
  };
1943
+ Logger.info(
1944
+ "[PractitionerInviteMailingService] Sending email with data:",
1945
+ {
1946
+ to: emailData.to,
1947
+ from: emailData.from,
1948
+ subject: emailData.subject,
1949
+ hasHtml: !!emailData.html
1950
+ }
1951
+ );
1805
1952
  const result = await this.sendEmail(emailData);
1806
1953
  await this.logEmailAttempt(
1807
1954
  {
@@ -1813,9 +1960,12 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1813
1960
  );
1814
1961
  return result;
1815
1962
  } catch (error) {
1816
- console.error(
1963
+ Logger.error(
1817
1964
  "[PractitionerInviteMailingService] Error sending invitation email:",
1818
- error
1965
+ {
1966
+ error: error instanceof Error ? error.message : error,
1967
+ stack: error instanceof Error ? error.stack : void 0
1968
+ }
1819
1969
  );
1820
1970
  await this.logEmailAttempt(
1821
1971
  {
@@ -1839,22 +1989,66 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1839
1989
  */
1840
1990
  async handleTokenCreationEvent(tokenData, fromAddress) {
1841
1991
  try {
1842
- console.log(
1992
+ Logger.info(
1843
1993
  "[PractitionerInviteMailingService] Handling token creation event for token:",
1844
1994
  tokenData.id
1845
1995
  );
1996
+ if (!tokenData || !tokenData.id || !tokenData.token || !tokenData.email) {
1997
+ throw new Error(
1998
+ `Invalid token data: Missing required properties. Token ID: ${tokenData == null ? void 0 : tokenData.id}`
1999
+ );
2000
+ }
2001
+ if (!tokenData.practitionerId) {
2002
+ throw new Error(
2003
+ `Token ${tokenData.id} is missing practitionerId reference`
2004
+ );
2005
+ }
2006
+ if (!tokenData.clinicId) {
2007
+ throw new Error(`Token ${tokenData.id} is missing clinicId reference`);
2008
+ }
2009
+ if (!tokenData.expiresAt) {
2010
+ throw new Error(`Token ${tokenData.id} is missing expiration date`);
2011
+ }
2012
+ Logger.info(
2013
+ `[PractitionerInviteMailingService] Fetching practitioner data: ${tokenData.practitionerId}`
2014
+ );
1846
2015
  const practitionerRef = this.db.collection(PRACTITIONERS_COLLECTION).doc(tokenData.practitionerId);
1847
2016
  const practitionerDoc = await practitionerRef.get();
1848
2017
  if (!practitionerDoc.exists) {
1849
2018
  throw new Error(`Practitioner ${tokenData.practitionerId} not found`);
1850
2019
  }
1851
2020
  const practitionerData = practitionerDoc.data();
2021
+ if (!practitionerData || !practitionerData.basicInfo) {
2022
+ throw new Error(
2023
+ `Practitioner ${tokenData.practitionerId} has invalid data structure`
2024
+ );
2025
+ }
2026
+ Logger.info(
2027
+ `[PractitionerInviteMailingService] Practitioner found: ${practitionerData.basicInfo.firstName} ${practitionerData.basicInfo.lastName}`
2028
+ );
2029
+ Logger.info(
2030
+ `[PractitionerInviteMailingService] Fetching clinic data: ${tokenData.clinicId}`
2031
+ );
1852
2032
  const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(tokenData.clinicId);
1853
2033
  const clinicDoc = await clinicRef.get();
1854
2034
  if (!clinicDoc.exists) {
1855
2035
  throw new Error(`Clinic ${tokenData.clinicId} not found`);
1856
2036
  }
1857
2037
  const clinicData = clinicDoc.data();
2038
+ if (!clinicData || !clinicData.contactInfo) {
2039
+ throw new Error(
2040
+ `Clinic ${tokenData.clinicId} has invalid data structure`
2041
+ );
2042
+ }
2043
+ Logger.info(
2044
+ `[PractitionerInviteMailingService] Clinic found: ${clinicData.name}`
2045
+ );
2046
+ if (!fromAddress) {
2047
+ Logger.warn(
2048
+ "[PractitionerInviteMailingService] No fromAddress provided, using default"
2049
+ );
2050
+ fromAddress = this.DEFAULT_FROM_ADDRESS;
2051
+ }
1858
2052
  const emailData = {
1859
2053
  token: {
1860
2054
  id: tokenData.id,
@@ -1870,20 +2064,28 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1870
2064
  },
1871
2065
  clinic: {
1872
2066
  name: clinicData.name || "Medical Clinic",
1873
- contactEmail: clinicData.contactInfo.email || "contact@medclinic.com"
2067
+ contactEmail: clinicData.contactInfo.email || "contact@medclinic.com",
2068
+ // Since there's no contactPerson in the Clinic model, we'll just use "Clinic Admin"
2069
+ contactName: "Clinic Admin"
1874
2070
  },
1875
2071
  options: {
1876
2072
  fromAddress
1877
2073
  }
1878
2074
  };
2075
+ Logger.info(
2076
+ "[PractitionerInviteMailingService] Email data prepared, sending invitation"
2077
+ );
1879
2078
  await this.sendInvitationEmail(emailData);
1880
- console.log(
2079
+ Logger.info(
1881
2080
  "[PractitionerInviteMailingService] Invitation email sent successfully"
1882
2081
  );
1883
2082
  } catch (error) {
1884
- console.error(
2083
+ Logger.error(
1885
2084
  "[PractitionerInviteMailingService] Error handling token creation event:",
1886
- error
2085
+ {
2086
+ error: error instanceof Error ? error.message : error,
2087
+ stack: error instanceof Error ? error.stack : void 0
2088
+ }
1887
2089
  );
1888
2090
  throw error;
1889
2091
  }