@blackcode_sa/metaestetics-api 1.5.45 → 1.5.47

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.
@@ -737,6 +737,10 @@ interface PractitionerToken {
737
737
  expiresAt: Timestamp;
738
738
  usedBy?: string;
739
739
  usedAt?: Timestamp;
740
+ emailSent?: boolean;
741
+ emailSentAt?: Timestamp;
742
+ emailError?: string;
743
+ emailErrorAt?: Timestamp;
740
744
  }
741
745
 
742
746
  /**
@@ -737,6 +737,10 @@ interface PractitionerToken {
737
737
  expiresAt: Timestamp;
738
738
  usedBy?: string;
739
739
  usedAt?: Timestamp;
740
+ emailSent?: boolean;
741
+ emailSentAt?: Timestamp;
742
+ emailError?: string;
743
+ emailErrorAt?: Timestamp;
740
744
  }
741
745
 
742
746
  /**
@@ -40,6 +40,7 @@ __export(index_exports, {
40
40
  PatientAggregationService: () => PatientAggregationService,
41
41
  PractitionerAggregationService: () => PractitionerAggregationService,
42
42
  PractitionerInviteMailingService: () => PractitionerInviteMailingService,
43
+ PractitionerTokenStatus: () => PractitionerTokenStatus,
43
44
  ProcedureAggregationService: () => ProcedureAggregationService,
44
45
  UserRole: () => UserRole
45
46
  });
@@ -238,6 +239,13 @@ var admin2 = __toESM(require("firebase-admin"));
238
239
 
239
240
  // src/types/practitioner/index.ts
240
241
  var PRACTITIONERS_COLLECTION = "practitioners";
242
+ var PractitionerTokenStatus = /* @__PURE__ */ ((PractitionerTokenStatus2) => {
243
+ PractitionerTokenStatus2["ACTIVE"] = "active";
244
+ PractitionerTokenStatus2["USED"] = "used";
245
+ PractitionerTokenStatus2["EXPIRED"] = "expired";
246
+ PractitionerTokenStatus2["REVOKED"] = "revoked";
247
+ return PractitionerTokenStatus2;
248
+ })(PractitionerTokenStatus || {});
241
249
 
242
250
  // src/types/procedure/index.ts
243
251
  var PROCEDURES_COLLECTION = "procedures";
@@ -1559,9 +1567,73 @@ var PatientAggregationService = class {
1559
1567
 
1560
1568
  // src/admin/mailing/base.mailing.service.ts
1561
1569
  var admin6 = __toESM(require("firebase-admin"));
1570
+
1571
+ // src/admin/logger/index.ts
1572
+ var firebaseFunctionsLogger;
1573
+ try {
1574
+ firebaseFunctionsLogger = require("firebase-functions/logger");
1575
+ require("firebase-functions/logger/compat");
1576
+ } catch (e) {
1577
+ }
1578
+ var Logger = class {
1579
+ /**
1580
+ * Log an error message
1581
+ * @param message Message to log
1582
+ * @param data Optional data to include
1583
+ */
1584
+ static error(message, data) {
1585
+ if (firebaseFunctionsLogger) {
1586
+ firebaseFunctionsLogger.error(message, data);
1587
+ } else {
1588
+ console.error(message, data !== void 0 ? data : "");
1589
+ }
1590
+ }
1591
+ /**
1592
+ * Log a warning message
1593
+ * @param message Message to log
1594
+ * @param data Optional data to include
1595
+ */
1596
+ static warn(message, data) {
1597
+ if (firebaseFunctionsLogger) {
1598
+ firebaseFunctionsLogger.warn(message, data);
1599
+ } else {
1600
+ console.warn(message, data !== void 0 ? data : "");
1601
+ }
1602
+ }
1603
+ /**
1604
+ * Log an info message
1605
+ * @param message Message to log
1606
+ * @param data Optional data to include
1607
+ */
1608
+ static info(message, data) {
1609
+ if (firebaseFunctionsLogger) {
1610
+ firebaseFunctionsLogger.info(message, data);
1611
+ } else {
1612
+ console.info(message, data !== void 0 ? data : "");
1613
+ }
1614
+ }
1615
+ /**
1616
+ * Log a debug message
1617
+ * @param message Message to log
1618
+ * @param data Optional data to include
1619
+ */
1620
+ static debug(message, data) {
1621
+ if (firebaseFunctionsLogger) {
1622
+ firebaseFunctionsLogger.debug(message, data);
1623
+ } else {
1624
+ console.debug(message, data !== void 0 ? data : "");
1625
+ }
1626
+ }
1627
+ };
1628
+
1629
+ // src/admin/mailing/base.mailing.service.ts
1562
1630
  var BaseMailingService = class {
1563
1631
  // Removed config property as it's no longer managed here
1564
- // protected config: MailgunConfig;
1632
+ // import {
1633
+ // getMailgunConfig,
1634
+ // createMailgunClient,
1635
+ // MailgunConfig,
1636
+ // } from "./mailgun.config";
1565
1637
  /**
1566
1638
  * Constructor for BaseMailingService
1567
1639
  * @param firestore Firestore instance provided by the caller
@@ -1571,14 +1643,14 @@ var BaseMailingService = class {
1571
1643
  this.db = firestore8;
1572
1644
  this.mailgunClient = mailgunClient;
1573
1645
  if (!this.db) {
1574
- console.error("[BaseMailingService] No Firestore instance provided");
1646
+ Logger.error("[BaseMailingService] No Firestore instance provided");
1575
1647
  throw new Error("Firestore instance is required");
1576
1648
  }
1577
1649
  if (!this.mailgunClient) {
1578
- console.error("[BaseMailingService] No Mailgun client provided");
1650
+ Logger.error("[BaseMailingService] No Mailgun client provided");
1579
1651
  throw new Error("Mailgun client is required");
1580
1652
  }
1581
- console.log("[BaseMailingService] Service initialized successfully");
1653
+ Logger.info("[BaseMailingService] Service initialized successfully");
1582
1654
  }
1583
1655
  /**
1584
1656
  * Sends an email using Mailgun
@@ -1604,7 +1676,7 @@ var BaseMailingService = class {
1604
1676
  if (!data.html && !data.text) {
1605
1677
  throw new Error("Email must have either 'html' or 'text' content");
1606
1678
  }
1607
- console.log("[BaseMailingService] Sending email via Mailgun", {
1679
+ Logger.info("[BaseMailingService] Sending email via Mailgun", {
1608
1680
  to: data.to,
1609
1681
  from: data.from,
1610
1682
  subject: data.subject,
@@ -1620,14 +1692,13 @@ var BaseMailingService = class {
1620
1692
  }
1621
1693
  messagesApi.send(data, (error, body) => {
1622
1694
  if (error) {
1623
- console.error(
1624
- "[BaseMailingService] Mailgun API error:",
1625
- error instanceof Error ? error.message : error,
1626
- error instanceof Error ? error.stack : ""
1627
- );
1695
+ Logger.error("[BaseMailingService] Mailgun API error:", {
1696
+ error: error instanceof Error ? error.message : error,
1697
+ stack: error instanceof Error ? error.stack : void 0
1698
+ });
1628
1699
  reject(error);
1629
1700
  } else {
1630
- console.log(
1701
+ Logger.info(
1631
1702
  "[BaseMailingService] Email sent successfully:",
1632
1703
  body
1633
1704
  );
@@ -1635,21 +1706,22 @@ var BaseMailingService = class {
1635
1706
  }
1636
1707
  });
1637
1708
  } catch (sendError) {
1638
- console.error(
1709
+ Logger.error(
1639
1710
  "[BaseMailingService] Error in mailgun.messages().send():",
1640
- sendError instanceof Error ? sendError.message : sendError,
1641
- sendError instanceof Error ? sendError.stack : ""
1711
+ {
1712
+ error: sendError instanceof Error ? sendError.message : sendError,
1713
+ stack: sendError instanceof Error ? sendError.stack : void 0
1714
+ }
1642
1715
  );
1643
1716
  reject(sendError);
1644
1717
  }
1645
1718
  }
1646
1719
  );
1647
1720
  } catch (error) {
1648
- console.error(
1649
- "[BaseMailingService] Error in sendEmail:",
1650
- error instanceof Error ? error.message : error,
1651
- error instanceof Error ? error.stack : ""
1652
- );
1721
+ Logger.error("[BaseMailingService] Error in sendEmail:", {
1722
+ error: error instanceof Error ? error.message : error,
1723
+ stack: error instanceof Error ? error.stack : void 0
1724
+ });
1653
1725
  throw error;
1654
1726
  }
1655
1727
  }
@@ -1670,15 +1742,14 @@ var BaseMailingService = class {
1670
1742
  error: error ? error instanceof Error ? { message: error.message, stack: error.stack } : JSON.stringify(error) : null,
1671
1743
  sentAt: admin6.firestore.FieldValue.serverTimestamp()
1672
1744
  });
1673
- console.log(
1745
+ Logger.info(
1674
1746
  `[BaseMailingService] Email log recorded. Success: ${success}`
1675
1747
  );
1676
1748
  } catch (logError) {
1677
- console.error(
1678
- "[BaseMailingService] Error logging email attempt:",
1679
- logError instanceof Error ? logError.message : logError,
1680
- logError instanceof Error ? logError.stack : ""
1681
- );
1749
+ Logger.error("[BaseMailingService] Error logging email attempt:", {
1750
+ error: logError instanceof Error ? logError.message : logError,
1751
+ stack: logError instanceof Error ? logError.stack : void 0
1752
+ });
1682
1753
  }
1683
1754
  }
1684
1755
  /**
@@ -1699,10 +1770,9 @@ var BaseMailingService = class {
1699
1770
  });
1700
1771
  return rendered;
1701
1772
  } catch (renderError) {
1702
- console.error(
1703
- "[BaseMailingService] Error rendering template:",
1704
- renderError instanceof Error ? renderError.message : renderError
1705
- );
1773
+ Logger.error("[BaseMailingService] Error rendering template:", {
1774
+ error: renderError instanceof Error ? renderError.message : renderError
1775
+ });
1706
1776
  throw new Error(
1707
1777
  `Template rendering failed: ${renderError instanceof Error ? renderError.message : "Unknown error"}`
1708
1778
  );
@@ -1819,9 +1889,9 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1819
1889
  */
1820
1890
  constructor(firestore8, mailgunClient) {
1821
1891
  super(firestore8, mailgunClient);
1822
- this.DEFAULT_REGISTRATION_URL = "https://app.medclinic.com/register";
1892
+ this.DEFAULT_REGISTRATION_URL = "https://metaestetics.net/register";
1823
1893
  this.DEFAULT_SUBJECT = "You've Been Invited to Join as a Practitioner";
1824
- this.DEFAULT_FROM_ADDRESS = "MedClinic <no-reply@your-domain.com>";
1894
+ this.DEFAULT_FROM_ADDRESS = "MedClinic <no-reply@mg.metaestetics.net>";
1825
1895
  }
1826
1896
  /**
1827
1897
  * Sends a practitioner invitation email
@@ -1831,7 +1901,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1831
1901
  async sendInvitationEmail(data) {
1832
1902
  var _a, _b, _c, _d;
1833
1903
  try {
1834
- console.log(
1904
+ Logger.info(
1835
1905
  "[PractitionerInviteMailingService] Sending invitation email to",
1836
1906
  data.token.email
1837
1907
  );
@@ -1858,7 +1928,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1858
1928
  contactEmail,
1859
1929
  currentYear
1860
1930
  };
1861
- console.log("[PractitionerInviteMailingService] Template variables:", {
1931
+ Logger.info("[PractitionerInviteMailingService] Template variables:", {
1862
1932
  clinicName: templateVariables.clinicName,
1863
1933
  practitionerName: templateVariables.practitionerName,
1864
1934
  expirationDate: templateVariables.expirationDate,
@@ -1878,7 +1948,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1878
1948
  subject,
1879
1949
  html
1880
1950
  };
1881
- console.log(
1951
+ Logger.info(
1882
1952
  "[PractitionerInviteMailingService] Sending email with data:",
1883
1953
  {
1884
1954
  to: emailData.to,
@@ -1898,10 +1968,12 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1898
1968
  );
1899
1969
  return result;
1900
1970
  } catch (error) {
1901
- console.error(
1971
+ Logger.error(
1902
1972
  "[PractitionerInviteMailingService] Error sending invitation email:",
1903
- error instanceof Error ? error.message : error,
1904
- error instanceof Error ? error.stack : ""
1973
+ {
1974
+ error: error instanceof Error ? error.message : error,
1975
+ stack: error instanceof Error ? error.stack : void 0
1976
+ }
1905
1977
  );
1906
1978
  await this.logEmailAttempt(
1907
1979
  {
@@ -1925,7 +1997,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1925
1997
  */
1926
1998
  async handleTokenCreationEvent(tokenData, fromAddress) {
1927
1999
  try {
1928
- console.log(
2000
+ Logger.info(
1929
2001
  "[PractitionerInviteMailingService] Handling token creation event for token:",
1930
2002
  tokenData.id
1931
2003
  );
@@ -1945,7 +2017,18 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1945
2017
  if (!tokenData.expiresAt) {
1946
2018
  throw new Error(`Token ${tokenData.id} is missing expiration date`);
1947
2019
  }
1948
- console.log(
2020
+ if (!tokenData.status) {
2021
+ throw new Error(`Token ${tokenData.id} has no status defined`);
2022
+ }
2023
+ Logger.info(
2024
+ `[PractitionerInviteMailingService] Token status validation:`,
2025
+ {
2026
+ tokenId: tokenData.id,
2027
+ status: tokenData.status,
2028
+ statusType: typeof tokenData.status
2029
+ }
2030
+ );
2031
+ Logger.info(
1949
2032
  `[PractitionerInviteMailingService] Fetching practitioner data: ${tokenData.practitionerId}`
1950
2033
  );
1951
2034
  const practitionerRef = this.db.collection(PRACTITIONERS_COLLECTION).doc(tokenData.practitionerId);
@@ -1959,10 +2042,10 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1959
2042
  `Practitioner ${tokenData.practitionerId} has invalid data structure`
1960
2043
  );
1961
2044
  }
1962
- console.log(
2045
+ Logger.info(
1963
2046
  `[PractitionerInviteMailingService] Practitioner found: ${practitionerData.basicInfo.firstName} ${practitionerData.basicInfo.lastName}`
1964
2047
  );
1965
- console.log(
2048
+ Logger.info(
1966
2049
  `[PractitionerInviteMailingService] Fetching clinic data: ${tokenData.clinicId}`
1967
2050
  );
1968
2051
  const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(tokenData.clinicId);
@@ -1976,11 +2059,11 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1976
2059
  `Clinic ${tokenData.clinicId} has invalid data structure`
1977
2060
  );
1978
2061
  }
1979
- console.log(
2062
+ Logger.info(
1980
2063
  `[PractitionerInviteMailingService] Clinic found: ${clinicData.name}`
1981
2064
  );
1982
2065
  if (!fromAddress) {
1983
- console.warn(
2066
+ Logger.warn(
1984
2067
  "[PractitionerInviteMailingService] No fromAddress provided, using default"
1985
2068
  );
1986
2069
  fromAddress = this.DEFAULT_FROM_ADDRESS;
@@ -2008,18 +2091,20 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
2008
2091
  fromAddress
2009
2092
  }
2010
2093
  };
2011
- console.log(
2094
+ Logger.info(
2012
2095
  "[PractitionerInviteMailingService] Email data prepared, sending invitation"
2013
2096
  );
2014
2097
  await this.sendInvitationEmail(emailData);
2015
- console.log(
2098
+ Logger.info(
2016
2099
  "[PractitionerInviteMailingService] Invitation email sent successfully"
2017
2100
  );
2018
2101
  } catch (error) {
2019
- console.error(
2102
+ Logger.error(
2020
2103
  "[PractitionerInviteMailingService] Error handling token creation event:",
2021
- error instanceof Error ? error.message : error,
2022
- error instanceof Error ? error.stack : ""
2104
+ {
2105
+ error: error instanceof Error ? error.message : error,
2106
+ stack: error instanceof Error ? error.stack : void 0
2107
+ }
2023
2108
  );
2024
2109
  throw error;
2025
2110
  }
@@ -2630,6 +2715,7 @@ console.log("[Admin Module] Initialized and services exported.");
2630
2715
  PatientAggregationService,
2631
2716
  PractitionerAggregationService,
2632
2717
  PractitionerInviteMailingService,
2718
+ PractitionerTokenStatus,
2633
2719
  ProcedureAggregationService,
2634
2720
  UserRole
2635
2721
  });
@@ -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";
@@ -191,6 +198,13 @@ import * as admin2 from "firebase-admin";
191
198
 
192
199
  // src/types/practitioner/index.ts
193
200
  var PRACTITIONERS_COLLECTION = "practitioners";
201
+ var PractitionerTokenStatus = /* @__PURE__ */ ((PractitionerTokenStatus2) => {
202
+ PractitionerTokenStatus2["ACTIVE"] = "active";
203
+ PractitionerTokenStatus2["USED"] = "used";
204
+ PractitionerTokenStatus2["EXPIRED"] = "expired";
205
+ PractitionerTokenStatus2["REVOKED"] = "revoked";
206
+ return PractitionerTokenStatus2;
207
+ })(PractitionerTokenStatus || {});
194
208
 
195
209
  // src/types/procedure/index.ts
196
210
  var PROCEDURES_COLLECTION = "procedures";
@@ -1512,9 +1526,73 @@ var PatientAggregationService = class {
1512
1526
 
1513
1527
  // src/admin/mailing/base.mailing.service.ts
1514
1528
  import * as admin6 from "firebase-admin";
1529
+
1530
+ // src/admin/logger/index.ts
1531
+ var firebaseFunctionsLogger;
1532
+ try {
1533
+ firebaseFunctionsLogger = __require("firebase-functions/logger");
1534
+ __require("firebase-functions/logger/compat");
1535
+ } catch (e) {
1536
+ }
1537
+ var Logger = class {
1538
+ /**
1539
+ * Log an error message
1540
+ * @param message Message to log
1541
+ * @param data Optional data to include
1542
+ */
1543
+ static error(message, data) {
1544
+ if (firebaseFunctionsLogger) {
1545
+ firebaseFunctionsLogger.error(message, data);
1546
+ } else {
1547
+ console.error(message, data !== void 0 ? data : "");
1548
+ }
1549
+ }
1550
+ /**
1551
+ * Log a warning message
1552
+ * @param message Message to log
1553
+ * @param data Optional data to include
1554
+ */
1555
+ static warn(message, data) {
1556
+ if (firebaseFunctionsLogger) {
1557
+ firebaseFunctionsLogger.warn(message, data);
1558
+ } else {
1559
+ console.warn(message, data !== void 0 ? data : "");
1560
+ }
1561
+ }
1562
+ /**
1563
+ * Log an info message
1564
+ * @param message Message to log
1565
+ * @param data Optional data to include
1566
+ */
1567
+ static info(message, data) {
1568
+ if (firebaseFunctionsLogger) {
1569
+ firebaseFunctionsLogger.info(message, data);
1570
+ } else {
1571
+ console.info(message, data !== void 0 ? data : "");
1572
+ }
1573
+ }
1574
+ /**
1575
+ * Log a debug message
1576
+ * @param message Message to log
1577
+ * @param data Optional data to include
1578
+ */
1579
+ static debug(message, data) {
1580
+ if (firebaseFunctionsLogger) {
1581
+ firebaseFunctionsLogger.debug(message, data);
1582
+ } else {
1583
+ console.debug(message, data !== void 0 ? data : "");
1584
+ }
1585
+ }
1586
+ };
1587
+
1588
+ // src/admin/mailing/base.mailing.service.ts
1515
1589
  var BaseMailingService = class {
1516
1590
  // Removed config property as it's no longer managed here
1517
- // protected config: MailgunConfig;
1591
+ // import {
1592
+ // getMailgunConfig,
1593
+ // createMailgunClient,
1594
+ // MailgunConfig,
1595
+ // } from "./mailgun.config";
1518
1596
  /**
1519
1597
  * Constructor for BaseMailingService
1520
1598
  * @param firestore Firestore instance provided by the caller
@@ -1524,14 +1602,14 @@ var BaseMailingService = class {
1524
1602
  this.db = firestore8;
1525
1603
  this.mailgunClient = mailgunClient;
1526
1604
  if (!this.db) {
1527
- console.error("[BaseMailingService] No Firestore instance provided");
1605
+ Logger.error("[BaseMailingService] No Firestore instance provided");
1528
1606
  throw new Error("Firestore instance is required");
1529
1607
  }
1530
1608
  if (!this.mailgunClient) {
1531
- console.error("[BaseMailingService] No Mailgun client provided");
1609
+ Logger.error("[BaseMailingService] No Mailgun client provided");
1532
1610
  throw new Error("Mailgun client is required");
1533
1611
  }
1534
- console.log("[BaseMailingService] Service initialized successfully");
1612
+ Logger.info("[BaseMailingService] Service initialized successfully");
1535
1613
  }
1536
1614
  /**
1537
1615
  * Sends an email using Mailgun
@@ -1557,7 +1635,7 @@ var BaseMailingService = class {
1557
1635
  if (!data.html && !data.text) {
1558
1636
  throw new Error("Email must have either 'html' or 'text' content");
1559
1637
  }
1560
- console.log("[BaseMailingService] Sending email via Mailgun", {
1638
+ Logger.info("[BaseMailingService] Sending email via Mailgun", {
1561
1639
  to: data.to,
1562
1640
  from: data.from,
1563
1641
  subject: data.subject,
@@ -1573,14 +1651,13 @@ var BaseMailingService = class {
1573
1651
  }
1574
1652
  messagesApi.send(data, (error, body) => {
1575
1653
  if (error) {
1576
- console.error(
1577
- "[BaseMailingService] Mailgun API error:",
1578
- error instanceof Error ? error.message : error,
1579
- error instanceof Error ? error.stack : ""
1580
- );
1654
+ Logger.error("[BaseMailingService] Mailgun API error:", {
1655
+ error: error instanceof Error ? error.message : error,
1656
+ stack: error instanceof Error ? error.stack : void 0
1657
+ });
1581
1658
  reject(error);
1582
1659
  } else {
1583
- console.log(
1660
+ Logger.info(
1584
1661
  "[BaseMailingService] Email sent successfully:",
1585
1662
  body
1586
1663
  );
@@ -1588,21 +1665,22 @@ var BaseMailingService = class {
1588
1665
  }
1589
1666
  });
1590
1667
  } catch (sendError) {
1591
- console.error(
1668
+ Logger.error(
1592
1669
  "[BaseMailingService] Error in mailgun.messages().send():",
1593
- sendError instanceof Error ? sendError.message : sendError,
1594
- sendError instanceof Error ? sendError.stack : ""
1670
+ {
1671
+ error: sendError instanceof Error ? sendError.message : sendError,
1672
+ stack: sendError instanceof Error ? sendError.stack : void 0
1673
+ }
1595
1674
  );
1596
1675
  reject(sendError);
1597
1676
  }
1598
1677
  }
1599
1678
  );
1600
1679
  } catch (error) {
1601
- console.error(
1602
- "[BaseMailingService] Error in sendEmail:",
1603
- error instanceof Error ? error.message : error,
1604
- error instanceof Error ? error.stack : ""
1605
- );
1680
+ Logger.error("[BaseMailingService] Error in sendEmail:", {
1681
+ error: error instanceof Error ? error.message : error,
1682
+ stack: error instanceof Error ? error.stack : void 0
1683
+ });
1606
1684
  throw error;
1607
1685
  }
1608
1686
  }
@@ -1623,15 +1701,14 @@ var BaseMailingService = class {
1623
1701
  error: error ? error instanceof Error ? { message: error.message, stack: error.stack } : JSON.stringify(error) : null,
1624
1702
  sentAt: admin6.firestore.FieldValue.serverTimestamp()
1625
1703
  });
1626
- console.log(
1704
+ Logger.info(
1627
1705
  `[BaseMailingService] Email log recorded. Success: ${success}`
1628
1706
  );
1629
1707
  } catch (logError) {
1630
- console.error(
1631
- "[BaseMailingService] Error logging email attempt:",
1632
- logError instanceof Error ? logError.message : logError,
1633
- logError instanceof Error ? logError.stack : ""
1634
- );
1708
+ Logger.error("[BaseMailingService] Error logging email attempt:", {
1709
+ error: logError instanceof Error ? logError.message : logError,
1710
+ stack: logError instanceof Error ? logError.stack : void 0
1711
+ });
1635
1712
  }
1636
1713
  }
1637
1714
  /**
@@ -1652,10 +1729,9 @@ var BaseMailingService = class {
1652
1729
  });
1653
1730
  return rendered;
1654
1731
  } catch (renderError) {
1655
- console.error(
1656
- "[BaseMailingService] Error rendering template:",
1657
- renderError instanceof Error ? renderError.message : renderError
1658
- );
1732
+ Logger.error("[BaseMailingService] Error rendering template:", {
1733
+ error: renderError instanceof Error ? renderError.message : renderError
1734
+ });
1659
1735
  throw new Error(
1660
1736
  `Template rendering failed: ${renderError instanceof Error ? renderError.message : "Unknown error"}`
1661
1737
  );
@@ -1772,9 +1848,9 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1772
1848
  */
1773
1849
  constructor(firestore8, mailgunClient) {
1774
1850
  super(firestore8, mailgunClient);
1775
- this.DEFAULT_REGISTRATION_URL = "https://app.medclinic.com/register";
1851
+ this.DEFAULT_REGISTRATION_URL = "https://metaestetics.net/register";
1776
1852
  this.DEFAULT_SUBJECT = "You've Been Invited to Join as a Practitioner";
1777
- this.DEFAULT_FROM_ADDRESS = "MedClinic <no-reply@your-domain.com>";
1853
+ this.DEFAULT_FROM_ADDRESS = "MedClinic <no-reply@mg.metaestetics.net>";
1778
1854
  }
1779
1855
  /**
1780
1856
  * Sends a practitioner invitation email
@@ -1784,7 +1860,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1784
1860
  async sendInvitationEmail(data) {
1785
1861
  var _a, _b, _c, _d;
1786
1862
  try {
1787
- console.log(
1863
+ Logger.info(
1788
1864
  "[PractitionerInviteMailingService] Sending invitation email to",
1789
1865
  data.token.email
1790
1866
  );
@@ -1811,7 +1887,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1811
1887
  contactEmail,
1812
1888
  currentYear
1813
1889
  };
1814
- console.log("[PractitionerInviteMailingService] Template variables:", {
1890
+ Logger.info("[PractitionerInviteMailingService] Template variables:", {
1815
1891
  clinicName: templateVariables.clinicName,
1816
1892
  practitionerName: templateVariables.practitionerName,
1817
1893
  expirationDate: templateVariables.expirationDate,
@@ -1831,7 +1907,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1831
1907
  subject,
1832
1908
  html
1833
1909
  };
1834
- console.log(
1910
+ Logger.info(
1835
1911
  "[PractitionerInviteMailingService] Sending email with data:",
1836
1912
  {
1837
1913
  to: emailData.to,
@@ -1851,10 +1927,12 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1851
1927
  );
1852
1928
  return result;
1853
1929
  } catch (error) {
1854
- console.error(
1930
+ Logger.error(
1855
1931
  "[PractitionerInviteMailingService] Error sending invitation email:",
1856
- error instanceof Error ? error.message : error,
1857
- error instanceof Error ? error.stack : ""
1932
+ {
1933
+ error: error instanceof Error ? error.message : error,
1934
+ stack: error instanceof Error ? error.stack : void 0
1935
+ }
1858
1936
  );
1859
1937
  await this.logEmailAttempt(
1860
1938
  {
@@ -1878,7 +1956,7 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1878
1956
  */
1879
1957
  async handleTokenCreationEvent(tokenData, fromAddress) {
1880
1958
  try {
1881
- console.log(
1959
+ Logger.info(
1882
1960
  "[PractitionerInviteMailingService] Handling token creation event for token:",
1883
1961
  tokenData.id
1884
1962
  );
@@ -1898,7 +1976,18 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1898
1976
  if (!tokenData.expiresAt) {
1899
1977
  throw new Error(`Token ${tokenData.id} is missing expiration date`);
1900
1978
  }
1901
- console.log(
1979
+ if (!tokenData.status) {
1980
+ throw new Error(`Token ${tokenData.id} has no status defined`);
1981
+ }
1982
+ Logger.info(
1983
+ `[PractitionerInviteMailingService] Token status validation:`,
1984
+ {
1985
+ tokenId: tokenData.id,
1986
+ status: tokenData.status,
1987
+ statusType: typeof tokenData.status
1988
+ }
1989
+ );
1990
+ Logger.info(
1902
1991
  `[PractitionerInviteMailingService] Fetching practitioner data: ${tokenData.practitionerId}`
1903
1992
  );
1904
1993
  const practitionerRef = this.db.collection(PRACTITIONERS_COLLECTION).doc(tokenData.practitionerId);
@@ -1912,10 +2001,10 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1912
2001
  `Practitioner ${tokenData.practitionerId} has invalid data structure`
1913
2002
  );
1914
2003
  }
1915
- console.log(
2004
+ Logger.info(
1916
2005
  `[PractitionerInviteMailingService] Practitioner found: ${practitionerData.basicInfo.firstName} ${practitionerData.basicInfo.lastName}`
1917
2006
  );
1918
- console.log(
2007
+ Logger.info(
1919
2008
  `[PractitionerInviteMailingService] Fetching clinic data: ${tokenData.clinicId}`
1920
2009
  );
1921
2010
  const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(tokenData.clinicId);
@@ -1929,11 +2018,11 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1929
2018
  `Clinic ${tokenData.clinicId} has invalid data structure`
1930
2019
  );
1931
2020
  }
1932
- console.log(
2021
+ Logger.info(
1933
2022
  `[PractitionerInviteMailingService] Clinic found: ${clinicData.name}`
1934
2023
  );
1935
2024
  if (!fromAddress) {
1936
- console.warn(
2025
+ Logger.warn(
1937
2026
  "[PractitionerInviteMailingService] No fromAddress provided, using default"
1938
2027
  );
1939
2028
  fromAddress = this.DEFAULT_FROM_ADDRESS;
@@ -1961,18 +2050,20 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
1961
2050
  fromAddress
1962
2051
  }
1963
2052
  };
1964
- console.log(
2053
+ Logger.info(
1965
2054
  "[PractitionerInviteMailingService] Email data prepared, sending invitation"
1966
2055
  );
1967
2056
  await this.sendInvitationEmail(emailData);
1968
- console.log(
2057
+ Logger.info(
1969
2058
  "[PractitionerInviteMailingService] Invitation email sent successfully"
1970
2059
  );
1971
2060
  } catch (error) {
1972
- console.error(
2061
+ Logger.error(
1973
2062
  "[PractitionerInviteMailingService] Error handling token creation event:",
1974
- error instanceof Error ? error.message : error,
1975
- error instanceof Error ? error.stack : ""
2063
+ {
2064
+ error: error instanceof Error ? error.message : error,
2065
+ stack: error instanceof Error ? error.stack : void 0
2066
+ }
1976
2067
  );
1977
2068
  throw error;
1978
2069
  }
@@ -2582,6 +2673,7 @@ export {
2582
2673
  PatientAggregationService,
2583
2674
  PractitionerAggregationService,
2584
2675
  PractitionerInviteMailingService,
2676
+ PractitionerTokenStatus,
2585
2677
  ProcedureAggregationService,
2586
2678
  UserRole
2587
2679
  };
package/dist/index.d.mts CHANGED
@@ -1530,6 +1530,10 @@ interface PractitionerToken {
1530
1530
  expiresAt: Timestamp;
1531
1531
  usedBy?: string;
1532
1532
  usedAt?: Timestamp;
1533
+ emailSent?: boolean;
1534
+ emailSentAt?: Timestamp;
1535
+ emailError?: string;
1536
+ emailErrorAt?: Timestamp;
1533
1537
  }
1534
1538
  /**
1535
1539
  * Tip za kreiranje tokena za zdravstvenog radnika
package/dist/index.d.ts CHANGED
@@ -1530,6 +1530,10 @@ interface PractitionerToken {
1530
1530
  expiresAt: Timestamp;
1531
1531
  usedBy?: string;
1532
1532
  usedAt?: Timestamp;
1533
+ emailSent?: boolean;
1534
+ emailSentAt?: Timestamp;
1535
+ emailError?: string;
1536
+ emailErrorAt?: Timestamp;
1533
1537
  }
1534
1538
  /**
1535
1539
  * Tip za kreiranje tokena za zdravstvenog radnika
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.5.45",
4
+ "version": "1.5.47",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",
@@ -100,6 +100,9 @@
100
100
  "geofire-common": "^6.0.0",
101
101
  "zod": "^3.24.1"
102
102
  },
103
+ "optionalDependencies": {
104
+ "firebase-functions": "^6.2.0"
105
+ },
103
106
  "jest": {
104
107
  "preset": "ts-jest",
105
108
  "testEnvironment": "node",
@@ -43,11 +43,7 @@ export type {
43
43
  // Re-export types needed by cloud functions
44
44
  export type { Clinic, ClinicLocation } from "../types/clinic";
45
45
  export type { ClinicInfo } from "../types/profile";
46
- export type {
47
- Practitioner,
48
- PractitionerToken,
49
- PractitionerTokenStatus,
50
- } from "../types/practitioner";
46
+ export type { Practitioner, PractitionerToken } from "../types/practitioner";
51
47
  export type { DoctorInfo } from "../types/clinic";
52
48
  export type { Procedure, ProcedureSummaryInfo } from "../types/procedure";
53
49
  export type { PatientProfile as Patient } from "../types/patient";
@@ -59,6 +55,7 @@ export {
59
55
  NOTIFICATIONS_COLLECTION,
60
56
  } from "../types/notifications";
61
57
  export { UserRole } from "../types";
58
+ export { PractitionerTokenStatus } from "../types/practitioner";
62
59
 
63
60
  // Export admin classes/services explicitly by name
64
61
  export {
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Cloud Functions-compatible logger with fallback for other environments
3
+ *
4
+ * This logger automatically detects if it's running in a Cloud Functions environment
5
+ * and uses the appropriate logging method. It falls back to console methods in other environments.
6
+ */
7
+
8
+ // Try to import Firebase Functions logger, but don't cause errors if it's not available
9
+ let firebaseFunctionsLogger: any;
10
+ try {
11
+ // Use dynamic import to avoid requiring firebase-functions in non-Functions environments
12
+ firebaseFunctionsLogger = require("firebase-functions/logger");
13
+ // Import the compatibility module for console.log support if available
14
+ require("firebase-functions/logger/compat");
15
+ } catch (e) {
16
+ // Firebase Functions logger not available, will use fallback
17
+ }
18
+
19
+ /**
20
+ * Logger class that uses Firebase Functions logger when available
21
+ * with fallback to console methods when not in a Cloud Functions environment
22
+ */
23
+ export class Logger {
24
+ /**
25
+ * Log an error message
26
+ * @param message Message to log
27
+ * @param data Optional data to include
28
+ */
29
+ static error(message: string, data?: any): void {
30
+ if (firebaseFunctionsLogger) {
31
+ firebaseFunctionsLogger.error(message, data);
32
+ } else {
33
+ console.error(message, data !== undefined ? data : "");
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Log a warning message
39
+ * @param message Message to log
40
+ * @param data Optional data to include
41
+ */
42
+ static warn(message: string, data?: any): void {
43
+ if (firebaseFunctionsLogger) {
44
+ firebaseFunctionsLogger.warn(message, data);
45
+ } else {
46
+ console.warn(message, data !== undefined ? data : "");
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Log an info message
52
+ * @param message Message to log
53
+ * @param data Optional data to include
54
+ */
55
+ static info(message: string, data?: any): void {
56
+ if (firebaseFunctionsLogger) {
57
+ firebaseFunctionsLogger.info(message, data);
58
+ } else {
59
+ console.info(message, data !== undefined ? data : "");
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Log a debug message
65
+ * @param message Message to log
66
+ * @param data Optional data to include
67
+ */
68
+ static debug(message: string, data?: any): void {
69
+ if (firebaseFunctionsLogger) {
70
+ firebaseFunctionsLogger.debug(message, data);
71
+ } else {
72
+ console.debug(message, data !== undefined ? data : "");
73
+ }
74
+ }
75
+ }
76
+
77
+ // Default export for easier importing
78
+ export default Logger;
@@ -1,11 +1,6 @@
1
1
  import * as mailgun from "mailgun-js";
2
2
  import * as admin from "firebase-admin";
3
- // Configuration is no longer read here
4
- // import {
5
- // getMailgunConfig,
6
- // createMailgunClient,
7
- // MailgunConfig,
8
- // } from "./mailgun.config";
3
+ import { Logger } from "../logger";
9
4
 
10
5
  /**
11
6
  * Base mailing service class that provides common functionality for all mailing services
@@ -14,7 +9,11 @@ export class BaseMailingService {
14
9
  protected db: FirebaseFirestore.Firestore;
15
10
  protected mailgunClient: mailgun.Mailgun;
16
11
  // Removed config property as it's no longer managed here
17
- // protected config: MailgunConfig;
12
+ // import {
13
+ // getMailgunConfig,
14
+ // createMailgunClient,
15
+ // MailgunConfig,
16
+ // } from "./mailgun.config";
18
17
 
19
18
  /**
20
19
  * Constructor for BaseMailingService
@@ -32,17 +31,17 @@ export class BaseMailingService {
32
31
 
33
32
  // Validate instances
34
33
  if (!this.db) {
35
- console.error("[BaseMailingService] No Firestore instance provided");
34
+ Logger.error("[BaseMailingService] No Firestore instance provided");
36
35
  throw new Error("Firestore instance is required");
37
36
  }
38
37
 
39
38
  if (!this.mailgunClient) {
40
- console.error("[BaseMailingService] No Mailgun client provided");
39
+ Logger.error("[BaseMailingService] No Mailgun client provided");
41
40
  throw new Error("Mailgun client is required");
42
41
  }
43
42
 
44
43
  // Log successful initialization
45
- console.log("[BaseMailingService] Service initialized successfully");
44
+ Logger.info("[BaseMailingService] Service initialized successfully");
46
45
  }
47
46
 
48
47
  /**
@@ -79,7 +78,7 @@ export class BaseMailingService {
79
78
  throw new Error("Email must have either 'html' or 'text' content");
80
79
  }
81
80
 
82
- console.log("[BaseMailingService] Sending email via Mailgun", {
81
+ Logger.info("[BaseMailingService] Sending email via Mailgun", {
83
82
  to: data.to,
84
83
  from: data.from,
85
84
  subject: data.subject,
@@ -98,14 +97,13 @@ export class BaseMailingService {
98
97
 
99
98
  messagesApi.send(data, (error, body) => {
100
99
  if (error) {
101
- console.error(
102
- "[BaseMailingService] Mailgun API error:",
103
- error instanceof Error ? error.message : error,
104
- error instanceof Error ? error.stack : ""
105
- );
100
+ Logger.error("[BaseMailingService] Mailgun API error:", {
101
+ error: error instanceof Error ? error.message : error,
102
+ stack: error instanceof Error ? error.stack : undefined,
103
+ });
106
104
  reject(error);
107
105
  } else {
108
- console.log(
106
+ Logger.info(
109
107
  "[BaseMailingService] Email sent successfully:",
110
108
  body
111
109
  );
@@ -113,21 +111,23 @@ export class BaseMailingService {
113
111
  }
114
112
  });
115
113
  } catch (sendError) {
116
- console.error(
114
+ Logger.error(
117
115
  "[BaseMailingService] Error in mailgun.messages().send():",
118
- sendError instanceof Error ? sendError.message : sendError,
119
- sendError instanceof Error ? sendError.stack : ""
116
+ {
117
+ error:
118
+ sendError instanceof Error ? sendError.message : sendError,
119
+ stack: sendError instanceof Error ? sendError.stack : undefined,
120
+ }
120
121
  );
121
122
  reject(sendError);
122
123
  }
123
124
  }
124
125
  );
125
126
  } catch (error) {
126
- console.error(
127
- "[BaseMailingService] Error in sendEmail:",
128
- error instanceof Error ? error.message : error,
129
- error instanceof Error ? error.stack : ""
130
- );
127
+ Logger.error("[BaseMailingService] Error in sendEmail:", {
128
+ error: error instanceof Error ? error.message : error,
129
+ stack: error instanceof Error ? error.stack : undefined,
130
+ });
131
131
  throw error;
132
132
  }
133
133
  }
@@ -158,15 +158,14 @@ export class BaseMailingService {
158
158
  sentAt: admin.firestore.FieldValue.serverTimestamp(),
159
159
  });
160
160
 
161
- console.log(
161
+ Logger.info(
162
162
  `[BaseMailingService] Email log recorded. Success: ${success}`
163
163
  );
164
164
  } catch (logError) {
165
- console.error(
166
- "[BaseMailingService] Error logging email attempt:",
167
- logError instanceof Error ? logError.message : logError,
168
- logError instanceof Error ? logError.stack : ""
169
- );
165
+ Logger.error("[BaseMailingService] Error logging email attempt:", {
166
+ error: logError instanceof Error ? logError.message : logError,
167
+ stack: logError instanceof Error ? logError.stack : undefined,
168
+ });
170
169
  // Don't throw here to prevent disrupting the main flow
171
170
  }
172
171
  }
@@ -196,10 +195,9 @@ export class BaseMailingService {
196
195
 
197
196
  return rendered;
198
197
  } catch (renderError) {
199
- console.error(
200
- "[BaseMailingService] Error rendering template:",
201
- renderError instanceof Error ? renderError.message : renderError
202
- );
198
+ Logger.error("[BaseMailingService] Error rendering template:", {
199
+ error: renderError instanceof Error ? renderError.message : renderError,
200
+ });
203
201
  throw new Error(
204
202
  `Template rendering failed: ${
205
203
  renderError instanceof Error ? renderError.message : "Unknown error"
@@ -2,7 +2,7 @@ import * as admin from "firebase-admin";
2
2
  import * as mailgun from "mailgun-js";
3
3
  import { BaseMailingService } from "../base.mailing.service";
4
4
  import { practitionerInvitationTemplate } from "./templates/invitation.template";
5
-
5
+ import { Logger } from "../../logger";
6
6
  // Import specific types and collection constants
7
7
  import {
8
8
  Practitioner,
@@ -51,11 +51,11 @@ export interface PractitionerInviteEmailData {
51
51
  */
52
52
  export class PractitionerInviteMailingService extends BaseMailingService {
53
53
  private readonly DEFAULT_REGISTRATION_URL =
54
- "https://app.medclinic.com/register";
54
+ "https://metaestetics.net/register";
55
55
  private readonly DEFAULT_SUBJECT =
56
56
  "You've Been Invited to Join as a Practitioner";
57
57
  private readonly DEFAULT_FROM_ADDRESS =
58
- "MedClinic <no-reply@your-domain.com>";
58
+ "MedClinic <no-reply@mg.metaestetics.net>";
59
59
 
60
60
  /**
61
61
  * Constructor for PractitionerInviteMailingService
@@ -78,7 +78,7 @@ export class PractitionerInviteMailingService extends BaseMailingService {
78
78
  data: PractitionerInviteEmailData
79
79
  ): Promise<mailgun.messages.SendResponse> {
80
80
  try {
81
- console.log(
81
+ Logger.info(
82
82
  "[PractitionerInviteMailingService] Sending invitation email to",
83
83
  data.token.email
84
84
  );
@@ -127,7 +127,7 @@ export class PractitionerInviteMailingService extends BaseMailingService {
127
127
  };
128
128
 
129
129
  // Debug log for template variables (excluding token for security)
130
- console.log("[PractitionerInviteMailingService] Template variables:", {
130
+ Logger.info("[PractitionerInviteMailingService] Template variables:", {
131
131
  clinicName: templateVariables.clinicName,
132
132
  practitionerName: templateVariables.practitionerName,
133
133
  expirationDate: templateVariables.expirationDate,
@@ -152,7 +152,7 @@ export class PractitionerInviteMailingService extends BaseMailingService {
152
152
  html,
153
153
  };
154
154
 
155
- console.log(
155
+ Logger.info(
156
156
  "[PractitionerInviteMailingService] Sending email with data:",
157
157
  {
158
158
  to: emailData.to,
@@ -176,10 +176,12 @@ export class PractitionerInviteMailingService extends BaseMailingService {
176
176
 
177
177
  return result;
178
178
  } catch (error) {
179
- console.error(
179
+ Logger.error(
180
180
  "[PractitionerInviteMailingService] Error sending invitation email:",
181
- error instanceof Error ? error.message : error,
182
- error instanceof Error ? error.stack : ""
181
+ {
182
+ error: error instanceof Error ? error.message : error,
183
+ stack: error instanceof Error ? error.stack : undefined,
184
+ }
183
185
  );
184
186
 
185
187
  // Log failure
@@ -210,7 +212,7 @@ export class PractitionerInviteMailingService extends BaseMailingService {
210
212
  fromAddress: string
211
213
  ): Promise<void> {
212
214
  try {
213
- console.log(
215
+ Logger.info(
214
216
  "[PractitionerInviteMailingService] Handling token creation event for token:",
215
217
  tokenData.id
216
218
  );
@@ -236,8 +238,23 @@ export class PractitionerInviteMailingService extends BaseMailingService {
236
238
  throw new Error(`Token ${tokenData.id} is missing expiration date`);
237
239
  }
238
240
 
241
+ // Validate token status (handle both enum and string values)
242
+ if (!tokenData.status) {
243
+ throw new Error(`Token ${tokenData.id} has no status defined`);
244
+ }
245
+
246
+ // Log token status to help with debugging
247
+ Logger.info(
248
+ `[PractitionerInviteMailingService] Token status validation:`,
249
+ {
250
+ tokenId: tokenData.id,
251
+ status: tokenData.status,
252
+ statusType: typeof tokenData.status,
253
+ }
254
+ );
255
+
239
256
  // Get practitioner data using constant and type
240
- console.log(
257
+ Logger.info(
241
258
  `[PractitionerInviteMailingService] Fetching practitioner data: ${tokenData.practitionerId}`
242
259
  );
243
260
  const practitionerRef = this.db
@@ -256,12 +273,12 @@ export class PractitionerInviteMailingService extends BaseMailingService {
256
273
  );
257
274
  }
258
275
 
259
- console.log(
276
+ Logger.info(
260
277
  `[PractitionerInviteMailingService] Practitioner found: ${practitionerData.basicInfo.firstName} ${practitionerData.basicInfo.lastName}`
261
278
  );
262
279
 
263
280
  // Get clinic data using constant and type
264
- console.log(
281
+ Logger.info(
265
282
  `[PractitionerInviteMailingService] Fetching clinic data: ${tokenData.clinicId}`
266
283
  );
267
284
  const clinicRef = this.db
@@ -280,7 +297,7 @@ export class PractitionerInviteMailingService extends BaseMailingService {
280
297
  );
281
298
  }
282
299
 
283
- console.log(
300
+ Logger.info(
284
301
  `[PractitionerInviteMailingService] Clinic found: ${clinicData.name}`
285
302
  );
286
303
 
@@ -289,7 +306,7 @@ export class PractitionerInviteMailingService extends BaseMailingService {
289
306
 
290
307
  // Validate fromAddress
291
308
  if (!fromAddress) {
292
- console.warn(
309
+ Logger.warn(
293
310
  "[PractitionerInviteMailingService] No fromAddress provided, using default"
294
311
  );
295
312
  fromAddress = this.DEFAULT_FROM_ADDRESS;
@@ -320,21 +337,23 @@ export class PractitionerInviteMailingService extends BaseMailingService {
320
337
  },
321
338
  };
322
339
 
323
- console.log(
340
+ Logger.info(
324
341
  "[PractitionerInviteMailingService] Email data prepared, sending invitation"
325
342
  );
326
343
 
327
344
  // Send the invitation email
328
345
  await this.sendInvitationEmail(emailData);
329
346
 
330
- console.log(
347
+ Logger.info(
331
348
  "[PractitionerInviteMailingService] Invitation email sent successfully"
332
349
  );
333
350
  } catch (error) {
334
- console.error(
351
+ Logger.error(
335
352
  "[PractitionerInviteMailingService] Error handling token creation event:",
336
- error instanceof Error ? error.message : error,
337
- error instanceof Error ? error.stack : ""
353
+ {
354
+ error: error instanceof Error ? error.message : error,
355
+ stack: error instanceof Error ? error.stack : undefined,
356
+ }
338
357
  );
339
358
  throw error;
340
359
  }
@@ -183,6 +183,11 @@ export interface PractitionerToken {
183
183
  expiresAt: Timestamp;
184
184
  usedBy?: string;
185
185
  usedAt?: Timestamp;
186
+ // Email tracking fields added by Cloud Function
187
+ emailSent?: boolean;
188
+ emailSentAt?: Timestamp;
189
+ emailError?: string;
190
+ emailErrorAt?: Timestamp;
186
191
  }
187
192
 
188
193
  /**