@infuro/cms-core 1.0.47 → 1.0.51

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 (40) hide show
  1. package/README.md +30 -16
  2. package/dist/admin.cjs +2012 -437
  3. package/dist/admin.d.cts +13 -1
  4. package/dist/admin.d.ts +13 -1
  5. package/dist/admin.js +2013 -438
  6. package/dist/api.cjs +37 -37
  7. package/dist/api.js +5 -5
  8. package/dist/auth.cjs +52 -23
  9. package/dist/auth.d.cts +101 -2
  10. package/dist/auth.d.ts +101 -2
  11. package/dist/auth.js +3 -2
  12. package/dist/chunk-3EOM4V2M.cjs +452 -0
  13. package/dist/{chunk-2HU5R2JE.js → chunk-AYERBA7I.js} +1 -7
  14. package/dist/{chunk-YXH2UUEZ.js → chunk-CTXBYO2J.js} +290 -59
  15. package/dist/{chunk-LMJ7RKPF.cjs → chunk-JN4AFHZ4.cjs} +311 -59
  16. package/dist/{chunk-JE22VP6S.js → chunk-MXIWUFBP.js} +1 -1
  17. package/dist/{chunk-W42UZLQO.js → chunk-NUXR7BUG.js} +2819 -2597
  18. package/dist/chunk-RK5ETF2I.js +434 -0
  19. package/dist/{chunk-4PMK3RNA.cjs → chunk-TJ2MIQUT.cjs} +1 -7
  20. package/dist/{chunk-KOTXDSQB.cjs → chunk-UQWZUZ5X.cjs} +1 -1
  21. package/dist/{chunk-YC4NUZCS.js → chunk-WRKV6MHB.js} +414 -2
  22. package/dist/{chunk-XUCKZPML.cjs → chunk-YOW457RA.cjs} +2872 -2657
  23. package/dist/{chunk-Q3HQEM4R.cjs → chunk-YV5PK4JW.cjs} +421 -1
  24. package/dist/cli.cjs +13 -22
  25. package/dist/cli.js +13 -22
  26. package/dist/{emit-order-notification-trigger-6XX7LSC4.js → emit-order-notification-trigger-HZQPPSFB.js} +1 -1
  27. package/dist/{emit-order-notification-trigger-NASG7ZEO.cjs → emit-order-notification-trigger-NR3VN6C6.cjs} +3 -3
  28. package/dist/{event-order-defaults-7Z3UZOEH.cjs → event-order-defaults-DU7V3YND.cjs} +9 -9
  29. package/dist/{event-order-defaults-XQ3IDPD7.js → event-order-defaults-H4RT7NMR.js} +1 -1
  30. package/dist/index.cjs +379 -309
  31. package/dist/index.d.cts +136 -6
  32. package/dist/index.d.ts +136 -6
  33. package/dist/index.js +58 -24
  34. package/dist/migrations/1782400000000-CreateUserDeviceTokens.ts +36 -0
  35. package/dist/migrations/1782500000000-AddPushToOrderNotificationBindingsChannelEnum.ts +15 -0
  36. package/dist/{order-notification-dispatcher-6WNG24NY.js → order-notification-dispatcher-AT4IFAGL.js} +1 -1
  37. package/dist/{order-notification-dispatcher-6XSU3AR7.cjs → order-notification-dispatcher-YBAWDOIO.cjs} +7 -3
  38. package/package.json +1 -1
  39. package/dist/chunk-VUQFARRT.cjs +0 -182
  40. package/dist/chunk-ZF2RQWXB.js +0 -171
@@ -8,11 +8,31 @@ var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
8
8
  var clientSes = require('@aws-sdk/client-ses');
9
9
  var module$1 = require('module');
10
10
  var nodemailer = require('nodemailer');
11
+ var crypto = require('crypto');
11
12
 
12
13
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
13
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
14
15
 
16
+ function _interopNamespace(e) {
17
+ if (e && e.__esModule) return e;
18
+ var n = Object.create(null);
19
+ if (e) {
20
+ Object.keys(e).forEach(function (k) {
21
+ if (k !== 'default') {
22
+ var d = Object.getOwnPropertyDescriptor(e, k);
23
+ Object.defineProperty(n, k, d.get ? d : {
24
+ enumerable: true,
25
+ get: function () { return e[k]; }
26
+ });
27
+ }
28
+ });
29
+ }
30
+ n.default = e;
31
+ return Object.freeze(n);
32
+ }
33
+
15
34
  var nodemailer__default = /*#__PURE__*/_interopDefault(nodemailer);
35
+ var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
16
36
 
17
37
  // src/lib/event-order-template-context.ts
18
38
  function resolvePublicSiteUrl() {
@@ -33,12 +53,6 @@ function buildOrderTrackUrl(qrToken, siteUrl, orderNumber) {
33
53
  return `${base}/track/${token}`;
34
54
  }
35
55
  chunkUSNT2KNT_cjs.__name(buildOrderTrackUrl, "buildOrderTrackUrl");
36
- function buildOrderQrImageUrl(trackUrl, size = 200, fallbackData) {
37
- const data = trackUrl.trim() || fallbackData?.trim() || "";
38
- if (!data) return "";
39
- return `https://api.qrserver.com/v1/create-qr-code/?size=${size}x${size}&data=${encodeURIComponent(data)}`;
40
- }
41
- chunkUSNT2KNT_cjs.__name(buildOrderQrImageUrl, "buildOrderQrImageUrl");
42
56
  function formatOrderDetailsText(input) {
43
57
  const { orderNumber, total, currency, lines } = input;
44
58
  const header = `Order: ${orderNumber}
@@ -60,8 +74,6 @@ chunkUSNT2KNT_cjs.__name(formatOrderDetailsHtml, "formatOrderDetailsHtml");
60
74
  function buildEventOrderTemplateVariables(input) {
61
75
  const { event, order, contact, productNames, vendorName = "", orderLines = [], siteUrl } = input;
62
76
  const trackUrl = buildOrderTrackUrl(order.qrToken, siteUrl, order.orderNumber);
63
- const qrImageUrl = buildOrderQrImageUrl(trackUrl, 200, order.orderNumber);
64
- const ticketQr = qrImageUrl ? `<img src="${qrImageUrl}" alt="Ticket QR Code" width="200" height="200" style="display:block;margin:12px 0;border:1px solid #e5e7eb;border-radius:8px;" />` : "";
65
77
  const baseSite = (siteUrl ?? resolvePublicSiteUrl()).replace(/\/+$/, "");
66
78
  const invoiceNumber = `INV-${order.orderNumber ?? ""}`;
67
79
  const invoiceUrl = baseSite ? `${baseSite}/api/orders/${order.orderNumber ?? ""}/invoice` : `/api/orders/${order.orderNumber ?? ""}/invoice`;
@@ -71,6 +83,9 @@ function buildEventOrderTemplateVariables(input) {
71
83
  currency: String(order.currency ?? "INR"),
72
84
  lines: orderLines
73
85
  };
86
+ const qrToken = order.qrToken?.trim() || order.orderNumber?.trim() || "";
87
+ const fallbackQrUrl = qrToken ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrToken)}` : "";
88
+ const fallbackTicketQr = fallbackQrUrl ? `<img src="${fallbackQrUrl}" alt="Ticket QR Code" width="200" height="200" style="display:block;margin:12px 0;border:1px solid #e5e7eb;border-radius:8px;" />` : "";
74
89
  return {
75
90
  eventName: event.name ?? productNames ?? "",
76
91
  vendorName: vendorName.trim(),
@@ -85,10 +100,10 @@ function buildEventOrderTemplateVariables(input) {
85
100
  customerPhone: contact.phone?.trim() || "",
86
101
  productNames,
87
102
  trackUrl,
88
- qrImageUrl,
89
- ticketQr,
90
103
  invoiceNumber,
91
104
  invoiceUrl,
105
+ ticketQr: fallbackTicketQr,
106
+ qrImageUrl: fallbackQrUrl,
92
107
  orderDetails: formatOrderDetailsText(orderDetailsPayload),
93
108
  orderDetailsHtml: formatOrderDetailsHtml(orderDetailsPayload)
94
109
  };
@@ -504,7 +519,7 @@ var WhatsAppService = class {
504
519
  let body = opts.body?.trim() ?? "";
505
520
  const variables = opts.variables ?? {};
506
521
  if (opts.templateKey?.trim() && this.getMessageTemplateRow) {
507
- const { resolveEventOrderTemplate, EVENT_ORDER_TEMPLATE_KEY } = await import('./event-order-defaults-7Z3UZOEH.cjs');
522
+ const { resolveEventOrderTemplate, EVENT_ORDER_TEMPLATE_KEY } = await import('./event-order-defaults-DU7V3YND.cjs');
508
523
  if (opts.templateKey.trim() === EVENT_ORDER_TEMPLATE_KEY) {
509
524
  const resolved = await resolveEventOrderTemplate("whatsapp", async (ch, key) => {
510
525
  const row = await this.getMessageTemplateRow(ch, key);
@@ -1316,7 +1331,7 @@ function renderEmail(templateName, ctx, options) {
1316
1331
  chunkUSNT2KNT_cjs.__name(renderEmail, "renderEmail");
1317
1332
 
1318
1333
  // src/plugins/email/email-service.ts
1319
- var require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-LMJ7RKPF.cjs', document.baseURI).href)));
1334
+ var require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-JN4AFHZ4.cjs', document.baseURI).href)));
1320
1335
  var MailComposer = require2("nodemailer/lib/mail-composer");
1321
1336
  var SES_REGIONS_WITHOUT_SMTP = /* @__PURE__ */ new Set([
1322
1337
  "af-south-1",
@@ -2068,6 +2083,117 @@ function emailPlugin(config) {
2068
2083
  };
2069
2084
  }
2070
2085
  chunkUSNT2KNT_cjs.__name(emailPlugin, "emailPlugin");
2086
+ function base64UrlEncode(str) {
2087
+ const buf = typeof str === "string" ? Buffer.from(str, "utf8") : str;
2088
+ return buf.toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
2089
+ }
2090
+ chunkUSNT2KNT_cjs.__name(base64UrlEncode, "base64UrlEncode");
2091
+ async function getGoogleAccessToken(clientEmail, privateKey) {
2092
+ const now = Math.floor(Date.now() / 1e3);
2093
+ const header = {
2094
+ alg: "RS256",
2095
+ typ: "JWT"
2096
+ };
2097
+ const claimSet = {
2098
+ iss: clientEmail,
2099
+ scope: "https://www.googleapis.com/auth/firebase.messaging",
2100
+ aud: "https://oauth2.googleapis.com/token",
2101
+ exp: now + 3600,
2102
+ iat: now
2103
+ };
2104
+ const encodedHeader = base64UrlEncode(JSON.stringify(header));
2105
+ const encodedClaimSet = base64UrlEncode(JSON.stringify(claimSet));
2106
+ const signatureInput = `${encodedHeader}.${encodedClaimSet}`;
2107
+ const formattedKey = privateKey.replace(/\\n/g, "\n");
2108
+ const signer = crypto__namespace.createSign("RSA-SHA256");
2109
+ signer.update(signatureInput);
2110
+ const signature = signer.sign(formattedKey, "base64");
2111
+ const jwt = `${signatureInput}.${signature.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_")}`;
2112
+ const tokenRes = await fetch("https://oauth2.googleapis.com/token", {
2113
+ method: "POST",
2114
+ headers: {
2115
+ "Content-Type": "application/x-www-form-urlencoded"
2116
+ },
2117
+ body: new URLSearchParams({
2118
+ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
2119
+ assertion: jwt
2120
+ }).toString()
2121
+ });
2122
+ if (!tokenRes.ok) {
2123
+ const errText = await tokenRes.text();
2124
+ throw new Error(`Failed to obtain Google access token: ${errText}`);
2125
+ }
2126
+ const tokenData = await tokenRes.json();
2127
+ if (!tokenData.access_token) {
2128
+ throw new Error("Google OAuth token response missing access_token");
2129
+ }
2130
+ return tokenData.access_token;
2131
+ }
2132
+ chunkUSNT2KNT_cjs.__name(getGoogleAccessToken, "getGoogleAccessToken");
2133
+ async function sendFcmPushNotification(dataSource, entityMap, msg) {
2134
+ try {
2135
+ const pushSettings = await getSettingsGroup(dataSource, entityMap, "push");
2136
+ let projectId = pushSettings.firebase_project_id?.trim();
2137
+ let clientEmail = pushSettings.firebase_client_email?.trim();
2138
+ let privateKey = pushSettings.firebase_private_key?.trim();
2139
+ if (pushSettings.firebase_service_account_json?.trim()) {
2140
+ try {
2141
+ const parsed = JSON.parse(pushSettings.firebase_service_account_json.trim());
2142
+ if (parsed.project_id) projectId = parsed.project_id;
2143
+ if (parsed.client_email) clientEmail = parsed.client_email;
2144
+ if (parsed.private_key) privateKey = parsed.private_key;
2145
+ } catch {
2146
+ }
2147
+ }
2148
+ if (!projectId || !clientEmail || !privateKey) {
2149
+ return {
2150
+ success: false,
2151
+ error: "Firebase Service Account JSON / credentials are not configured"
2152
+ };
2153
+ }
2154
+ const accessToken = await getGoogleAccessToken(clientEmail, privateKey);
2155
+ const fcmEndpoint = `https://fcm.googleapis.com/v1/projects/${projectId}/messages:send`;
2156
+ const fcmPayload = {
2157
+ message: {
2158
+ token: msg.token,
2159
+ notification: {
2160
+ title: msg.title,
2161
+ body: msg.body
2162
+ },
2163
+ data: msg.data || {}
2164
+ }
2165
+ };
2166
+ const response = await fetch(fcmEndpoint, {
2167
+ method: "POST",
2168
+ headers: {
2169
+ "Authorization": `Bearer ${accessToken}`,
2170
+ "Content-Type": "application/json"
2171
+ },
2172
+ body: JSON.stringify(fcmPayload)
2173
+ });
2174
+ const resData = await response.json();
2175
+ if (!response.ok) {
2176
+ const errorMsg = resData.error?.message || "FCM request failed";
2177
+ console.error("[fcm-push] Error sending push notification", errorMsg);
2178
+ return {
2179
+ success: false,
2180
+ error: errorMsg
2181
+ };
2182
+ }
2183
+ return {
2184
+ success: true,
2185
+ messageId: resData.name
2186
+ };
2187
+ } catch (err) {
2188
+ const errorMsg = err instanceof Error ? err.message : "Unknown push error";
2189
+ console.error("[fcm-push] Exception in sendFcmPushNotification", errorMsg);
2190
+ return {
2191
+ success: false,
2192
+ error: errorMsg
2193
+ };
2194
+ }
2195
+ }
2196
+ chunkUSNT2KNT_cjs.__name(sendFcmPushNotification, "sendFcmPushNotification");
2071
2197
 
2072
2198
  // src/lib/order-notification-dispatcher.ts
2073
2199
  var initialized = false;
@@ -2135,59 +2261,69 @@ async function loadBoundTemplate(triggerKey, channel, audienceType = "customers"
2135
2261
  console.warn("[order-notifications] order_notification_bindings or message_templates missing from entityMap");
2136
2262
  return null;
2137
2263
  }
2138
- const bindingRepo = dataSource.getRepository(entityMap.order_notification_bindings);
2139
- let binding = await bindingRepo.findOne({
2140
- where: {
2141
- triggerKey,
2142
- channel,
2143
- type: audienceType,
2144
- enabled: true
2145
- }
2146
- });
2147
- if (!binding && audienceType === "customers") {
2148
- binding = await bindingRepo.findOne({
2264
+ try {
2265
+ const bindingRepo = dataSource.getRepository(entityMap.order_notification_bindings);
2266
+ let binding = await bindingRepo.findOne({
2149
2267
  where: {
2150
2268
  triggerKey,
2151
2269
  channel,
2270
+ type: audienceType,
2152
2271
  enabled: true
2153
2272
  }
2154
- });
2155
- }
2156
- if (!binding) {
2157
- console.warn("[order-notifications] no order_notification_bindings row", {
2158
- triggerKey,
2159
- channel,
2160
- audienceType
2161
- });
2162
- return null;
2163
- }
2164
- const templateId = binding.messageTemplateId;
2165
- if (templateId == null) {
2166
- console.warn("[order-notifications] binding exists but no template selected", {
2167
- triggerKey,
2168
- channel,
2169
- audienceType
2170
- });
2171
- return null;
2172
- }
2173
- const template = await dataSource.getRepository(entityMap.message_templates).findOne({
2174
- where: {
2175
- id: templateId,
2176
- channel,
2177
- deleted: false,
2178
- enabled: true
2273
+ }).catch(() => null);
2274
+ if (!binding && audienceType === "customers") {
2275
+ binding = await bindingRepo.findOne({
2276
+ where: {
2277
+ triggerKey,
2278
+ channel,
2279
+ enabled: true
2280
+ }
2281
+ }).catch(() => null);
2179
2282
  }
2180
- });
2181
- if (!template) {
2182
- console.warn("[order-notifications] bound template not found or disabled", {
2283
+ if (!binding) {
2284
+ console.warn("[order-notifications] no order_notification_bindings row", {
2285
+ triggerKey,
2286
+ channel,
2287
+ audienceType
2288
+ });
2289
+ return null;
2290
+ }
2291
+ const templateId = binding.messageTemplateId;
2292
+ if (templateId == null) {
2293
+ console.warn("[order-notifications] binding exists but no template selected", {
2294
+ triggerKey,
2295
+ channel,
2296
+ audienceType
2297
+ });
2298
+ return null;
2299
+ }
2300
+ const template = await dataSource.getRepository(entityMap.message_templates).findOne({
2301
+ where: {
2302
+ id: templateId,
2303
+ channel,
2304
+ deleted: false,
2305
+ enabled: true
2306
+ }
2307
+ }).catch(() => null);
2308
+ if (!template) {
2309
+ console.warn("[order-notifications] bound template not found or disabled", {
2310
+ triggerKey,
2311
+ channel,
2312
+ audienceType,
2313
+ templateId
2314
+ });
2315
+ return null;
2316
+ }
2317
+ return template;
2318
+ } catch (err) {
2319
+ console.warn("[order-notifications] loadBoundTemplate query failed", {
2183
2320
  triggerKey,
2184
2321
  channel,
2185
2322
  audienceType,
2186
- templateId
2323
+ error: err instanceof Error ? err.message : String(err)
2187
2324
  });
2188
2325
  return null;
2189
2326
  }
2190
- return template;
2191
2327
  }
2192
2328
  chunkUSNT2KNT_cjs.__name(loadBoundTemplate, "loadBoundTemplate");
2193
2329
  function mergeTriggerVariables(payload, rich) {
@@ -2204,9 +2340,11 @@ function mergeTriggerVariables(payload, rich) {
2204
2340
  refundAmount: String(payload.refundAmount)
2205
2341
  } : {}
2206
2342
  };
2343
+ const extraVars = payload.extraVariables ?? {};
2207
2344
  return {
2208
2345
  ...basic,
2209
- ...rich ?? {}
2346
+ ...rich ?? {},
2347
+ ...extraVars
2210
2348
  };
2211
2349
  }
2212
2350
  chunkUSNT2KNT_cjs.__name(mergeTriggerVariables, "mergeTriggerVariables");
@@ -2218,6 +2356,82 @@ async function isAudienceEmailEnabled(dataSource, entityMap, audience) {
2218
2356
  return settings[key] !== "false" && settings[key] !== "0";
2219
2357
  }
2220
2358
  chunkUSNT2KNT_cjs.__name(isAudienceEmailEnabled, "isAudienceEmailEnabled");
2359
+ async function isPushNotificationsEnabled(dataSource, entityMap) {
2360
+ const settings = await getSettingsGroup(dataSource, entityMap, "event_notifications");
2361
+ if (settings.enabled === "false" || settings.enabled === "0") return false;
2362
+ return settings.push_enabled !== "false" && settings.push_enabled !== "0";
2363
+ }
2364
+ chunkUSNT2KNT_cjs.__name(isPushNotificationsEnabled, "isPushNotificationsEnabled");
2365
+ async function isAudiencePushEnabled(dataSource, entityMap, audience) {
2366
+ const settings = await getSettingsGroup(dataSource, entityMap, "event_notifications");
2367
+ if (settings.enabled === "false" || settings.enabled === "0") return false;
2368
+ if (settings.push_enabled === "false" || settings.push_enabled === "0") return false;
2369
+ const key = `push_${audience}_enabled`;
2370
+ return settings[key] !== "false" && settings[key] !== "0";
2371
+ }
2372
+ chunkUSNT2KNT_cjs.__name(isAudiencePushEnabled, "isAudiencePushEnabled");
2373
+ async function sendPushNotificationForTrigger(triggerKey, orderId, audienceType, targetId, variables, dataSource, entityMap) {
2374
+ let template = await loadBoundTemplate(triggerKey, "mobile", audienceType, dataSource, entityMap);
2375
+ if (!template) {
2376
+ template = await loadBoundTemplate(triggerKey, "push", audienceType, dataSource, entityMap);
2377
+ }
2378
+ if (!template || !template.body) return;
2379
+ const rawTitle = template.subject?.trim() || "Order Notification";
2380
+ const title = chunkOOTLNH63_cjs.applyTemplateVars(rawTitle, variables);
2381
+ const body = chunkOOTLNH63_cjs.applyTemplateVars(template.body, variables);
2382
+ if (!entityMap.user_device_tokens) return;
2383
+ const tokenRepo = dataSource.getRepository(entityMap.user_device_tokens);
2384
+ let targetTokens = [];
2385
+ try {
2386
+ if (audienceType === "customers") {
2387
+ targetTokens = await tokenRepo.find({
2388
+ where: {
2389
+ userId: targetId,
2390
+ isActive: true
2391
+ },
2392
+ select: [
2393
+ "token"
2394
+ ]
2395
+ });
2396
+ } else if (audienceType === "vendors") {
2397
+ targetTokens = await tokenRepo.find({
2398
+ where: {
2399
+ vendorId: targetId,
2400
+ isActive: true
2401
+ },
2402
+ select: [
2403
+ "token"
2404
+ ]
2405
+ });
2406
+ } else if (audienceType === "admin") {
2407
+ targetTokens = await tokenRepo.find({
2408
+ where: {
2409
+ isActive: true
2410
+ },
2411
+ select: [
2412
+ "token"
2413
+ ]
2414
+ });
2415
+ }
2416
+ } catch (err) {
2417
+ console.error("[order-notifications] Error querying device tokens for push", err);
2418
+ return;
2419
+ }
2420
+ for (const t of targetTokens) {
2421
+ if (t.token?.trim()) {
2422
+ await sendFcmPushNotification(dataSource, entityMap, {
2423
+ token: t.token.trim(),
2424
+ title,
2425
+ body,
2426
+ data: {
2427
+ orderId: String(orderId),
2428
+ triggerKey
2429
+ }
2430
+ });
2431
+ }
2432
+ }
2433
+ }
2434
+ chunkUSNT2KNT_cjs.__name(sendPushNotificationForTrigger, "sendPushNotificationForTrigger");
2221
2435
  async function getOrderVendorEmails(orderId, orderVendorId, dataSource, entityMap) {
2222
2436
  const emails = /* @__PURE__ */ new Set();
2223
2437
  if (!entityMap.vendors) return [];
@@ -2326,7 +2540,23 @@ async function getAdminRecipientEmails(dataSource, entityMap) {
2326
2540
  }
2327
2541
  } catch {
2328
2542
  }
2329
- return Array.from(emails);
2543
+ const vendorEmails = /* @__PURE__ */ new Set();
2544
+ try {
2545
+ const vRows = await dataSource.query(`SELECT DISTINCT LOWER(TRIM(email)) AS email FROM vendors WHERE COALESCE(deleted, false) = false AND email IS NOT NULL AND TRIM(email) != ''`).catch(() => []);
2546
+ for (const r of vRows) {
2547
+ if (r.email) vendorEmails.add(r.email.toLowerCase());
2548
+ }
2549
+ const vuRows = await dataSource.query(`SELECT DISTINCT LOWER(TRIM(u.email)) AS email
2550
+ FROM users u
2551
+ LEFT JOIN user_groups g ON g.id = u."groupId"
2552
+ WHERE COALESCE(u.deleted, false) = false
2553
+ AND (LOWER(g.name) LIKE '%vendor%' OR u."groupId" = 5)`).catch(() => []);
2554
+ for (const r of vuRows) {
2555
+ if (r.email) vendorEmails.add(r.email.toLowerCase());
2556
+ }
2557
+ } catch {
2558
+ }
2559
+ return Array.from(emails).filter((e) => !vendorEmails.has(e.toLowerCase()));
2330
2560
  }
2331
2561
  chunkUSNT2KNT_cjs.__name(getAdminRecipientEmails, "getAdminRecipientEmails");
2332
2562
  function formatBodyForEmailHtml(body) {
@@ -2480,12 +2710,13 @@ async function handleTrigger(triggerKey, payload, dataSource, entityMap, getCms)
2480
2710
  return;
2481
2711
  }
2482
2712
  }
2483
- const [emailChannelEnabled, whatsappChannelEnabled] = await Promise.all([
2713
+ const [emailChannelEnabled, whatsappChannelEnabled, pushChannelEnabled] = await Promise.all([
2484
2714
  isEmailNotificationsEnabled(dataSource, entityMap),
2485
- isWhatsappNotificationsEnabled(dataSource, entityMap)
2715
+ isWhatsappNotificationsEnabled(dataSource, entityMap),
2716
+ isPushNotificationsEnabled(dataSource, entityMap)
2486
2717
  ]);
2487
- if (!emailChannelEnabled && !whatsappChannelEnabled) {
2488
- console.warn("[order-notifications] skip: Both Email and WhatsApp notifications are disabled");
2718
+ if (!emailChannelEnabled && !whatsappChannelEnabled && !pushChannelEnabled) {
2719
+ console.warn("[order-notifications] skip: Email, WhatsApp, and Mobile Push notifications are disabled");
2489
2720
  return;
2490
2721
  }
2491
2722
  const triggerEnabled = await isTriggerCatalogEnabled(triggerKey, dataSource, entityMap);
@@ -2524,6 +2755,23 @@ async function handleTrigger(triggerKey, payload, dataSource, entityMap, getCms)
2524
2755
  } else {
2525
2756
  console.log("[order-notifications] skip email: Email notifications channel is disabled");
2526
2757
  }
2758
+ if (pushChannelEnabled) {
2759
+ const [pushCustomerEnabled, pushVendorEnabled, pushAdminEnabled] = await Promise.all([
2760
+ isAudiencePushEnabled(dataSource, entityMap, "customer"),
2761
+ isAudiencePushEnabled(dataSource, entityMap, "vendor"),
2762
+ isAudiencePushEnabled(dataSource, entityMap, "admin")
2763
+ ]);
2764
+ const targetCustomerId = context?.order?.customerContactId || context?.order?.contactId || context?.order?.userId || context?.order?.id;
2765
+ if (pushCustomerEnabled && targetCustomerId) {
2766
+ await sendPushNotificationForTrigger(triggerKey, payload.orderId, "customers", String(targetCustomerId), variables, dataSource, entityMap);
2767
+ }
2768
+ if (pushVendorEnabled && payload.vendorId) {
2769
+ await sendPushNotificationForTrigger(triggerKey, payload.orderId, "vendors", String(payload.vendorId), variables, dataSource, entityMap);
2770
+ }
2771
+ if (pushAdminEnabled) {
2772
+ await sendPushNotificationForTrigger(triggerKey, payload.orderId, "admin", "admin", variables, dataSource, entityMap);
2773
+ }
2774
+ }
2527
2775
  if (whatsappChannelEnabled) {
2528
2776
  if (contactPhone) {
2529
2777
  await sendWhatsAppForTrigger(triggerKey, payload.orderId, contactPhone, variables, dataSource, entityMap, getCms);
@@ -2542,6 +2790,8 @@ function initWhatsappTriggerDispatcher(deps) {
2542
2790
  if (initialized) return;
2543
2791
  initialized = true;
2544
2792
  const { dataSource, entityMap, getCms } = deps;
2793
+ void dataSource.query(`ALTER TYPE "order_notification_bindings_channel_enum" ADD VALUE IF NOT EXISTS 'mobile'`).catch(() => {
2794
+ });
2545
2795
  chunkUCKN4BBY_cjs.notificationTriggerEmitter.onAnyTrigger((triggerKey, payload) => {
2546
2796
  void handleTrigger(triggerKey, payload, dataSource, entityMap, getCms).catch((err) => {
2547
2797
  console.error("[order-notifications]", triggerKey, err);
@@ -2610,6 +2860,7 @@ exports.buildTranscriptForLeadEmail = buildTranscriptForLeadEmail;
2610
2860
  exports.detectChatLeadIntent = detectChatLeadIntent;
2611
2861
  exports.emailPlugin = emailPlugin;
2612
2862
  exports.emailTemplates = emailTemplates;
2863
+ exports.getSettingsGroup = getSettingsGroup;
2613
2864
  exports.initWhatsappTriggerDispatcher = initWhatsappTriggerDispatcher;
2614
2865
  exports.isWhatsAppPluginEnabled = isWhatsAppPluginEnabled;
2615
2866
  exports.joinRecipientsForSend = joinRecipientsForSend;
@@ -2623,5 +2874,6 @@ exports.renderLayout = renderLayout;
2623
2874
  exports.resendOrderNotification = resendOrderNotification;
2624
2875
  exports.resolveChatEmailToolSettings = resolveChatEmailToolSettings;
2625
2876
  exports.sendChatLeadEmail = sendChatLeadEmail;
2877
+ exports.sendFcmPushNotification = sendFcmPushNotification;
2626
2878
  exports.serializeEmailRecipients = serializeEmailRecipients;
2627
2879
  exports.whatsAppConfigured = whatsAppConfigured;
@@ -59,7 +59,7 @@ async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
59
59
  total: fo.total ?? 0,
60
60
  currency: String(fo.currency ?? "INR"),
61
61
  vendorId: fo.vendorId ?? null,
62
- ...extra?.extraVariables ?? {},
62
+ extraVariables: extra?.extraVariables,
63
63
  ...extra?.refundAmount != null ? {
64
64
  refundAmount: extra.refundAmount
65
65
  } : {}