@infuro/cms-core 1.0.64 → 1.0.65

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 +1 -1
  2. package/dist/admin.js +1 -1
  3. package/dist/api.cjs +36 -36
  4. package/dist/api.js +4 -4
  5. package/dist/{chunk-OJAYCNE5.js → chunk-ACBN6UWZ.js} +218 -39
  6. package/dist/chunk-BXAKL2TF.cjs +84 -0
  7. package/dist/{chunk-M25DGZ5J.cjs → chunk-NIRYYJIJ.cjs} +220 -41
  8. package/dist/{chunk-DXERXWBR.js → chunk-RDEVZMO5.js} +36 -20
  9. package/dist/{chunk-K6C3ZSBZ.js → chunk-SANKKGB3.js} +28 -18
  10. package/dist/chunk-THL5JDWJ.cjs +101 -0
  11. package/dist/{chunk-PX3BSCIG.cjs → chunk-V6EYAC7X.cjs} +38 -22
  12. package/dist/chunk-XJNNOSJR.js +98 -0
  13. package/dist/chunk-YEAXE4U2.js +77 -0
  14. package/dist/{chunk-FF45VZMM.cjs → chunk-YHEITFHR.cjs} +56 -46
  15. package/dist/{emit-order-notification-trigger-ZRRGCQGB.cjs → emit-order-notification-trigger-DR74TQXN.cjs} +4 -4
  16. package/dist/{emit-order-notification-trigger-MFCBAE7L.js → emit-order-notification-trigger-UCKJHDQK.js} +2 -2
  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-CH22ZRAI.js} +2 -2
  22. package/dist/{order-completion-otp-handlers-RF3DLNV7.cjs → order-completion-otp-handlers-RW5RSXH3.cjs} +3 -3
  23. package/dist/{order-notification-dispatcher-ID2PDEXD.js → order-notification-dispatcher-3TXUAJ7L.js} +2 -2
  24. package/dist/{order-notification-dispatcher-RNEQB3V7.cjs → order-notification-dispatcher-Y7NZAALH.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
package/dist/admin.cjs CHANGED
@@ -895,7 +895,7 @@ var init_admin_config_context = __esm({
895
895
  var CMS_VERSION;
896
896
  var init_cms_version = __esm({
897
897
  "src/lib/cms-version.ts"() {
898
- CMS_VERSION = "1.0.64" ;
898
+ CMS_VERSION = "1.0.65" ;
899
899
  }
900
900
  });
901
901
  function useCatalogCategories(enabled = true) {
package/dist/admin.js CHANGED
@@ -861,7 +861,7 @@ var init_admin_config_context = __esm({
861
861
  var CMS_VERSION;
862
862
  var init_cms_version = __esm({
863
863
  "src/lib/cms-version.ts"() {
864
- CMS_VERSION = "1.0.64" ;
864
+ CMS_VERSION = "1.0.65" ;
865
865
  }
866
866
  });
867
867
  function useCatalogCategories(enabled = true) {
package/dist/api.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var chunkFF45VZMM_cjs = require('./chunk-FF45VZMM.cjs');
3
+ var chunkYHEITFHR_cjs = require('./chunk-YHEITFHR.cjs');
4
4
  require('./chunk-WFMVD567.cjs');
5
- require('./chunk-XQ3QUHWR.cjs');
5
+ require('./chunk-THL5JDWJ.cjs');
6
6
  require('./chunk-HY3AXLOI.cjs');
7
- require('./chunk-M25DGZ5J.cjs');
7
+ require('./chunk-NIRYYJIJ.cjs');
8
8
  require('./chunk-H3IVLIPR.cjs');
9
- require('./chunk-UEE4PTTB.cjs');
9
+ require('./chunk-BXAKL2TF.cjs');
10
10
  require('./chunk-7NMT3GBR.cjs');
11
11
  require('./chunk-VM6OVUUM.cjs');
12
12
  require('./chunk-XFDIIVZB.cjs');
@@ -26,131 +26,131 @@ require('./chunk-USNT2KNT.cjs');
26
26
 
27
27
  Object.defineProperty(exports, "autoExpireOrderIfPaymentTimeExceeded", {
28
28
  enumerable: true,
29
- get: function () { return chunkFF45VZMM_cjs.autoExpireOrderIfPaymentTimeExceeded; }
29
+ get: function () { return chunkYHEITFHR_cjs.autoExpireOrderIfPaymentTimeExceeded; }
30
30
  });
31
31
  Object.defineProperty(exports, "createAnalyticsHandlers", {
32
32
  enumerable: true,
33
- get: function () { return chunkFF45VZMM_cjs.createAnalyticsHandlers; }
33
+ get: function () { return chunkYHEITFHR_cjs.createAnalyticsHandlers; }
34
34
  });
35
35
  Object.defineProperty(exports, "createBlogBySlugHandler", {
36
36
  enumerable: true,
37
- get: function () { return chunkFF45VZMM_cjs.createBlogBySlugHandler; }
37
+ get: function () { return chunkYHEITFHR_cjs.createBlogBySlugHandler; }
38
38
  });
39
39
  Object.defineProperty(exports, "createChangePasswordHandler", {
40
40
  enumerable: true,
41
- get: function () { return chunkFF45VZMM_cjs.createChangePasswordHandler; }
41
+ get: function () { return chunkYHEITFHR_cjs.createChangePasswordHandler; }
42
42
  });
43
43
  Object.defineProperty(exports, "createCmsApiHandler", {
44
44
  enumerable: true,
45
- get: function () { return chunkFF45VZMM_cjs.createCmsApiHandler; }
45
+ get: function () { return chunkYHEITFHR_cjs.createCmsApiHandler; }
46
46
  });
47
47
  Object.defineProperty(exports, "createCrudByIdHandler", {
48
48
  enumerable: true,
49
- get: function () { return chunkFF45VZMM_cjs.createCrudByIdHandler; }
49
+ get: function () { return chunkYHEITFHR_cjs.createCrudByIdHandler; }
50
50
  });
51
51
  Object.defineProperty(exports, "createCrudHandler", {
52
52
  enumerable: true,
53
- get: function () { return chunkFF45VZMM_cjs.createCrudHandler; }
53
+ get: function () { return chunkYHEITFHR_cjs.createCrudHandler; }
54
54
  });
55
55
  Object.defineProperty(exports, "createDashboardStatsHandler", {
56
56
  enumerable: true,
57
- get: function () { return chunkFF45VZMM_cjs.createDashboardStatsHandler; }
57
+ get: function () { return chunkYHEITFHR_cjs.createDashboardStatsHandler; }
58
58
  });
59
59
  Object.defineProperty(exports, "createEcommerceAnalyticsHandler", {
60
60
  enumerable: true,
61
- get: function () { return chunkFF45VZMM_cjs.createEcommerceAnalyticsHandler; }
61
+ get: function () { return chunkYHEITFHR_cjs.createEcommerceAnalyticsHandler; }
62
62
  });
63
63
  Object.defineProperty(exports, "createForgotPasswordHandler", {
64
64
  enumerable: true,
65
- get: function () { return chunkFF45VZMM_cjs.createForgotPasswordHandler; }
65
+ get: function () { return chunkYHEITFHR_cjs.createForgotPasswordHandler; }
66
66
  });
67
67
  Object.defineProperty(exports, "createFormBySlugHandler", {
68
68
  enumerable: true,
69
- get: function () { return chunkFF45VZMM_cjs.createFormBySlugHandler; }
69
+ get: function () { return chunkYHEITFHR_cjs.createFormBySlugHandler; }
70
70
  });
71
71
  Object.defineProperty(exports, "createInviteAcceptHandler", {
72
72
  enumerable: true,
73
- get: function () { return chunkFF45VZMM_cjs.createInviteAcceptHandler; }
73
+ get: function () { return chunkYHEITFHR_cjs.createInviteAcceptHandler; }
74
74
  });
75
75
  Object.defineProperty(exports, "createJobScheduleHandlers", {
76
76
  enumerable: true,
77
- get: function () { return chunkFF45VZMM_cjs.createJobScheduleHandlers; }
77
+ get: function () { return chunkYHEITFHR_cjs.createJobScheduleHandlers; }
78
78
  });
79
79
  Object.defineProperty(exports, "createLlmAgentKnowledgeHandlers", {
80
80
  enumerable: true,
81
- get: function () { return chunkFF45VZMM_cjs.createLlmAgentKnowledgeHandlers; }
81
+ get: function () { return chunkYHEITFHR_cjs.createLlmAgentKnowledgeHandlers; }
82
82
  });
83
83
  Object.defineProperty(exports, "createMediaZipExtractHandler", {
84
84
  enumerable: true,
85
- get: function () { return chunkFF45VZMM_cjs.createMediaZipExtractHandler; }
85
+ get: function () { return chunkYHEITFHR_cjs.createMediaZipExtractHandler; }
86
86
  });
87
87
  Object.defineProperty(exports, "createSetPasswordHandler", {
88
88
  enumerable: true,
89
- get: function () { return chunkFF45VZMM_cjs.createSetPasswordHandler; }
89
+ get: function () { return chunkYHEITFHR_cjs.createSetPasswordHandler; }
90
90
  });
91
91
  Object.defineProperty(exports, "createSettingsApiHandlers", {
92
92
  enumerable: true,
93
- get: function () { return chunkFF45VZMM_cjs.createSettingsApiHandlers; }
93
+ get: function () { return chunkYHEITFHR_cjs.createSettingsApiHandlers; }
94
94
  });
95
95
  Object.defineProperty(exports, "createStorefrontApiHandler", {
96
96
  enumerable: true,
97
- get: function () { return chunkFF45VZMM_cjs.createStorefrontApiHandler; }
97
+ get: function () { return chunkYHEITFHR_cjs.createStorefrontApiHandler; }
98
98
  });
99
99
  Object.defineProperty(exports, "createUploadHandler", {
100
100
  enumerable: true,
101
- get: function () { return chunkFF45VZMM_cjs.createUploadHandler; }
101
+ get: function () { return chunkYHEITFHR_cjs.createUploadHandler; }
102
102
  });
103
103
  Object.defineProperty(exports, "createUserAuthApiRouter", {
104
104
  enumerable: true,
105
- get: function () { return chunkFF45VZMM_cjs.createUserAuthApiRouter; }
105
+ get: function () { return chunkYHEITFHR_cjs.createUserAuthApiRouter; }
106
106
  });
107
107
  Object.defineProperty(exports, "createUserAvatarHandler", {
108
108
  enumerable: true,
109
- get: function () { return chunkFF45VZMM_cjs.createUserAvatarHandler; }
109
+ get: function () { return chunkYHEITFHR_cjs.createUserAvatarHandler; }
110
110
  });
111
111
  Object.defineProperty(exports, "createUserProfileHandler", {
112
112
  enumerable: true,
113
- get: function () { return chunkFF45VZMM_cjs.createUserProfileHandler; }
113
+ get: function () { return chunkYHEITFHR_cjs.createUserProfileHandler; }
114
114
  });
115
115
  Object.defineProperty(exports, "createUsersApiHandlers", {
116
116
  enumerable: true,
117
- get: function () { return chunkFF45VZMM_cjs.createUsersApiHandlers; }
117
+ get: function () { return chunkYHEITFHR_cjs.createUsersApiHandlers; }
118
118
  });
119
119
  Object.defineProperty(exports, "createVendorDashboardHandler", {
120
120
  enumerable: true,
121
- get: function () { return chunkFF45VZMM_cjs.createVendorDashboardHandler; }
121
+ get: function () { return chunkYHEITFHR_cjs.createVendorDashboardHandler; }
122
122
  });
123
123
  Object.defineProperty(exports, "createVendorOnboardHandlers", {
124
124
  enumerable: true,
125
- get: function () { return chunkFF45VZMM_cjs.createVendorOnboardHandlers; }
125
+ get: function () { return chunkYHEITFHR_cjs.createVendorOnboardHandlers; }
126
126
  });
127
127
  Object.defineProperty(exports, "getPublicSettingsGroup", {
128
128
  enumerable: true,
129
- get: function () { return chunkFF45VZMM_cjs.getPublicSettingsGroup; }
129
+ get: function () { return chunkYHEITFHR_cjs.getPublicSettingsGroup; }
130
130
  });
131
131
  Object.defineProperty(exports, "mergeGuardrailsIntoSystemPrompt", {
132
132
  enumerable: true,
133
- get: function () { return chunkFF45VZMM_cjs.mergeGuardrailsIntoSystemPrompt; }
133
+ get: function () { return chunkYHEITFHR_cjs.mergeGuardrailsIntoSystemPrompt; }
134
134
  });
135
135
  Object.defineProperty(exports, "parseLlmAgentValidationRules", {
136
136
  enumerable: true,
137
- get: function () { return chunkFF45VZMM_cjs.parseLlmAgentValidationRules; }
137
+ get: function () { return chunkYHEITFHR_cjs.parseLlmAgentValidationRules; }
138
138
  });
139
139
  Object.defineProperty(exports, "simpleDecrypt", {
140
140
  enumerable: true,
141
- get: function () { return chunkFF45VZMM_cjs.simpleDecrypt; }
141
+ get: function () { return chunkYHEITFHR_cjs.simpleDecrypt; }
142
142
  });
143
143
  Object.defineProperty(exports, "simpleEncrypt", {
144
144
  enumerable: true,
145
- get: function () { return chunkFF45VZMM_cjs.simpleEncrypt; }
145
+ get: function () { return chunkYHEITFHR_cjs.simpleEncrypt; }
146
146
  });
147
147
  Object.defineProperty(exports, "validateUserMessageAgainstAgentRules", {
148
148
  enumerable: true,
149
- get: function () { return chunkFF45VZMM_cjs.validateUserMessageAgainstAgentRules; }
149
+ get: function () { return chunkYHEITFHR_cjs.validateUserMessageAgainstAgentRules; }
150
150
  });
151
151
  Object.defineProperty(exports, "validateUserMessageAgainstStructuredRules", {
152
152
  enumerable: true,
153
- get: function () { return chunkFF45VZMM_cjs.validateUserMessageAgainstStructuredRules; }
153
+ get: function () { return chunkYHEITFHR_cjs.validateUserMessageAgainstStructuredRules; }
154
154
  });
155
155
  Object.defineProperty(exports, "createCmsAuthBundle", {
156
156
  enumerable: true,
package/dist/api.js CHANGED
@@ -1,10 +1,10 @@
1
- export { autoExpireOrderIfPaymentTimeExceeded, createAnalyticsHandlers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createEcommerceAnalyticsHandler, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createSetPasswordHandler, createSettingsApiHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, getPublicSettingsGroup, mergeGuardrailsIntoSystemPrompt, parseLlmAgentValidationRules, simpleDecrypt, simpleEncrypt, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules } from './chunk-K6C3ZSBZ.js';
1
+ export { autoExpireOrderIfPaymentTimeExceeded, createAnalyticsHandlers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createEcommerceAnalyticsHandler, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createSetPasswordHandler, createSettingsApiHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, getPublicSettingsGroup, mergeGuardrailsIntoSystemPrompt, parseLlmAgentValidationRules, simpleDecrypt, simpleEncrypt, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules } from './chunk-SANKKGB3.js';
2
2
  import './chunk-OVTOP42W.js';
3
- import './chunk-GO7PPYNU.js';
3
+ import './chunk-XJNNOSJR.js';
4
4
  import './chunk-3K5AIEIZ.js';
5
- import './chunk-OJAYCNE5.js';
5
+ import './chunk-ACBN6UWZ.js';
6
6
  import './chunk-GWDI752Q.js';
7
- import './chunk-AYWDQFJZ.js';
7
+ import './chunk-YEAXE4U2.js';
8
8
  import './chunk-JXF23MPG.js';
9
9
  import './chunk-6YOQ7G5O.js';
10
10
  import './chunk-TU23GJPJ.js';
@@ -1,5 +1,5 @@
1
1
  import { queueWhatsApp } from './chunk-GWDI752Q.js';
2
- import { notificationTriggerEmitter } from './chunk-AYWDQFJZ.js';
2
+ import { notifyLog, maskNotifyToken, maskNotifyEmail, maskNotifyPhone, notificationTriggerEmitter } from './chunk-YEAXE4U2.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';
@@ -1400,12 +1400,6 @@ var ORDER_NOTIFICATION_DEFAULTS = {
1400
1400
 
1401
1401
  // src/lib/order-notification-dispatcher.ts
1402
1402
  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
1403
  async function getSettingsGroup(dataSource, entityMap, group) {
1410
1404
  if (!entityMap.configs) return {};
1411
1405
  const rows = await dataSource.getRepository(entityMap.configs).find({
@@ -1615,11 +1609,26 @@ async function sendPushNotificationForTrigger(triggerKey, orderId, audienceType,
1615
1609
  if (!template) {
1616
1610
  template = await loadBoundTemplate(triggerKey, "push", audienceType, dataSource, entityMap);
1617
1611
  }
1618
- if (!template || !template.body) return;
1612
+ if (!template || !template.body) {
1613
+ notifyLog.skip("PUSH", "no mobile/push template or empty body", {
1614
+ triggerKey,
1615
+ orderId,
1616
+ audienceType,
1617
+ targetId
1618
+ });
1619
+ return;
1620
+ }
1619
1621
  const rawTitle = template.subject?.trim() || "Order Notification";
1620
1622
  const title = applyTemplateVars(rawTitle, variables);
1621
1623
  const body = applyTemplateVars(template.body, variables);
1622
- if (!entityMap.user_device_tokens) return;
1624
+ if (!entityMap.user_device_tokens) {
1625
+ notifyLog.skip("PUSH", "user_device_tokens entity not registered", {
1626
+ triggerKey,
1627
+ orderId,
1628
+ audienceType
1629
+ });
1630
+ return;
1631
+ }
1623
1632
  const tokenRepo = dataSource.getRepository(entityMap.user_device_tokens);
1624
1633
  let targetTokens = [];
1625
1634
  try {
@@ -1654,19 +1663,60 @@ async function sendPushNotificationForTrigger(triggerKey, orderId, audienceType,
1654
1663
  });
1655
1664
  }
1656
1665
  } catch (err) {
1657
- console.error("[order-notifications] Error querying device tokens for push", err);
1666
+ notifyLog.error("PUSH", "device token query failed", {
1667
+ triggerKey,
1668
+ orderId,
1669
+ audienceType,
1670
+ targetId,
1671
+ error: err instanceof Error ? err.message : String(err)
1672
+ });
1658
1673
  return;
1659
1674
  }
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
- }
1675
+ const tokens = targetTokens.map((t) => t.token?.trim()).filter(Boolean);
1676
+ notifyLog.push("sending", {
1677
+ triggerKey,
1678
+ orderId,
1679
+ audienceType,
1680
+ targetId,
1681
+ title,
1682
+ tokenCount: tokens.length,
1683
+ tokens: tokens.map((t) => maskNotifyToken(t))
1684
+ });
1685
+ if (tokens.length === 0) {
1686
+ notifyLog.skip("PUSH", "no active FCM tokens for target", {
1687
+ triggerKey,
1688
+ orderId,
1689
+ audienceType,
1690
+ targetId,
1691
+ hint: "App must POST /api/user-device-tokens after login"
1692
+ });
1693
+ return;
1694
+ }
1695
+ for (const token of tokens) {
1696
+ const res = await sendFcmPushNotification(dataSource, entityMap, {
1697
+ token,
1698
+ title,
1699
+ body,
1700
+ data: {
1701
+ orderId: String(orderId),
1702
+ triggerKey
1703
+ }
1704
+ });
1705
+ if (res.success) {
1706
+ notifyLog.push("FCM sent", {
1707
+ triggerKey,
1708
+ orderId,
1709
+ audienceType,
1710
+ token: maskNotifyToken(token),
1711
+ messageId: res.messageId ?? null
1712
+ });
1713
+ } else {
1714
+ notifyLog.error("PUSH", "FCM send failed", {
1715
+ triggerKey,
1716
+ orderId,
1717
+ audienceType,
1718
+ token: maskNotifyToken(token),
1719
+ error: res.error ?? "unknown"
1670
1720
  });
1671
1721
  }
1672
1722
  }
@@ -1810,7 +1860,15 @@ function formatBodyForEmailHtml(body) {
1810
1860
  __name(formatBodyForEmailHtml, "formatBodyForEmailHtml");
1811
1861
  async function sendEmailForTrigger(triggerKey, orderId, audienceType, variables, contactEmail, dataSource, entityMap, getCms) {
1812
1862
  const template = await loadBoundTemplate(triggerKey, "email", audienceType, dataSource, entityMap);
1813
- if (!template) return;
1863
+ if (!template) {
1864
+ notifyLog.skip("EMAIL", "no bound/default email template", {
1865
+ triggerKey,
1866
+ orderId,
1867
+ audienceType,
1868
+ to: maskNotifyEmail(contactEmail)
1869
+ });
1870
+ return;
1871
+ }
1814
1872
  const [branding, emailSettings, storeSettings] = await Promise.all([
1815
1873
  getSettingsGroup(dataSource, entityMap, "branding"),
1816
1874
  getSettingsGroup(dataSource, entityMap, "email"),
@@ -1845,22 +1903,31 @@ async function sendEmailForTrigger(triggerKey, orderId, audienceType, variables,
1845
1903
  attachInvoice: true
1846
1904
  } : {}
1847
1905
  });
1848
- console.log("[order-notifications] email queued", {
1906
+ notifyLog.email("queued", {
1849
1907
  triggerKey,
1850
1908
  audienceType,
1851
1909
  orderId,
1852
- to: contactEmail,
1910
+ to: maskNotifyEmail(contactEmail),
1911
+ subject,
1853
1912
  attachInvoice: shouldAttachInvoice
1854
1913
  });
1855
1914
  }
1856
1915
  __name(sendEmailForTrigger, "sendEmailForTrigger");
1857
1916
  async function sendWhatsAppForTrigger(triggerKey, orderId, phone, variables, dataSource, entityMap, getCms) {
1858
1917
  const template = await loadBoundTemplate(triggerKey, "whatsapp", "customers", dataSource, entityMap);
1859
- if (!template) return;
1918
+ if (!template) {
1919
+ notifyLog.skip("WHATSAPP", "no bound/default WhatsApp template", {
1920
+ triggerKey,
1921
+ orderId,
1922
+ phone: maskNotifyPhone(phone)
1923
+ });
1924
+ return;
1925
+ }
1860
1926
  const paramOrder = template.providerMeta?.paramOrder ?? [];
1861
1927
  if (paramOrder.length === 0) {
1862
- console.warn("[order-notifications] WhatsApp template has no paramOrder set \u2014 variables may send blank/wrong", {
1863
- triggerKey
1928
+ notifyLog.skip("WHATSAPP", "template has no paramOrder \u2014 variables may send blank/wrong", {
1929
+ triggerKey,
1930
+ orderId
1864
1931
  });
1865
1932
  }
1866
1933
  const cms = await getCms();
@@ -1869,8 +1936,10 @@ async function sendWhatsAppForTrigger(triggerKey, orderId, phone, variables, dat
1869
1936
  name: template.name
1870
1937
  });
1871
1938
  if (!metaTemplateName) {
1872
- console.warn("[order-notifications] bound WhatsApp template has no Meta template name", {
1939
+ notifyLog.skip("WHATSAPP", "template has no Meta template name", {
1873
1940
  triggerKey,
1941
+ orderId,
1942
+ phone: maskNotifyPhone(phone),
1874
1943
  templateId: template.id
1875
1944
  });
1876
1945
  return;
@@ -1885,37 +1954,57 @@ async function sendWhatsAppForTrigger(triggerKey, orderId, phone, variables, dat
1885
1954
  templateParamOrder: paramOrder
1886
1955
  });
1887
1956
  if (!sent) {
1888
- console.warn("[order-notifications] WhatsApp send failed", {
1957
+ notifyLog.error("WHATSAPP", "send failed / not queued", {
1889
1958
  triggerKey,
1890
1959
  orderId,
1960
+ phone: maskNotifyPhone(phone),
1891
1961
  hint: "Register whatsappPlugin() + queuePlugin() in getCms(), or set WHATSAPP_ACCESS_TOKEN and WHATSAPP_PHONE_NUMBER_ID"
1892
1962
  });
1893
1963
  } else {
1894
- console.log("[order-notifications] WhatsApp queued/sent", {
1964
+ notifyLog.whatsapp("queued/sent", {
1895
1965
  triggerKey,
1896
1966
  orderId,
1897
- phone: maskPhone2(phone)
1967
+ phone: maskNotifyPhone(phone),
1968
+ metaTemplateName
1898
1969
  });
1899
1970
  }
1900
1971
  }
1901
1972
  __name(sendWhatsAppForTrigger, "sendWhatsAppForTrigger");
1902
1973
  async function handleTrigger(triggerKey, payload, dataSource, entityMap, getCms) {
1903
- console.log("[order-notifications] received", {
1974
+ notifyLog.trigger("dispatcher received", {
1904
1975
  triggerKey,
1905
1976
  orderId: payload.orderId,
1906
- phone: maskPhone2(payload.customerPhone)
1977
+ orderNumber: payload.orderNumber,
1978
+ phone: maskNotifyPhone(payload.customerPhone),
1979
+ vendorId: payload.vendorId ?? null
1907
1980
  });
1908
1981
  const [emailChannelEnabled, whatsappChannelEnabled, pushChannelEnabled] = await Promise.all([
1909
1982
  isEmailNotificationsEnabled(dataSource, entityMap),
1910
1983
  isWhatsappNotificationsEnabled(dataSource, entityMap),
1911
1984
  isPushNotificationsEnabled(dataSource, entityMap)
1912
1985
  ]);
1986
+ notifyLog.trigger("channel switches", {
1987
+ triggerKey,
1988
+ orderId: payload.orderId,
1989
+ email: emailChannelEnabled,
1990
+ whatsapp: whatsappChannelEnabled,
1991
+ push: pushChannelEnabled
1992
+ });
1913
1993
  if (!emailChannelEnabled && !whatsappChannelEnabled && !pushChannelEnabled) {
1914
- console.warn("[order-notifications] skip: Email, WhatsApp, and Mobile Push notifications are disabled");
1994
+ notifyLog.skip("ALL", "Email, WhatsApp, and Mobile Push are disabled in event_notifications", {
1995
+ triggerKey,
1996
+ orderId: payload.orderId
1997
+ });
1915
1998
  return;
1916
1999
  }
1917
2000
  const triggerEnabled = await isTriggerCatalogEnabled(triggerKey, dataSource, entityMap);
1918
- if (!triggerEnabled) return;
2001
+ if (!triggerEnabled) {
2002
+ notifyLog.skip("TRIGGER", "trigger catalog disabled", {
2003
+ triggerKey,
2004
+ orderId: payload.orderId
2005
+ });
2006
+ return;
2007
+ }
1919
2008
  const context = await loadOrderNotificationContexts(payload.orderId, {
1920
2009
  dataSource,
1921
2010
  entityMap
@@ -1923,37 +2012,86 @@ async function handleTrigger(triggerKey, payload, dataSource, entityMap, getCms)
1923
2012
  const variables = mergeTriggerVariables(payload, context?.variables);
1924
2013
  const contactEmail = context?.contact.email?.trim() || "";
1925
2014
  const contactPhone = context?.contact.phone?.trim() || payload.customerPhone?.trim() || "";
2015
+ notifyLog.trigger("recipients resolved", {
2016
+ triggerKey,
2017
+ orderId: payload.orderId,
2018
+ contactEmail: maskNotifyEmail(contactEmail),
2019
+ contactPhone: maskNotifyPhone(contactPhone)
2020
+ });
1926
2021
  if (emailChannelEnabled) {
1927
2022
  const [customerEnabled, vendorEnabled, adminEnabled] = await Promise.all([
1928
2023
  isAudienceEmailEnabled(dataSource, entityMap, "customer"),
1929
2024
  isAudienceEmailEnabled(dataSource, entityMap, "vendor"),
1930
2025
  isAudienceEmailEnabled(dataSource, entityMap, "admin")
1931
2026
  ]);
2027
+ notifyLog.email("audience switches", {
2028
+ triggerKey,
2029
+ orderId: payload.orderId,
2030
+ customer: customerEnabled,
2031
+ vendor: vendorEnabled,
2032
+ admin: adminEnabled
2033
+ });
1932
2034
  if (triggerKey === "order_assigned_assignee") {
1933
2035
  const assigneeEmail = context?.order?.assignedUser?.email?.trim();
1934
2036
  if (assigneeEmail) {
1935
2037
  await sendEmailForTrigger(triggerKey, payload.orderId, "customers", variables, assigneeEmail, dataSource, entityMap, getCms);
2038
+ } else {
2039
+ notifyLog.skip("EMAIL", "order_assigned_assignee has no assignee email", {
2040
+ triggerKey,
2041
+ orderId: payload.orderId
2042
+ });
1936
2043
  }
1937
2044
  } else if (customerEnabled && contactEmail) {
1938
2045
  await sendEmailForTrigger(triggerKey, payload.orderId, "customers", variables, contactEmail, dataSource, entityMap, getCms);
2046
+ } else if (!customerEnabled) {
2047
+ notifyLog.skip("EMAIL", "customer email audience disabled", {
2048
+ triggerKey,
2049
+ orderId: payload.orderId
2050
+ });
2051
+ } else {
2052
+ notifyLog.skip("EMAIL", "no customer email on order contact", {
2053
+ triggerKey,
2054
+ orderId: payload.orderId
2055
+ });
1939
2056
  }
1940
2057
  if (vendorEnabled && triggerKey !== "order_assigned_assignee") {
1941
2058
  const multiVendorSettings = await getSettingsGroup(dataSource, entityMap, "multi_vendor");
1942
2059
  if (multiVendorSettings.enabled !== "false" && multiVendorSettings.enabled !== "0") {
1943
2060
  const vendorEmails = await getOrderVendorEmails(payload.orderId, payload.vendorId, dataSource, entityMap);
2061
+ if (vendorEmails.length === 0) {
2062
+ notifyLog.skip("EMAIL", "no vendor emails for order", {
2063
+ triggerKey,
2064
+ orderId: payload.orderId,
2065
+ vendorId: payload.vendorId ?? null
2066
+ });
2067
+ }
1944
2068
  for (const vEmail of vendorEmails) {
1945
2069
  await sendEmailForTrigger(triggerKey, payload.orderId, "vendors", variables, vEmail, dataSource, entityMap, getCms);
1946
2070
  }
2071
+ } else {
2072
+ notifyLog.skip("EMAIL", "multi-vendor off \u2014 skip vendor email", {
2073
+ triggerKey,
2074
+ orderId: payload.orderId
2075
+ });
1947
2076
  }
1948
2077
  }
1949
2078
  if (adminEnabled && triggerKey !== "order_assigned_assignee") {
1950
2079
  const adminEmails = await getAdminRecipientEmails(dataSource, entityMap);
2080
+ if (adminEmails.length === 0) {
2081
+ notifyLog.skip("EMAIL", "no admin recipient emails", {
2082
+ triggerKey,
2083
+ orderId: payload.orderId
2084
+ });
2085
+ }
1951
2086
  for (const aEmail of adminEmails) {
1952
2087
  await sendEmailForTrigger(triggerKey, payload.orderId, "admin", variables, aEmail, dataSource, entityMap, getCms);
1953
2088
  }
1954
2089
  }
1955
2090
  } else {
1956
- console.log("[order-notifications] skip email: Email notifications channel is disabled");
2091
+ notifyLog.skip("EMAIL", "email channel disabled", {
2092
+ triggerKey,
2093
+ orderId: payload.orderId
2094
+ });
1957
2095
  }
1958
2096
  if (pushChannelEnabled) {
1959
2097
  const [pushCustomerEnabled, pushVendorEnabled, pushAdminEnabled] = await Promise.all([
@@ -1961,29 +2099,59 @@ async function handleTrigger(triggerKey, payload, dataSource, entityMap, getCms)
1961
2099
  isAudiencePushEnabled(dataSource, entityMap, "vendor"),
1962
2100
  isAudiencePushEnabled(dataSource, entityMap, "admin")
1963
2101
  ]);
2102
+ notifyLog.push("audience switches", {
2103
+ triggerKey,
2104
+ orderId: payload.orderId,
2105
+ customer: pushCustomerEnabled,
2106
+ vendor: pushVendorEnabled,
2107
+ admin: pushAdminEnabled
2108
+ });
1964
2109
  const targetCustomerId = triggerKey === "order_assigned_assignee" ? context?.order?.assignedUser?.id : context?.order?.customerContactId || context?.order?.contactId || context?.order?.userId || context?.order?.id;
1965
2110
  if (pushCustomerEnabled && targetCustomerId) {
1966
2111
  await sendPushNotificationForTrigger(triggerKey, payload.orderId, "customers", String(targetCustomerId), variables, dataSource, entityMap);
2112
+ } else if (!pushCustomerEnabled) {
2113
+ notifyLog.skip("PUSH", "customer push audience disabled", {
2114
+ triggerKey,
2115
+ orderId: payload.orderId
2116
+ });
2117
+ } else {
2118
+ notifyLog.skip("PUSH", "no customer user/contact id for push", {
2119
+ triggerKey,
2120
+ orderId: payload.orderId
2121
+ });
1967
2122
  }
1968
2123
  if (pushVendorEnabled && payload.vendorId && triggerKey !== "order_assigned_assignee") {
1969
2124
  await sendPushNotificationForTrigger(triggerKey, payload.orderId, "vendors", String(payload.vendorId), variables, dataSource, entityMap);
2125
+ } else if (pushVendorEnabled && triggerKey !== "order_assigned_assignee" && !payload.vendorId) {
2126
+ notifyLog.skip("PUSH", "no vendorId on order \u2014 skip vendor push", {
2127
+ triggerKey,
2128
+ orderId: payload.orderId
2129
+ });
1970
2130
  }
1971
2131
  if (pushAdminEnabled && triggerKey !== "order_assigned_assignee") {
1972
2132
  await sendPushNotificationForTrigger(triggerKey, payload.orderId, "admin", "admin", variables, dataSource, entityMap);
1973
2133
  }
2134
+ } else {
2135
+ notifyLog.skip("PUSH", "push channel disabled", {
2136
+ triggerKey,
2137
+ orderId: payload.orderId
2138
+ });
1974
2139
  }
1975
2140
  if (whatsappChannelEnabled) {
1976
2141
  const targetPhone = triggerKey === "order_assigned_assignee" ? context?.order?.assignedUser?.phone?.trim() : contactPhone;
1977
2142
  if (targetPhone) {
1978
2143
  await sendWhatsAppForTrigger(triggerKey, payload.orderId, targetPhone, variables, dataSource, entityMap, getCms);
1979
2144
  } else {
1980
- console.warn("[order-notifications] skip WhatsApp: no recipient phone", {
2145
+ notifyLog.skip("WHATSAPP", "no recipient phone", {
1981
2146
  triggerKey,
1982
2147
  orderId: payload.orderId
1983
2148
  });
1984
2149
  }
1985
2150
  } else {
1986
- console.log("[order-notifications] skip WhatsApp: WhatsApp notifications channel is disabled");
2151
+ notifyLog.skip("WHATSAPP", "WhatsApp channel disabled", {
2152
+ triggerKey,
2153
+ orderId: payload.orderId
2154
+ });
1987
2155
  }
1988
2156
  }
1989
2157
  __name(handleTrigger, "handleTrigger");
@@ -1997,10 +2165,21 @@ function initWhatsappTriggerDispatcher(deps) {
1997
2165
  });
1998
2166
  notificationTriggerEmitter.onAnyTrigger((triggerKey, payload) => {
1999
2167
  void handleTrigger(triggerKey, payload, dataSource, entityMap, getCms).catch((err) => {
2000
- console.error("[order-notifications]", triggerKey, err);
2168
+ notifyLog.error("TRIGGER", "dispatcher handleTrigger failed", {
2169
+ triggerKey,
2170
+ orderId: payload.orderId,
2171
+ error: err instanceof Error ? err.message : String(err),
2172
+ stack: err instanceof Error ? err.stack : void 0
2173
+ });
2001
2174
  });
2002
2175
  });
2003
- console.log("[order-notifications] dispatcher initialized (email + WhatsApp, unified via order_notification_bindings)");
2176
+ notifyLog.trigger("dispatcher initialized", {
2177
+ channels: [
2178
+ "email",
2179
+ "whatsapp",
2180
+ "push"
2181
+ ]
2182
+ });
2004
2183
  }
2005
2184
  __name(initWhatsappTriggerDispatcher, "initWhatsappTriggerDispatcher");
2006
2185
  async function dispatchOrderNotificationDirectly(triggerKey, payload, dataSource, entityMap, getCms) {