@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,16 +1,10 @@
1
- import { notificationTriggerEmitter } from './chunk-AYWDQFJZ.js';
1
+ import { notifyLog, notificationTriggerEmitter, maskNotifyPhone } from './chunk-FLUF2GZH.js';
2
2
  import { __name } from './chunk-SHUYVCID.js';
3
3
 
4
4
  // src/lib/emit-order-notification-trigger.ts
5
- function maskPhone(raw) {
6
- const digits = String(raw ?? "").replace(/\D/g, "");
7
- if (digits.length <= 4) return "(none)";
8
- return `***${digits.slice(-4)}`;
9
- }
10
- __name(maskPhone, "maskPhone");
11
5
  async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
12
6
  if (!deps.entityMap.orders) {
13
- console.warn("[notification-triggers] skip emit: orders entity missing from entityMap", {
7
+ notifyLog.skip("TRIGGER", "orders entity missing from entityMap", {
14
8
  triggerKey,
15
9
  orderId
16
10
  });
@@ -18,7 +12,10 @@ async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
18
12
  }
19
13
  const listenerCount = notificationTriggerEmitter.listenerCount("__any__");
20
14
  if (listenerCount === 0) {
21
- console.warn("[notification-triggers] no WhatsApp dispatcher listener \u2014 ensure createCmsApiHandler passes getCms (initWhatsappTriggerDispatcher)");
15
+ notifyLog.skip("TRIGGER", "no dispatcher listener \u2014 will try direct dispatch (pass getCms to createCmsApiHandler)", {
16
+ triggerKey,
17
+ orderId
18
+ });
22
19
  }
23
20
  const orderRepo = deps.dataSource.getRepository(deps.entityMap.orders);
24
21
  const fullOrder = await orderRepo.findOne({
@@ -31,7 +28,7 @@ async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
31
28
  ]
32
29
  });
33
30
  if (!fullOrder) {
34
- console.warn("[notification-triggers] skip emit: order not found", {
31
+ notifyLog.skip("TRIGGER", "order not found", {
35
32
  triggerKey,
36
33
  orderId
37
34
  });
@@ -39,15 +36,18 @@ async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
39
36
  }
40
37
  const fo = fullOrder;
41
38
  const phone = fo.contact?.phone ?? null;
42
- console.log("[notification-triggers] emit", {
39
+ notifyLog.trigger("emit", {
43
40
  triggerKey,
44
41
  orderId,
45
42
  orderNumber: fo.orderNumber ?? null,
46
- phone: maskPhone(phone),
47
- listeners: listenerCount
43
+ phone: maskNotifyPhone(phone),
44
+ listeners: listenerCount,
45
+ vendorId: fo.vendorId ?? null,
46
+ source: extra?.source ?? "api"
48
47
  });
49
48
  if (!phone?.trim()) {
50
- console.warn("[notification-triggers] order contact has no phone \u2014 WhatsApp will be skipped", {
49
+ notifyLog.skip("WHATSAPP", "order contact has no phone", {
50
+ triggerKey,
51
51
  orderId
52
52
  });
53
53
  }
@@ -89,28 +89,44 @@ async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
89
89
  refundAmount: resolvedRefundAmount
90
90
  };
91
91
  if (listenerCount === 0) {
92
+ notifyLog.trigger("direct dispatch (no in-process listener)", {
93
+ triggerKey,
94
+ orderId
95
+ });
92
96
  try {
93
- const { dispatchOrderNotificationDirectly } = await import('./order-notification-dispatcher-ID2PDEXD.js');
97
+ const { dispatchOrderNotificationDirectly } = await import('./order-notification-dispatcher-ECPFI7CD.js');
94
98
  await dispatchOrderNotificationDirectly(triggerKey, triggerPayload, deps.dataSource, deps.entityMap);
95
99
  } catch (err) {
96
- console.error("[notification-triggers] direct dispatch failed", {
100
+ notifyLog.error("TRIGGER", "direct dispatch failed", {
97
101
  triggerKey,
98
102
  orderId,
99
- err
103
+ error: err instanceof Error ? err.message : String(err),
104
+ stack: err instanceof Error ? err.stack : void 0
100
105
  });
101
106
  }
102
107
  } else {
108
+ notifyLog.trigger("emit to dispatcher listener", {
109
+ triggerKey,
110
+ orderId,
111
+ listeners: listenerCount
112
+ });
103
113
  notificationTriggerEmitter.emitTrigger(triggerKey, triggerPayload);
104
114
  }
105
115
  }
106
116
  __name(emitOrderNotificationTrigger, "emitOrderNotificationTrigger");
107
117
  function fireOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
108
- console.log("[notification-triggers] fire", {
118
+ notifyLog.trigger("FIRE", {
109
119
  triggerKey,
110
- orderId
120
+ orderId,
121
+ source: extra?.source ?? "api"
111
122
  });
112
123
  void emitOrderNotificationTrigger(triggerKey, orderId, deps, extra).catch((err) => {
113
- console.error("[notification-triggers]", triggerKey, orderId, err);
124
+ notifyLog.error("TRIGGER", "fire failed", {
125
+ triggerKey,
126
+ orderId,
127
+ error: err instanceof Error ? err.message : String(err),
128
+ stack: err instanceof Error ? err.stack : void 0
129
+ });
114
130
  });
115
131
  }
116
132
  __name(fireOrderNotificationTrigger, "fireOrderNotificationTrigger");
@@ -1,7 +1,7 @@
1
1
  import { normalizePhoneE164, generateNumericOtp, createOtpChallenge, queueSms, verifyAndConsumeOtpChallenge } from './chunk-OVTOP42W.js';
2
- import { JOB_RUNNER_QUEUE } from './chunk-GO7PPYNU.js';
2
+ import { JOB_RUNNER_QUEUE } from './chunk-XJNNOSJR.js';
3
3
  import { validateInventoryForConfirmedOrderLines, orderStatusHoldsStock, reconcileOrderInventoryBetweenSnapshots, orderInventorySnapshotFromRow, validateInventoryForOrderBecomingConfirmed } from './chunk-3K5AIEIZ.js';
4
- import { resolveChatEmailToolSettings, CHAT_EMAIL_LOG, detectChatLeadIntent, parseIntentRecipientEmails, sendChatLeadEmail, buildTranscriptForLeadEmail, buildChatbotSystemPromptWithEmailTool, validateFcmCredentials, sendFcmPushNotification, parseEmailRecipientsFromConfig, isWhatsAppPluginEnabled, WhatsAppService, emailPlugin, initWhatsappTriggerDispatcher } from './chunk-OJAYCNE5.js';
4
+ import { resolveChatEmailToolSettings, CHAT_EMAIL_LOG, detectChatLeadIntent, parseIntentRecipientEmails, sendChatLeadEmail, buildTranscriptForLeadEmail, buildChatbotSystemPromptWithEmailTool, validateFcmCredentials, sendFcmPushNotification, parseEmailRecipientsFromConfig, isWhatsAppPluginEnabled, WhatsAppService, emailPlugin, initWhatsappTriggerDispatcher } from './chunk-NV5IRHI3.js';
5
5
  import { registerWhatsAppQueueProcessor } from './chunk-GWDI752Q.js';
6
6
  import { inviteStatusForActivation } from './chunk-JXF23MPG.js';
7
7
  import { queueEmail, queueVendorOnboardEmails, registerEmailQueueProcessor } from './chunk-TU23GJPJ.js';
@@ -5229,7 +5229,7 @@ function createCrudHandler(dataSource, entityMap, options) {
5229
5229
  const orderIdForNotify = created.id;
5230
5230
  const finalCreatedStatus = String(created.status ?? createdStatus ?? "pending").toLowerCase();
5231
5231
  const initialPayStatus = String(persistBody.paymentStatus ?? body.paymentStatus ?? "unpaid").toLowerCase();
5232
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
5232
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
5233
5233
  if (finalCreatedStatus === "pending") {
5234
5234
  if (initialPayStatus === "failed") {
5235
5235
  fireOrderNotificationTrigger("payment_failed", orderIdForNotify, {
@@ -6309,7 +6309,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6309
6309
  const paymentUpdated = Boolean(rawBody && typeof rawBody === "object" && rawBody.paymentStatus != null);
6310
6310
  const assigneeUpdated = Boolean(rawBody && typeof rawBody === "object" && "assignedUserId" in rawBody && rawBody.assignedUserId !== void 0 && Number(rawBody.assignedUserId) > 0 && Number(rawBody.assignedUserId) !== Number(existingOrderRow?.assignedUserId));
6311
6311
  if (assigneeUpdated) {
6312
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
6312
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
6313
6313
  fireOrderNotificationTrigger("order_assigned", updatedOrder.id, {
6314
6314
  dataSource,
6315
6315
  entityMap
@@ -6326,7 +6326,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6326
6326
  const payments = Array.isArray(updatedOrder.payments) ? updatedOrder.payments : [];
6327
6327
  const bodyPayStatus = rawBody && typeof rawBody === "object" && rawBody.paymentStatus != null ? String(rawBody.paymentStatus).toLowerCase() : null;
6328
6328
  const curPayStatus = bodyPayStatus || String(payments[0]?.status || "unpaid").toLowerCase();
6329
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
6329
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
6330
6330
  if (newStatus === "pending") {
6331
6331
  if (curPayStatus === "failed") {
6332
6332
  fireOrderNotificationTrigger("payment_failed", updatedOrder.id, {
@@ -6980,7 +6980,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6980
6980
  });
6981
6981
  }
6982
6982
  if (ordStatus === "pending" || ordStatus === "confirmed") {
6983
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
6983
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
6984
6984
  fireOrderNotificationTrigger("order_placed", pOrder, {
6985
6985
  dataSource,
6986
6986
  entityMap
@@ -6994,7 +6994,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6994
6994
  }
6995
6995
  }
6996
6996
  } else if (newPayStatus === "failed") {
6997
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
6997
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
6998
6998
  fireOrderNotificationTrigger("payment_failed", pOrder, {
6999
6999
  dataSource,
7000
7000
  entityMap
@@ -7002,7 +7002,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
7002
7002
  }).catch(() => {
7003
7003
  });
7004
7004
  } else if (newPayStatus === "refunded") {
7005
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
7005
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
7006
7006
  fireOrderNotificationTrigger("payment_refund_initiated", pOrder, {
7007
7007
  dataSource,
7008
7008
  entityMap
@@ -7129,7 +7129,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
7129
7129
  const paymentUpdated = Boolean(rawBody && typeof rawBody === "object" && rawBody.paymentStatus != null);
7130
7130
  const assigneeUpdated = Boolean(rawBody && typeof rawBody === "object" && "assignedUserId" in rawBody && rawBody.assignedUserId !== void 0 && Number(rawBody.assignedUserId) > 0 && Number(rawBody.assignedUserId) !== Number(existingOrderRow?.assignedUserId));
7131
7131
  if (assigneeUpdated) {
7132
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
7132
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
7133
7133
  fireOrderNotificationTrigger("order_assigned", ord.id, {
7134
7134
  dataSource,
7135
7135
  entityMap
@@ -7146,7 +7146,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
7146
7146
  const payments = Array.isArray(ord.payments) ? ord.payments : [];
7147
7147
  const bodyPayStatus = rawBody && typeof rawBody === "object" && rawBody.paymentStatus != null ? String(rawBody.paymentStatus).toLowerCase() : null;
7148
7148
  const curPayStatus = bodyPayStatus || String(payments[0]?.status || "unpaid").toLowerCase();
7149
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
7149
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
7150
7150
  if (newStatus === "pending") {
7151
7151
  if (curPayStatus === "failed") {
7152
7152
  fireOrderNotificationTrigger("payment_failed", ord.id, {
@@ -27485,7 +27485,7 @@ async function queueJobScheduleNow(cms, scheduleId) {
27485
27485
  if (!boss) {
27486
27486
  throw new Error("pg-boss is not configured (DATABASE_URL required)");
27487
27487
  }
27488
- const { JOB_RUNNER_QUEUE: JOB_RUNNER_QUEUE2 } = await import('./pg-boss-service-4XF2TQ2E.js');
27488
+ const { JOB_RUNNER_QUEUE: JOB_RUNNER_QUEUE2 } = await import('./pg-boss-service-WCBJD4JB.js');
27489
27489
  await boss.send(JOB_RUNNER_QUEUE2, {
27490
27490
  scheduleId,
27491
27491
  triggeredBy: "manual"
@@ -28314,7 +28314,7 @@ function slugify2(input) {
28314
28314
  return input.toLowerCase().trim().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 64) || "template";
28315
28315
  }
28316
28316
  __name(slugify2, "slugify");
28317
- function createEmailMessageTemplatesHandlers(config) {
28317
+ function createTextMessageTemplatesHandlers(config, channel) {
28318
28318
  const { dataSource, entityMap, json, requireAuth, requireEntityPermission } = config;
28319
28319
  const templateRepo = /* @__PURE__ */ __name(() => dataSource.getRepository(entityMap.message_templates), "templateRepo");
28320
28320
  async function requireRead(req, entity) {
@@ -28337,6 +28337,10 @@ function createEmailMessageTemplatesHandlers(config) {
28337
28337
  return null;
28338
28338
  }
28339
28339
  __name(requireUpdate, "requireUpdate");
28340
+ function isLegacyPushTemplate(row) {
28341
+ return row.channel === "email" && typeof row.name === "string" && row.name.includes("_push_");
28342
+ }
28343
+ __name(isLegacyPushTemplate, "isLegacyPushTemplate");
28340
28344
  return {
28341
28345
  async listCached(req) {
28342
28346
  const err = await requireRead(req, "settings");
@@ -28344,15 +28348,19 @@ function createEmailMessageTemplatesHandlers(config) {
28344
28348
  try {
28345
28349
  const rows = await templateRepo().find({
28346
28350
  where: {
28347
- channel: "email",
28348
28351
  deleted: false
28349
28352
  },
28350
28353
  order: {
28351
28354
  name: "ASC"
28352
28355
  }
28353
28356
  });
28357
+ const items = rows.filter((row) => {
28358
+ const r = row;
28359
+ if (channel === "email") return r.channel === "email" && !isLegacyPushTemplate(r);
28360
+ return r.channel === "mobile" || isLegacyPushTemplate(r);
28361
+ });
28354
28362
  return json({
28355
- items: rows
28363
+ items
28356
28364
  });
28357
28365
  } catch {
28358
28366
  return json({
@@ -28393,7 +28401,7 @@ function createEmailMessageTemplatesHandlers(config) {
28393
28401
  let suffix = 1;
28394
28402
  while (await templateRepo().findOne({
28395
28403
  where: {
28396
- channel: "email",
28404
+ channel,
28397
28405
  templateKey,
28398
28406
  deleted: false
28399
28407
  }
@@ -28402,7 +28410,7 @@ function createEmailMessageTemplatesHandlers(config) {
28402
28410
  templateKey = `${baseKey}_${suffix}`;
28403
28411
  }
28404
28412
  const row = await templateRepo().save(templateRepo().create({
28405
- channel: "email",
28413
+ channel,
28406
28414
  templateKey,
28407
28415
  name,
28408
28416
  subject,
@@ -28440,7 +28448,6 @@ function createEmailMessageTemplatesHandlers(config) {
28440
28448
  const existing = await templateRepo().findOne({
28441
28449
  where: {
28442
28450
  id: numId,
28443
- channel: "email",
28444
28451
  deleted: false
28445
28452
  }
28446
28453
  });
@@ -28449,9 +28456,25 @@ function createEmailMessageTemplatesHandlers(config) {
28449
28456
  }, {
28450
28457
  status: 404
28451
28458
  });
28459
+ const row = existing;
28460
+ if (channel === "email" && row.channel !== "email") {
28461
+ return json({
28462
+ error: "Template not found"
28463
+ }, {
28464
+ status: 404
28465
+ });
28466
+ }
28467
+ if (channel === "mobile" && row.channel !== "mobile" && !isLegacyPushTemplate(row)) {
28468
+ return json({
28469
+ error: "Template not found"
28470
+ }, {
28471
+ status: 404
28472
+ });
28473
+ }
28452
28474
  const patch = {
28453
28475
  updatedAt: /* @__PURE__ */ new Date()
28454
28476
  };
28477
+ if (channel === "mobile") patch.channel = "mobile";
28455
28478
  if (typeof body.name === "string" && body.name.trim()) patch.name = body.name.trim();
28456
28479
  if (typeof body.subject === "string") patch.subject = body.subject;
28457
28480
  if (typeof body.body === "string") {
@@ -28474,7 +28497,15 @@ function createEmailMessageTemplatesHandlers(config) {
28474
28497
  }
28475
28498
  };
28476
28499
  }
28500
+ __name(createTextMessageTemplatesHandlers, "createTextMessageTemplatesHandlers");
28501
+ function createEmailMessageTemplatesHandlers(config) {
28502
+ return createTextMessageTemplatesHandlers(config, "email");
28503
+ }
28477
28504
  __name(createEmailMessageTemplatesHandlers, "createEmailMessageTemplatesHandlers");
28505
+ function createMobileMessageTemplatesHandlers(config) {
28506
+ return createTextMessageTemplatesHandlers(config, "mobile");
28507
+ }
28508
+ __name(createMobileMessageTemplatesHandlers, "createMobileMessageTemplatesHandlers");
28478
28509
  function connectionFromUrl(redisUrl) {
28479
28510
  const u = new URL(redisUrl);
28480
28511
  return {
@@ -29234,6 +29265,13 @@ function createCmsApiHandler(config) {
29234
29265
  requireAuth: config.requireAuth,
29235
29266
  requireEntityPermission: requireEntityPermissionEffective
29236
29267
  });
29268
+ const mobileMessageTemplatesHandlers = createMobileMessageTemplatesHandlers({
29269
+ dataSource,
29270
+ entityMap,
29271
+ json: config.json,
29272
+ requireAuth: config.requireAuth,
29273
+ requireEntityPermission: requireEntityPermissionEffective
29274
+ });
29237
29275
  const deviceTokensHandlers = createDeviceTokensHandlers({
29238
29276
  dataSource,
29239
29277
  entityMap,
@@ -30268,9 +30306,16 @@ function createCmsApiHandler(config) {
30268
30306
  if (m === "GET") return emailMessageTemplatesHandlers.listCached(req);
30269
30307
  if (m === "POST") return emailMessageTemplatesHandlers.create(req);
30270
30308
  }
30271
- if (isMsgTemplatesRoute && (path2[1] === "email" || path2.length === 2) && path2.length === 3) {
30309
+ if (isMsgTemplatesRoute && path2[1] === "mobile" && path2.length === 2) {
30310
+ if (m === "GET") return mobileMessageTemplatesHandlers.listCached(req);
30311
+ if (m === "POST") return mobileMessageTemplatesHandlers.create(req);
30312
+ }
30313
+ if (isMsgTemplatesRoute && (path2[1] === "email" || path2.length === 2) && path2.length === 3 && path2[1] !== "mobile") {
30272
30314
  if (m === "PATCH") return emailMessageTemplatesHandlers.update(req, path2[2]);
30273
30315
  }
30316
+ if (isMsgTemplatesRoute && path2[1] === "mobile" && path2.length === 3) {
30317
+ if (m === "PATCH") return mobileMessageTemplatesHandlers.update(req, path2[2]);
30318
+ }
30274
30319
  if (path2[0] === "llm_agents") {
30275
30320
  if (!entityMap.llm_agents) {
30276
30321
  console.error(CMS_API_LOG, "llm_agents route: entity missing after merge", {
@@ -30713,7 +30758,7 @@ function createCmsApiHandler(config) {
30713
30758
  status: 400
30714
30759
  });
30715
30760
  }
30716
- const { resendOrderNotification } = await import('./order-notification-dispatcher-ID2PDEXD.js');
30761
+ const { resendOrderNotification } = await import('./order-notification-dispatcher-ECPFI7CD.js');
30717
30762
  const result = await resendOrderNotification(triggerKey, orderId, {
30718
30763
  dataSource,
30719
30764
  entityMap,
@@ -30812,7 +30857,7 @@ function createCmsApiHandler(config) {
30812
30857
  status: "cancelled"
30813
30858
  });
30814
30859
  const fireOrderCancelledNotification = /* @__PURE__ */ __name((refundAmount) => {
30815
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
30860
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
30816
30861
  fireOrderNotificationTrigger("order_cancelled", orderId, {
30817
30862
  dataSource,
30818
30863
  entityMap
@@ -31057,7 +31102,7 @@ function createCmsApiHandler(config) {
31057
31102
  }, {
31058
31103
  status: 400
31059
31104
  });
31060
- const { createOrderCompletionOtpHandlers } = await import('./order-completion-otp-handlers-3W5I3LON.js');
31105
+ const { createOrderCompletionOtpHandlers } = await import('./order-completion-otp-handlers-LFRHXWK4.js');
31061
31106
  const handlers = createOrderCompletionOtpHandlers(dataSource, entityMap, getCms);
31062
31107
  return handlers.getChannels(req, orderId);
31063
31108
  }
@@ -31072,7 +31117,7 @@ function createCmsApiHandler(config) {
31072
31117
  }, {
31073
31118
  status: 400
31074
31119
  });
31075
- const { createOrderCompletionOtpHandlers } = await import('./order-completion-otp-handlers-3W5I3LON.js');
31120
+ const { createOrderCompletionOtpHandlers } = await import('./order-completion-otp-handlers-LFRHXWK4.js');
31076
31121
  const handlers = createOrderCompletionOtpHandlers(dataSource, entityMap, getCms);
31077
31122
  return handlers.sendOtp(req, orderId);
31078
31123
  }
@@ -31087,7 +31132,7 @@ function createCmsApiHandler(config) {
31087
31132
  }, {
31088
31133
  status: 400
31089
31134
  });
31090
- const { createOrderCompletionOtpHandlers } = await import('./order-completion-otp-handlers-3W5I3LON.js');
31135
+ const { createOrderCompletionOtpHandlers } = await import('./order-completion-otp-handlers-LFRHXWK4.js');
31091
31136
  const handlers = createOrderCompletionOtpHandlers(dataSource, entityMap, getCms);
31092
31137
  return handlers.verifyOtp(req, orderId);
31093
31138
  }
@@ -31718,26 +31763,17 @@ function createStorefrontApiHandler(config) {
31718
31763
  const otpFlags = config.otpFlags;
31719
31764
  const otpPepper = config.otpPepper;
31720
31765
  const defaultPhoneCc = config.defaultPhoneCountryCode;
31721
- function fireOrderPlacedNotification(orderId, isPaid) {
31722
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
31723
- fireOrderNotificationTrigger("order_placed", orderId, {
31766
+ function fireStorefrontCheckoutNotifications(orderId) {
31767
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
31768
+ fireOrderNotificationTrigger("order_pending", orderId, {
31724
31769
  dataSource,
31725
31770
  entityMap
31771
+ }, {
31772
+ source: "storefront"
31726
31773
  });
31727
- if (isPaid) {
31728
- fireOrderNotificationTrigger("payment_success", orderId, {
31729
- dataSource,
31730
- entityMap
31731
- });
31732
- } else {
31733
- fireOrderNotificationTrigger("payment_failed", orderId, {
31734
- dataSource,
31735
- entityMap
31736
- });
31737
- }
31738
31774
  }).catch((err) => console.error("[notification-triggers] import failed", err));
31739
31775
  }
31740
- __name(fireOrderPlacedNotification, "fireOrderPlacedNotification");
31776
+ __name(fireStorefrontCheckoutNotifications, "fireStorefrontCheckoutNotifications");
31741
31777
  const otpAllowPhoneLogin = config.otpAllowPhoneLogin !== false;
31742
31778
  function otpOff(key) {
31743
31779
  return !otpFlags || otpFlags[key] !== true;
@@ -34234,6 +34270,7 @@ function createStorefrontApiHandler(config) {
34234
34270
  }));
34235
34271
  }
34236
34272
  await linkOrderContactToVendors(contactId, vendorRes.vendorIds);
34273
+ fireStorefrontCheckoutNotifications(oid);
34237
34274
  return json({
34238
34275
  orderId: oid,
34239
34276
  orderNumber: ord.orderNumber,
@@ -34314,6 +34351,7 @@ function createStorefrontApiHandler(config) {
34314
34351
  cartId: cart.id
34315
34352
  });
34316
34353
  await cartRepo().delete(cart.id);
34354
+ fireStorefrontCheckoutNotifications(oid);
34317
34355
  return json({
34318
34356
  orderId: oid,
34319
34357
  orderNumber: ord.orderNumber,
@@ -34656,14 +34694,18 @@ function createStorefrontApiHandler(config) {
34656
34694
  } catch {
34657
34695
  }
34658
34696
  try {
34659
- void import('./emit-order-notification-trigger-MFCBAE7L.js').then(({ fireOrderNotificationTrigger }) => {
34697
+ void import('./emit-order-notification-trigger-EJJZ6XTS.js').then(({ fireOrderNotificationTrigger }) => {
34660
34698
  fireOrderNotificationTrigger("order_cancelled", orderId, {
34661
34699
  dataSource,
34662
34700
  entityMap
34701
+ }, {
34702
+ source: "storefront"
34663
34703
  });
34664
34704
  fireOrderNotificationTrigger("payment_failed", orderId, {
34665
34705
  dataSource,
34666
34706
  entityMap
34707
+ }, {
34708
+ source: "storefront"
34667
34709
  });
34668
34710
  }).catch(() => {
34669
34711
  });
@@ -0,0 +1,101 @@
1
+ 'use strict';
2
+
3
+ var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
4
+
5
+ // src/plugins/pg-boss/pg-boss-service.ts
6
+ var JOB_RUNNER_QUEUE = "job-runner";
7
+ var PgBossService = class {
8
+ static {
9
+ chunkUSNT2KNT_cjs.__name(this, "PgBossService");
10
+ }
11
+ connectionString;
12
+ schema;
13
+ boss = null;
14
+ bossPromise = null;
15
+ started = false;
16
+ workRegistered = /* @__PURE__ */ new Set();
17
+ constructor(connectionString, schema) {
18
+ this.connectionString = connectionString;
19
+ this.schema = schema?.trim() ? schema.trim() : void 0;
20
+ }
21
+ async getBoss() {
22
+ if (this.boss) return this.boss;
23
+ if (this.bossPromise) return this.bossPromise;
24
+ this.bossPromise = (async () => {
25
+ const mod = await import('pg-boss');
26
+ const PgBossClass = mod?.PgBoss ?? mod?.default ?? mod;
27
+ const instance = new PgBossClass({
28
+ connectionString: this.connectionString,
29
+ ...this.schema ? {
30
+ schema: this.schema
31
+ } : {},
32
+ schedule: true
33
+ });
34
+ instance.on("error", (err) => {
35
+ console.error("[pg-boss]", err);
36
+ });
37
+ this.boss = instance;
38
+ return instance;
39
+ })();
40
+ return this.bossPromise;
41
+ }
42
+ async start() {
43
+ if (this.started) return;
44
+ const boss = await this.getBoss();
45
+ await boss.start();
46
+ await this.ensureQueue(JOB_RUNNER_QUEUE);
47
+ this.started = true;
48
+ }
49
+ async stop() {
50
+ if (!this.started || !this.boss) return;
51
+ await this.boss.stop({
52
+ graceful: true,
53
+ timeout: 1e4
54
+ });
55
+ this.started = false;
56
+ this.workRegistered.clear();
57
+ }
58
+ get raw() {
59
+ return this.boss;
60
+ }
61
+ async ensureQueue(name) {
62
+ const boss = await this.getBoss();
63
+ const existing = await boss.getQueue(name);
64
+ if (!existing) {
65
+ await boss.createQueue(name);
66
+ }
67
+ }
68
+ async send(queue, data) {
69
+ await this.ensureQueue(queue);
70
+ const boss = await this.getBoss();
71
+ return boss.send(queue, data, {
72
+ retryLimit: 2
73
+ });
74
+ }
75
+ async schedule(name, cron, data, options) {
76
+ await this.ensureQueue(name);
77
+ const boss = await this.getBoss();
78
+ await boss.schedule(name, cron, data, options);
79
+ }
80
+ async unschedule(name) {
81
+ try {
82
+ const boss = await this.getBoss();
83
+ await boss.unschedule(name);
84
+ } catch {
85
+ }
86
+ }
87
+ async registerWork(queue, handler) {
88
+ if (this.workRegistered.has(queue)) return;
89
+ await this.ensureQueue(queue);
90
+ const boss = await this.getBoss();
91
+ await boss.work(queue, async (jobs) => {
92
+ for (const job of jobs) {
93
+ await handler(job.data);
94
+ }
95
+ });
96
+ this.workRegistered.add(queue);
97
+ }
98
+ };
99
+
100
+ exports.JOB_RUNNER_QUEUE = JOB_RUNNER_QUEUE;
101
+ exports.PgBossService = PgBossService;
@@ -1,26 +1,23 @@
1
1
  'use strict';
2
2
 
3
- var chunkUEE4PTTB_cjs = require('./chunk-UEE4PTTB.cjs');
3
+ var chunkPA6YDMFZ_cjs = require('./chunk-PA6YDMFZ.cjs');
4
4
  var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
5
5
 
6
6
  // src/lib/emit-order-notification-trigger.ts
7
- function maskPhone(raw) {
8
- const digits = String(raw ?? "").replace(/\D/g, "");
9
- if (digits.length <= 4) return "(none)";
10
- return `***${digits.slice(-4)}`;
11
- }
12
- chunkUSNT2KNT_cjs.__name(maskPhone, "maskPhone");
13
7
  async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
14
8
  if (!deps.entityMap.orders) {
15
- console.warn("[notification-triggers] skip emit: orders entity missing from entityMap", {
9
+ chunkPA6YDMFZ_cjs.notifyLog.skip("TRIGGER", "orders entity missing from entityMap", {
16
10
  triggerKey,
17
11
  orderId
18
12
  });
19
13
  return;
20
14
  }
21
- const listenerCount = chunkUEE4PTTB_cjs.notificationTriggerEmitter.listenerCount("__any__");
15
+ const listenerCount = chunkPA6YDMFZ_cjs.notificationTriggerEmitter.listenerCount("__any__");
22
16
  if (listenerCount === 0) {
23
- console.warn("[notification-triggers] no WhatsApp dispatcher listener \u2014 ensure createCmsApiHandler passes getCms (initWhatsappTriggerDispatcher)");
17
+ chunkPA6YDMFZ_cjs.notifyLog.skip("TRIGGER", "no dispatcher listener \u2014 will try direct dispatch (pass getCms to createCmsApiHandler)", {
18
+ triggerKey,
19
+ orderId
20
+ });
24
21
  }
25
22
  const orderRepo = deps.dataSource.getRepository(deps.entityMap.orders);
26
23
  const fullOrder = await orderRepo.findOne({
@@ -33,7 +30,7 @@ async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
33
30
  ]
34
31
  });
35
32
  if (!fullOrder) {
36
- console.warn("[notification-triggers] skip emit: order not found", {
33
+ chunkPA6YDMFZ_cjs.notifyLog.skip("TRIGGER", "order not found", {
37
34
  triggerKey,
38
35
  orderId
39
36
  });
@@ -41,15 +38,18 @@ async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
41
38
  }
42
39
  const fo = fullOrder;
43
40
  const phone = fo.contact?.phone ?? null;
44
- console.log("[notification-triggers] emit", {
41
+ chunkPA6YDMFZ_cjs.notifyLog.trigger("emit", {
45
42
  triggerKey,
46
43
  orderId,
47
44
  orderNumber: fo.orderNumber ?? null,
48
- phone: maskPhone(phone),
49
- listeners: listenerCount
45
+ phone: chunkPA6YDMFZ_cjs.maskNotifyPhone(phone),
46
+ listeners: listenerCount,
47
+ vendorId: fo.vendorId ?? null,
48
+ source: extra?.source ?? "api"
50
49
  });
51
50
  if (!phone?.trim()) {
52
- console.warn("[notification-triggers] order contact has no phone \u2014 WhatsApp will be skipped", {
51
+ chunkPA6YDMFZ_cjs.notifyLog.skip("WHATSAPP", "order contact has no phone", {
52
+ triggerKey,
53
53
  orderId
54
54
  });
55
55
  }
@@ -91,28 +91,44 @@ async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
91
91
  refundAmount: resolvedRefundAmount
92
92
  };
93
93
  if (listenerCount === 0) {
94
+ chunkPA6YDMFZ_cjs.notifyLog.trigger("direct dispatch (no in-process listener)", {
95
+ triggerKey,
96
+ orderId
97
+ });
94
98
  try {
95
- const { dispatchOrderNotificationDirectly } = await import('./order-notification-dispatcher-RNEQB3V7.cjs');
99
+ const { dispatchOrderNotificationDirectly } = await import('./order-notification-dispatcher-LL7ETKLU.cjs');
96
100
  await dispatchOrderNotificationDirectly(triggerKey, triggerPayload, deps.dataSource, deps.entityMap);
97
101
  } catch (err) {
98
- console.error("[notification-triggers] direct dispatch failed", {
102
+ chunkPA6YDMFZ_cjs.notifyLog.error("TRIGGER", "direct dispatch failed", {
99
103
  triggerKey,
100
104
  orderId,
101
- err
105
+ error: err instanceof Error ? err.message : String(err),
106
+ stack: err instanceof Error ? err.stack : void 0
102
107
  });
103
108
  }
104
109
  } else {
105
- chunkUEE4PTTB_cjs.notificationTriggerEmitter.emitTrigger(triggerKey, triggerPayload);
110
+ chunkPA6YDMFZ_cjs.notifyLog.trigger("emit to dispatcher listener", {
111
+ triggerKey,
112
+ orderId,
113
+ listeners: listenerCount
114
+ });
115
+ chunkPA6YDMFZ_cjs.notificationTriggerEmitter.emitTrigger(triggerKey, triggerPayload);
106
116
  }
107
117
  }
108
118
  chunkUSNT2KNT_cjs.__name(emitOrderNotificationTrigger, "emitOrderNotificationTrigger");
109
119
  function fireOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
110
- console.log("[notification-triggers] fire", {
120
+ chunkPA6YDMFZ_cjs.notifyLog.trigger("FIRE", {
111
121
  triggerKey,
112
- orderId
122
+ orderId,
123
+ source: extra?.source ?? "api"
113
124
  });
114
125
  void emitOrderNotificationTrigger(triggerKey, orderId, deps, extra).catch((err) => {
115
- console.error("[notification-triggers]", triggerKey, orderId, err);
126
+ chunkPA6YDMFZ_cjs.notifyLog.error("TRIGGER", "fire failed", {
127
+ triggerKey,
128
+ orderId,
129
+ error: err instanceof Error ? err.message : String(err),
130
+ stack: err instanceof Error ? err.stack : void 0
131
+ });
116
132
  });
117
133
  }
118
134
  chunkUSNT2KNT_cjs.__name(fireOrderNotificationTrigger, "fireOrderNotificationTrigger");