@infuro/cms-core 1.0.64 → 1.0.66

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.
Files changed (32) hide show
  1. package/dist/admin.cjs +4 -4
  2. package/dist/admin.js +4 -4
  3. package/dist/api.cjs +36 -36
  4. package/dist/api.js +4 -4
  5. package/dist/{chunk-M25DGZ5J.cjs → chunk-5MZFQRDW.cjs} +242 -45
  6. package/dist/chunk-FLUF2GZH.js +71 -0
  7. package/dist/{chunk-OJAYCNE5.js → chunk-NV5IRHI3.js} +240 -43
  8. package/dist/chunk-PA6YDMFZ.cjs +78 -0
  9. package/dist/{chunk-FF45VZMM.cjs → chunk-QYRXLURF.cjs} +109 -67
  10. package/dist/{chunk-DXERXWBR.js → chunk-RCE5SJBA.js} +36 -20
  11. package/dist/{chunk-K6C3ZSBZ.js → chunk-T33KU5G5.js} +81 -39
  12. package/dist/chunk-THL5JDWJ.cjs +101 -0
  13. package/dist/{chunk-PX3BSCIG.cjs → chunk-WMMZZRDJ.cjs} +38 -22
  14. package/dist/chunk-XJNNOSJR.js +98 -0
  15. package/dist/{emit-order-notification-trigger-MFCBAE7L.js → emit-order-notification-trigger-EJJZ6XTS.js} +2 -2
  16. package/dist/{emit-order-notification-trigger-ZRRGCQGB.cjs → emit-order-notification-trigger-ZD5YN3JM.cjs} +4 -4
  17. package/dist/index.cjs +224 -224
  18. package/dist/index.d.cts +8 -3
  19. package/dist/index.d.ts +8 -3
  20. package/dist/index.js +8 -8
  21. package/dist/{order-completion-otp-handlers-3W5I3LON.js → order-completion-otp-handlers-LFRHXWK4.js} +2 -2
  22. package/dist/{order-completion-otp-handlers-RF3DLNV7.cjs → order-completion-otp-handlers-NK65LOLV.cjs} +3 -3
  23. package/dist/{order-notification-dispatcher-ID2PDEXD.js → order-notification-dispatcher-ECPFI7CD.js} +2 -2
  24. package/dist/{order-notification-dispatcher-RNEQB3V7.cjs → order-notification-dispatcher-LL7ETKLU.cjs} +7 -7
  25. package/dist/{pg-boss-service-L6MTF4EQ.cjs → pg-boss-service-BDGOKM2T.cjs} +3 -3
  26. package/dist/pg-boss-service-WCBJD4JB.js +2 -0
  27. package/package.json +1 -1
  28. package/dist/chunk-AYWDQFJZ.js +0 -27
  29. package/dist/chunk-GO7PPYNU.js +0 -76
  30. package/dist/chunk-UEE4PTTB.cjs +0 -30
  31. package/dist/chunk-XQ3QUHWR.cjs +0 -83
  32. package/dist/pg-boss-service-4XF2TQ2E.js +0 -2
@@ -1,5 +1,5 @@
1
1
  import { queueWhatsApp } from './chunk-GWDI752Q.js';
2
- import { notificationTriggerEmitter } from './chunk-AYWDQFJZ.js';
2
+ import { notifyLog, logFcmToken, maskNotifyEmail, maskNotifyPhone, notificationTriggerEmitter } from './chunk-FLUF2GZH.js';
3
3
  import { sesRegionSupportsSmtp, sesSmtpHost, EmailService, renderLayout } from './chunk-6YOQ7G5O.js';
4
4
  import { queueEmail } from './chunk-TU23GJPJ.js';
5
5
  import { mergeEmailLayoutCompanyDetails } from './chunk-YRCKEGL2.js';
@@ -217,7 +217,8 @@ async function loadOrderNotificationContexts(orderId, deps) {
217
217
  const contact = {
218
218
  name: metaBuyerName || rawContact.name,
219
219
  email: metaBuyerEmail || metaCheckoutEmail || rawContact.email,
220
- phone: rawContact.phone
220
+ phone: rawContact.phone,
221
+ userId: rawContact.userId ?? null
221
222
  };
222
223
  const currency = String(o.currency ?? "INR");
223
224
  const siteUrl = resolvePublicSiteUrl();
@@ -1400,12 +1401,6 @@ var ORDER_NOTIFICATION_DEFAULTS = {
1400
1401
 
1401
1402
  // src/lib/order-notification-dispatcher.ts
1402
1403
  var initialized = false;
1403
- function maskPhone2(raw) {
1404
- const digits = String(raw ?? "").replace(/\D/g, "");
1405
- if (digits.length <= 4) return "(none)";
1406
- return `***${digits.slice(-4)}`;
1407
- }
1408
- __name(maskPhone2, "maskPhone");
1409
1404
  async function getSettingsGroup(dataSource, entityMap, group) {
1410
1405
  if (!entityMap.configs) return {};
1411
1406
  const rows = await dataSource.getRepository(entityMap.configs).find({
@@ -1508,7 +1503,17 @@ async function loadBoundTemplate(triggerKey, channel, audienceType = "customers"
1508
1503
  enabled: true
1509
1504
  }
1510
1505
  }).catch(() => null);
1511
- if (!template) {
1506
+ let resolvedTemplate = template;
1507
+ if (!resolvedTemplate && (channel === "mobile" || channel === "push")) {
1508
+ resolvedTemplate = await dataSource.getRepository(entityMap.message_templates).findOne({
1509
+ where: {
1510
+ id: templateId,
1511
+ deleted: false,
1512
+ enabled: true
1513
+ }
1514
+ }).catch(() => null);
1515
+ }
1516
+ if (!resolvedTemplate) {
1512
1517
  const defChannel = ORDER_NOTIFICATION_DEFAULTS[channel];
1513
1518
  const def = defChannel ? defChannel[triggerKey] : null;
1514
1519
  if (def) {
@@ -1533,7 +1538,7 @@ async function loadBoundTemplate(triggerKey, channel, audienceType = "customers"
1533
1538
  });
1534
1539
  return null;
1535
1540
  }
1536
- return template;
1541
+ return resolvedTemplate;
1537
1542
  } catch (err) {
1538
1543
  const defChannel = ORDER_NOTIFICATION_DEFAULTS[channel];
1539
1544
  const def = defChannel ? defChannel[triggerKey] : null;
@@ -1615,11 +1620,26 @@ async function sendPushNotificationForTrigger(triggerKey, orderId, audienceType,
1615
1620
  if (!template) {
1616
1621
  template = await loadBoundTemplate(triggerKey, "push", audienceType, dataSource, entityMap);
1617
1622
  }
1618
- if (!template || !template.body) return;
1623
+ if (!template || !template.body) {
1624
+ notifyLog.skip("PUSH", "no mobile/push template or empty body", {
1625
+ triggerKey,
1626
+ orderId,
1627
+ audienceType,
1628
+ targetId
1629
+ });
1630
+ return;
1631
+ }
1619
1632
  const rawTitle = template.subject?.trim() || "Order Notification";
1620
1633
  const title = applyTemplateVars(rawTitle, variables);
1621
1634
  const body = applyTemplateVars(template.body, variables);
1622
- if (!entityMap.user_device_tokens) return;
1635
+ if (!entityMap.user_device_tokens) {
1636
+ notifyLog.skip("PUSH", "user_device_tokens entity not registered", {
1637
+ triggerKey,
1638
+ orderId,
1639
+ audienceType
1640
+ });
1641
+ return;
1642
+ }
1623
1643
  const tokenRepo = dataSource.getRepository(entityMap.user_device_tokens);
1624
1644
  let targetTokens = [];
1625
1645
  try {
@@ -1654,19 +1674,67 @@ async function sendPushNotificationForTrigger(triggerKey, orderId, audienceType,
1654
1674
  });
1655
1675
  }
1656
1676
  } catch (err) {
1657
- console.error("[order-notifications] Error querying device tokens for push", err);
1677
+ notifyLog.error("PUSH", "device token query failed", {
1678
+ triggerKey,
1679
+ orderId,
1680
+ audienceType,
1681
+ targetId,
1682
+ error: err instanceof Error ? err.message : String(err)
1683
+ });
1658
1684
  return;
1659
1685
  }
1660
- for (const t of targetTokens) {
1661
- if (t.token?.trim()) {
1662
- await sendFcmPushNotification(dataSource, entityMap, {
1663
- token: t.token.trim(),
1664
- title,
1665
- body,
1666
- data: {
1667
- orderId: String(orderId),
1668
- triggerKey
1669
- }
1686
+ const tokens = targetTokens.map((t) => t.token?.trim()).filter(Boolean);
1687
+ notifyLog.push("sending", {
1688
+ triggerKey,
1689
+ orderId,
1690
+ audienceType,
1691
+ targetId,
1692
+ title,
1693
+ tokenCount: tokens.length,
1694
+ fcmTokens: tokens.map((t) => logFcmToken(t))
1695
+ });
1696
+ if (tokens.length === 0) {
1697
+ notifyLog.skip("PUSH", "no active FCM tokens for target", {
1698
+ triggerKey,
1699
+ orderId,
1700
+ audienceType,
1701
+ targetId,
1702
+ hint: "App must POST /api/user-device-tokens after login"
1703
+ });
1704
+ return;
1705
+ }
1706
+ for (const token of tokens) {
1707
+ notifyLog.push("FCM target", {
1708
+ triggerKey,
1709
+ orderId,
1710
+ audienceType,
1711
+ targetId,
1712
+ fcmToken: logFcmToken(token)
1713
+ });
1714
+ const res = await sendFcmPushNotification(dataSource, entityMap, {
1715
+ token,
1716
+ title,
1717
+ body,
1718
+ data: {
1719
+ orderId: String(orderId),
1720
+ triggerKey
1721
+ }
1722
+ });
1723
+ if (res.success) {
1724
+ notifyLog.push("FCM sent", {
1725
+ triggerKey,
1726
+ orderId,
1727
+ audienceType,
1728
+ fcmToken: logFcmToken(token),
1729
+ messageId: res.messageId ?? null
1730
+ });
1731
+ } else {
1732
+ notifyLog.error("PUSH", "FCM send failed", {
1733
+ triggerKey,
1734
+ orderId,
1735
+ audienceType,
1736
+ fcmToken: logFcmToken(token),
1737
+ error: res.error ?? "unknown"
1670
1738
  });
1671
1739
  }
1672
1740
  }
@@ -1810,7 +1878,15 @@ function formatBodyForEmailHtml(body) {
1810
1878
  __name(formatBodyForEmailHtml, "formatBodyForEmailHtml");
1811
1879
  async function sendEmailForTrigger(triggerKey, orderId, audienceType, variables, contactEmail, dataSource, entityMap, getCms) {
1812
1880
  const template = await loadBoundTemplate(triggerKey, "email", audienceType, dataSource, entityMap);
1813
- if (!template) return;
1881
+ if (!template) {
1882
+ notifyLog.skip("EMAIL", "no bound/default email template", {
1883
+ triggerKey,
1884
+ orderId,
1885
+ audienceType,
1886
+ to: maskNotifyEmail(contactEmail)
1887
+ });
1888
+ return;
1889
+ }
1814
1890
  const [branding, emailSettings, storeSettings] = await Promise.all([
1815
1891
  getSettingsGroup(dataSource, entityMap, "branding"),
1816
1892
  getSettingsGroup(dataSource, entityMap, "email"),
@@ -1845,22 +1921,31 @@ async function sendEmailForTrigger(triggerKey, orderId, audienceType, variables,
1845
1921
  attachInvoice: true
1846
1922
  } : {}
1847
1923
  });
1848
- console.log("[order-notifications] email queued", {
1924
+ notifyLog.email("queued", {
1849
1925
  triggerKey,
1850
1926
  audienceType,
1851
1927
  orderId,
1852
- to: contactEmail,
1928
+ to: maskNotifyEmail(contactEmail),
1929
+ subject,
1853
1930
  attachInvoice: shouldAttachInvoice
1854
1931
  });
1855
1932
  }
1856
1933
  __name(sendEmailForTrigger, "sendEmailForTrigger");
1857
1934
  async function sendWhatsAppForTrigger(triggerKey, orderId, phone, variables, dataSource, entityMap, getCms) {
1858
1935
  const template = await loadBoundTemplate(triggerKey, "whatsapp", "customers", dataSource, entityMap);
1859
- if (!template) return;
1936
+ if (!template) {
1937
+ notifyLog.skip("WHATSAPP", "no bound/default WhatsApp template", {
1938
+ triggerKey,
1939
+ orderId,
1940
+ phone: maskNotifyPhone(phone)
1941
+ });
1942
+ return;
1943
+ }
1860
1944
  const paramOrder = template.providerMeta?.paramOrder ?? [];
1861
1945
  if (paramOrder.length === 0) {
1862
- console.warn("[order-notifications] WhatsApp template has no paramOrder set \u2014 variables may send blank/wrong", {
1863
- triggerKey
1946
+ notifyLog.skip("WHATSAPP", "template has no paramOrder \u2014 variables may send blank/wrong", {
1947
+ triggerKey,
1948
+ orderId
1864
1949
  });
1865
1950
  }
1866
1951
  const cms = await getCms();
@@ -1869,8 +1954,10 @@ async function sendWhatsAppForTrigger(triggerKey, orderId, phone, variables, dat
1869
1954
  name: template.name
1870
1955
  });
1871
1956
  if (!metaTemplateName) {
1872
- console.warn("[order-notifications] bound WhatsApp template has no Meta template name", {
1957
+ notifyLog.skip("WHATSAPP", "template has no Meta template name", {
1873
1958
  triggerKey,
1959
+ orderId,
1960
+ phone: maskNotifyPhone(phone),
1874
1961
  templateId: template.id
1875
1962
  });
1876
1963
  return;
@@ -1885,37 +1972,57 @@ async function sendWhatsAppForTrigger(triggerKey, orderId, phone, variables, dat
1885
1972
  templateParamOrder: paramOrder
1886
1973
  });
1887
1974
  if (!sent) {
1888
- console.warn("[order-notifications] WhatsApp send failed", {
1975
+ notifyLog.error("WHATSAPP", "send failed / not queued", {
1889
1976
  triggerKey,
1890
1977
  orderId,
1978
+ phone: maskNotifyPhone(phone),
1891
1979
  hint: "Register whatsappPlugin() + queuePlugin() in getCms(), or set WHATSAPP_ACCESS_TOKEN and WHATSAPP_PHONE_NUMBER_ID"
1892
1980
  });
1893
1981
  } else {
1894
- console.log("[order-notifications] WhatsApp queued/sent", {
1982
+ notifyLog.whatsapp("queued/sent", {
1895
1983
  triggerKey,
1896
1984
  orderId,
1897
- phone: maskPhone2(phone)
1985
+ phone: maskNotifyPhone(phone),
1986
+ metaTemplateName
1898
1987
  });
1899
1988
  }
1900
1989
  }
1901
1990
  __name(sendWhatsAppForTrigger, "sendWhatsAppForTrigger");
1902
1991
  async function handleTrigger(triggerKey, payload, dataSource, entityMap, getCms) {
1903
- console.log("[order-notifications] received", {
1992
+ notifyLog.trigger("dispatcher received", {
1904
1993
  triggerKey,
1905
1994
  orderId: payload.orderId,
1906
- phone: maskPhone2(payload.customerPhone)
1995
+ orderNumber: payload.orderNumber,
1996
+ phone: maskNotifyPhone(payload.customerPhone),
1997
+ vendorId: payload.vendorId ?? null
1907
1998
  });
1908
1999
  const [emailChannelEnabled, whatsappChannelEnabled, pushChannelEnabled] = await Promise.all([
1909
2000
  isEmailNotificationsEnabled(dataSource, entityMap),
1910
2001
  isWhatsappNotificationsEnabled(dataSource, entityMap),
1911
2002
  isPushNotificationsEnabled(dataSource, entityMap)
1912
2003
  ]);
2004
+ notifyLog.trigger("channel switches", {
2005
+ triggerKey,
2006
+ orderId: payload.orderId,
2007
+ email: emailChannelEnabled,
2008
+ whatsapp: whatsappChannelEnabled,
2009
+ push: pushChannelEnabled
2010
+ });
1913
2011
  if (!emailChannelEnabled && !whatsappChannelEnabled && !pushChannelEnabled) {
1914
- console.warn("[order-notifications] skip: Email, WhatsApp, and Mobile Push notifications are disabled");
2012
+ notifyLog.skip("ALL", "Email, WhatsApp, and Mobile Push are disabled in event_notifications", {
2013
+ triggerKey,
2014
+ orderId: payload.orderId
2015
+ });
1915
2016
  return;
1916
2017
  }
1917
2018
  const triggerEnabled = await isTriggerCatalogEnabled(triggerKey, dataSource, entityMap);
1918
- if (!triggerEnabled) return;
2019
+ if (!triggerEnabled) {
2020
+ notifyLog.skip("TRIGGER", "trigger catalog disabled", {
2021
+ triggerKey,
2022
+ orderId: payload.orderId
2023
+ });
2024
+ return;
2025
+ }
1919
2026
  const context = await loadOrderNotificationContexts(payload.orderId, {
1920
2027
  dataSource,
1921
2028
  entityMap
@@ -1923,37 +2030,86 @@ async function handleTrigger(triggerKey, payload, dataSource, entityMap, getCms)
1923
2030
  const variables = mergeTriggerVariables(payload, context?.variables);
1924
2031
  const contactEmail = context?.contact.email?.trim() || "";
1925
2032
  const contactPhone = context?.contact.phone?.trim() || payload.customerPhone?.trim() || "";
2033
+ notifyLog.trigger("recipients resolved", {
2034
+ triggerKey,
2035
+ orderId: payload.orderId,
2036
+ contactEmail: maskNotifyEmail(contactEmail),
2037
+ contactPhone: maskNotifyPhone(contactPhone)
2038
+ });
1926
2039
  if (emailChannelEnabled) {
1927
2040
  const [customerEnabled, vendorEnabled, adminEnabled] = await Promise.all([
1928
2041
  isAudienceEmailEnabled(dataSource, entityMap, "customer"),
1929
2042
  isAudienceEmailEnabled(dataSource, entityMap, "vendor"),
1930
2043
  isAudienceEmailEnabled(dataSource, entityMap, "admin")
1931
2044
  ]);
2045
+ notifyLog.email("audience switches", {
2046
+ triggerKey,
2047
+ orderId: payload.orderId,
2048
+ customer: customerEnabled,
2049
+ vendor: vendorEnabled,
2050
+ admin: adminEnabled
2051
+ });
1932
2052
  if (triggerKey === "order_assigned_assignee") {
1933
2053
  const assigneeEmail = context?.order?.assignedUser?.email?.trim();
1934
2054
  if (assigneeEmail) {
1935
2055
  await sendEmailForTrigger(triggerKey, payload.orderId, "customers", variables, assigneeEmail, dataSource, entityMap, getCms);
2056
+ } else {
2057
+ notifyLog.skip("EMAIL", "order_assigned_assignee has no assignee email", {
2058
+ triggerKey,
2059
+ orderId: payload.orderId
2060
+ });
1936
2061
  }
1937
2062
  } else if (customerEnabled && contactEmail) {
1938
2063
  await sendEmailForTrigger(triggerKey, payload.orderId, "customers", variables, contactEmail, dataSource, entityMap, getCms);
2064
+ } else if (!customerEnabled) {
2065
+ notifyLog.skip("EMAIL", "customer email audience disabled", {
2066
+ triggerKey,
2067
+ orderId: payload.orderId
2068
+ });
2069
+ } else {
2070
+ notifyLog.skip("EMAIL", "no customer email on order contact", {
2071
+ triggerKey,
2072
+ orderId: payload.orderId
2073
+ });
1939
2074
  }
1940
2075
  if (vendorEnabled && triggerKey !== "order_assigned_assignee") {
1941
2076
  const multiVendorSettings = await getSettingsGroup(dataSource, entityMap, "multi_vendor");
1942
2077
  if (multiVendorSettings.enabled !== "false" && multiVendorSettings.enabled !== "0") {
1943
2078
  const vendorEmails = await getOrderVendorEmails(payload.orderId, payload.vendorId, dataSource, entityMap);
2079
+ if (vendorEmails.length === 0) {
2080
+ notifyLog.skip("EMAIL", "no vendor emails for order", {
2081
+ triggerKey,
2082
+ orderId: payload.orderId,
2083
+ vendorId: payload.vendorId ?? null
2084
+ });
2085
+ }
1944
2086
  for (const vEmail of vendorEmails) {
1945
2087
  await sendEmailForTrigger(triggerKey, payload.orderId, "vendors", variables, vEmail, dataSource, entityMap, getCms);
1946
2088
  }
2089
+ } else {
2090
+ notifyLog.skip("EMAIL", "multi-vendor off \u2014 skip vendor email", {
2091
+ triggerKey,
2092
+ orderId: payload.orderId
2093
+ });
1947
2094
  }
1948
2095
  }
1949
2096
  if (adminEnabled && triggerKey !== "order_assigned_assignee") {
1950
2097
  const adminEmails = await getAdminRecipientEmails(dataSource, entityMap);
2098
+ if (adminEmails.length === 0) {
2099
+ notifyLog.skip("EMAIL", "no admin recipient emails", {
2100
+ triggerKey,
2101
+ orderId: payload.orderId
2102
+ });
2103
+ }
1951
2104
  for (const aEmail of adminEmails) {
1952
2105
  await sendEmailForTrigger(triggerKey, payload.orderId, "admin", variables, aEmail, dataSource, entityMap, getCms);
1953
2106
  }
1954
2107
  }
1955
2108
  } else {
1956
- console.log("[order-notifications] skip email: Email notifications channel is disabled");
2109
+ notifyLog.skip("EMAIL", "email channel disabled", {
2110
+ triggerKey,
2111
+ orderId: payload.orderId
2112
+ });
1957
2113
  }
1958
2114
  if (pushChannelEnabled) {
1959
2115
  const [pushCustomerEnabled, pushVendorEnabled, pushAdminEnabled] = await Promise.all([
@@ -1961,29 +2117,59 @@ async function handleTrigger(triggerKey, payload, dataSource, entityMap, getCms)
1961
2117
  isAudiencePushEnabled(dataSource, entityMap, "vendor"),
1962
2118
  isAudiencePushEnabled(dataSource, entityMap, "admin")
1963
2119
  ]);
1964
- const targetCustomerId = triggerKey === "order_assigned_assignee" ? context?.order?.assignedUser?.id : context?.order?.customerContactId || context?.order?.contactId || context?.order?.userId || context?.order?.id;
2120
+ notifyLog.push("audience switches", {
2121
+ triggerKey,
2122
+ orderId: payload.orderId,
2123
+ customer: pushCustomerEnabled,
2124
+ vendor: pushVendorEnabled,
2125
+ admin: pushAdminEnabled
2126
+ });
2127
+ const targetCustomerId = triggerKey === "order_assigned_assignee" ? context?.order?.assignedUser?.id : context?.contact?.userId;
1965
2128
  if (pushCustomerEnabled && targetCustomerId) {
1966
2129
  await sendPushNotificationForTrigger(triggerKey, payload.orderId, "customers", String(targetCustomerId), variables, dataSource, entityMap);
2130
+ } else if (!pushCustomerEnabled) {
2131
+ notifyLog.skip("PUSH", "customer push audience disabled", {
2132
+ triggerKey,
2133
+ orderId: payload.orderId
2134
+ });
2135
+ } else {
2136
+ notifyLog.skip("PUSH", "no customer user/contact id for push", {
2137
+ triggerKey,
2138
+ orderId: payload.orderId
2139
+ });
1967
2140
  }
1968
2141
  if (pushVendorEnabled && payload.vendorId && triggerKey !== "order_assigned_assignee") {
1969
2142
  await sendPushNotificationForTrigger(triggerKey, payload.orderId, "vendors", String(payload.vendorId), variables, dataSource, entityMap);
2143
+ } else if (pushVendorEnabled && triggerKey !== "order_assigned_assignee" && !payload.vendorId) {
2144
+ notifyLog.skip("PUSH", "no vendorId on order \u2014 skip vendor push", {
2145
+ triggerKey,
2146
+ orderId: payload.orderId
2147
+ });
1970
2148
  }
1971
2149
  if (pushAdminEnabled && triggerKey !== "order_assigned_assignee") {
1972
2150
  await sendPushNotificationForTrigger(triggerKey, payload.orderId, "admin", "admin", variables, dataSource, entityMap);
1973
2151
  }
2152
+ } else {
2153
+ notifyLog.skip("PUSH", "push channel disabled", {
2154
+ triggerKey,
2155
+ orderId: payload.orderId
2156
+ });
1974
2157
  }
1975
2158
  if (whatsappChannelEnabled) {
1976
2159
  const targetPhone = triggerKey === "order_assigned_assignee" ? context?.order?.assignedUser?.phone?.trim() : contactPhone;
1977
2160
  if (targetPhone) {
1978
2161
  await sendWhatsAppForTrigger(triggerKey, payload.orderId, targetPhone, variables, dataSource, entityMap, getCms);
1979
2162
  } else {
1980
- console.warn("[order-notifications] skip WhatsApp: no recipient phone", {
2163
+ notifyLog.skip("WHATSAPP", "no recipient phone", {
1981
2164
  triggerKey,
1982
2165
  orderId: payload.orderId
1983
2166
  });
1984
2167
  }
1985
2168
  } else {
1986
- console.log("[order-notifications] skip WhatsApp: WhatsApp notifications channel is disabled");
2169
+ notifyLog.skip("WHATSAPP", "WhatsApp channel disabled", {
2170
+ triggerKey,
2171
+ orderId: payload.orderId
2172
+ });
1987
2173
  }
1988
2174
  }
1989
2175
  __name(handleTrigger, "handleTrigger");
@@ -1997,10 +2183,21 @@ function initWhatsappTriggerDispatcher(deps) {
1997
2183
  });
1998
2184
  notificationTriggerEmitter.onAnyTrigger((triggerKey, payload) => {
1999
2185
  void handleTrigger(triggerKey, payload, dataSource, entityMap, getCms).catch((err) => {
2000
- console.error("[order-notifications]", triggerKey, err);
2186
+ notifyLog.error("TRIGGER", "dispatcher handleTrigger failed", {
2187
+ triggerKey,
2188
+ orderId: payload.orderId,
2189
+ error: err instanceof Error ? err.message : String(err),
2190
+ stack: err instanceof Error ? err.stack : void 0
2191
+ });
2001
2192
  });
2002
2193
  });
2003
- console.log("[order-notifications] dispatcher initialized (email + WhatsApp, unified via order_notification_bindings)");
2194
+ notifyLog.trigger("dispatcher initialized", {
2195
+ channels: [
2196
+ "email",
2197
+ "whatsapp",
2198
+ "push"
2199
+ ]
2200
+ });
2004
2201
  }
2005
2202
  __name(initWhatsappTriggerDispatcher, "initWhatsappTriggerDispatcher");
2006
2203
  async function dispatchOrderNotificationDirectly(triggerKey, payload, dataSource, entityMap, getCms) {
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
4
+ var events = require('events');
5
+
6
+ var KNOWN_NOTIFICATION_TRIGGERS = {
7
+ ORDER_PENDING: "order_pending",
8
+ ORDER_PROCESSING: "order_processing",
9
+ ORDER_COMPLETED: "order_completed",
10
+ ORDER_PLACED: "order_placed",
11
+ ORDER_CANCELLED: "order_cancelled",
12
+ PAYMENT_SUCCESS: "payment_success",
13
+ PAYMENT_FAILED: "payment_failed",
14
+ PAYMENT_REFUND_INITIATED: "payment_refund_initiated"
15
+ };
16
+ var NotificationTriggerEmitter = class NotificationTriggerEmitter2 extends events.EventEmitter {
17
+ static {
18
+ chunkUSNT2KNT_cjs.__name(this, "NotificationTriggerEmitter");
19
+ }
20
+ emitTrigger(triggerKey, payload) {
21
+ this.emit("__any__", triggerKey, payload);
22
+ }
23
+ onAnyTrigger(listener) {
24
+ this.on("__any__", listener);
25
+ }
26
+ };
27
+ var notificationTriggerEmitter = new NotificationTriggerEmitter();
28
+
29
+ // src/lib/notify-log.ts
30
+ function maskNotifyPhone(raw) {
31
+ const digits = String(raw ?? "").replace(/\D/g, "");
32
+ if (digits.length <= 4) return "(none)";
33
+ return `***${digits.slice(-4)}`;
34
+ }
35
+ chunkUSNT2KNT_cjs.__name(maskNotifyPhone, "maskNotifyPhone");
36
+ function maskNotifyEmail(raw) {
37
+ const e = String(raw ?? "").trim();
38
+ if (!e || !e.includes("@")) return "(none)";
39
+ const [user, domain] = e.split("@");
40
+ const u = user.length <= 2 ? "**" : `${user.slice(0, 2)}***`;
41
+ return `${u}@${domain}`;
42
+ }
43
+ chunkUSNT2KNT_cjs.__name(maskNotifyEmail, "maskNotifyEmail");
44
+ function logFcmToken(raw) {
45
+ const s = String(raw ?? "").trim();
46
+ return s || "(none)";
47
+ }
48
+ chunkUSNT2KNT_cjs.__name(logFcmToken, "logFcmToken");
49
+ function write(level, channel, message, data) {
50
+ const banner = `========== [NOTIFY] ${channel} | ${message} ==========`;
51
+ const payload = data ?? {};
52
+ if (level === "error") {
53
+ console.error(`
54
+ ${banner}`, payload);
55
+ } else if (level === "warn") {
56
+ console.warn(`
57
+ ${banner}`, payload);
58
+ } else {
59
+ console.info(`
60
+ ${banner}`, payload);
61
+ }
62
+ }
63
+ chunkUSNT2KNT_cjs.__name(write, "write");
64
+ var notifyLog = {
65
+ trigger: /* @__PURE__ */ chunkUSNT2KNT_cjs.__name((message, data) => write("info", "TRIGGER", message, data), "trigger"),
66
+ email: /* @__PURE__ */ chunkUSNT2KNT_cjs.__name((message, data) => write("info", "EMAIL", message, data), "email"),
67
+ whatsapp: /* @__PURE__ */ chunkUSNT2KNT_cjs.__name((message, data) => write("info", "WHATSAPP", message, data), "whatsapp"),
68
+ push: /* @__PURE__ */ chunkUSNT2KNT_cjs.__name((message, data) => write("info", "PUSH", message, data), "push"),
69
+ skip: /* @__PURE__ */ chunkUSNT2KNT_cjs.__name((channel, message, data) => write("warn", `SKIP ${channel}`, message, data), "skip"),
70
+ error: /* @__PURE__ */ chunkUSNT2KNT_cjs.__name((channel, message, data) => write("error", channel, message, data), "error")
71
+ };
72
+
73
+ exports.KNOWN_NOTIFICATION_TRIGGERS = KNOWN_NOTIFICATION_TRIGGERS;
74
+ exports.logFcmToken = logFcmToken;
75
+ exports.maskNotifyEmail = maskNotifyEmail;
76
+ exports.maskNotifyPhone = maskNotifyPhone;
77
+ exports.notificationTriggerEmitter = notificationTriggerEmitter;
78
+ exports.notifyLog = notifyLog;