@oneclick.dev/cms-core-modules 0.0.124 → 0.0.125

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 (149) hide show
  1. package/dist/AppointmentListTable-CWzbwqR-.js +1 -0
  2. package/dist/AppointmentListTable-DoZuBstk.mjs +270 -0
  3. package/dist/ContentEditor-BlNbqkAz.js +324 -0
  4. package/dist/{ContentEditor-DX1bTQKs.mjs → ContentEditor-D754iLJS.mjs} +8074 -27026
  5. package/dist/{Detail-B7pe808q.mjs → Detail-BOxWQ1QQ.mjs} +2 -2
  6. package/dist/{Detail-B_Q7Qkuz.mjs → Detail-BfKW0uZE.mjs} +2 -2
  7. package/dist/Detail-DFVu2F38.mjs +11 -0
  8. package/dist/{Detail-t3tOcy3X.js → Detail-DJea_fCd.js} +1 -1
  9. package/dist/{Detail-CNiLIEh9.js → Detail-DPJacXfm.js} +1 -1
  10. package/dist/Detail-DSLZ7_bM.js +1 -0
  11. package/dist/{Detail-BESGmY7z.js → Detail-DUGThL9Y.js} +1 -1
  12. package/dist/{Detail-DNxAzeCs.mjs → Detail-D_LlEeHu.mjs} +2 -2
  13. package/dist/Overview-0hFXiuYo.js +1 -0
  14. package/dist/Overview-BTx5LF4J.js +1 -0
  15. package/dist/Overview-CCu2PHai.mjs +289 -0
  16. package/dist/Overview-D2u-leeO.js +1 -0
  17. package/dist/Overview-D_2wozCG.mjs +1733 -0
  18. package/dist/Overview-Dffo-zH4.mjs +11 -0
  19. package/dist/{TableCalculationWidget-CrqcLGfU.mjs → TableCalculationWidget-B_LFoOYm.mjs} +3 -3
  20. package/dist/{TableCalculationWidget-CkQPrVUd.js → TableCalculationWidget-CahOIcbk.js} +1 -1
  21. package/dist/TableDataWidget-BwqWFH4A.js +1 -0
  22. package/dist/TableDataWidget-RsVxcDsL.mjs +112 -0
  23. package/dist/TableOverviewCard-BPWCqo56.js +1 -0
  24. package/dist/{TableOverviewCard-Ci0d4o4w.mjs → TableOverviewCard-D667DDag.mjs} +113 -127
  25. package/dist/TableResultView.vue_vue_type_script_setup_true_lang-C3XiOXgb.js +1 -0
  26. package/dist/TableResultView.vue_vue_type_script_setup_true_lang-sp0TLio0.mjs +547 -0
  27. package/dist/{TableRowActionCard-BhdnnPaq.mjs → TableRowActionCard-BPYJ-Kjy.mjs} +95 -101
  28. package/dist/TableRowActionCard-Bnqj1YIe.js +1 -0
  29. package/dist/TableView-CwhZ9YN2.js +4 -0
  30. package/dist/TableView-DX9PKS8N.mjs +9673 -0
  31. package/dist/TemplateBuilder.vue_vue_type_script_setup_true_lang-BgDdzbLe.js +1 -0
  32. package/dist/TemplateBuilder.vue_vue_type_script_setup_true_lang-D85V4nrQ.mjs +2886 -0
  33. package/dist/cms-core-modules.css +1 -1
  34. package/dist/dateRangePresets-CaPVagHY.mjs +453 -0
  35. package/dist/dateRangePresets-gxQCiZ6c.js +1 -0
  36. package/dist/index-6hZ6MYY6.js +1 -0
  37. package/dist/index-BVmmicu3.mjs +14 -0
  38. package/dist/index-ChHD_1Cf.js +144 -0
  39. package/dist/index-CvV4nVWI.js +1 -0
  40. package/dist/index-DH2z0W_w.mjs +19012 -0
  41. package/dist/index-DZKzj48V.mjs +17 -0
  42. package/dist/index.cjs.js +1 -1
  43. package/dist/index.mjs +237 -103
  44. package/dist/orders-C_sz8J9b.js +1 -0
  45. package/dist/{orders-BfTLIm7U.mjs → orders-Cgdggzvx.mjs} +84 -84
  46. package/dist/server-handlers.cjs.js +1 -1
  47. package/dist/server-handlers.mjs +2055 -1123
  48. package/dist/src/appointments/chat-components/AppointmentListTable.vue.d.ts +3 -0
  49. package/dist/src/appointments/index.d.ts +93 -3
  50. package/dist/src/appointments/reservation-summary.d.ts +48 -0
  51. package/dist/src/appointments/server.d.ts +1 -0
  52. package/dist/src/appointments/tools.d.ts +93 -3
  53. package/dist/src/filezone/config.d.ts +31 -0
  54. package/dist/src/filezone/index.d.ts +43 -0
  55. package/dist/src/filezone/index.vue.d.ts +2 -0
  56. package/dist/src/filezone/metadata.d.ts +2 -0
  57. package/dist/src/filezone/pages/Overview.vue.d.ts +4 -0
  58. package/dist/src/filezone/permissions.d.ts +5 -0
  59. package/dist/src/filezone/routes.d.ts +5 -0
  60. package/dist/src/filezone/server.d.ts +36 -0
  61. package/dist/src/index.d.ts +2 -0
  62. package/dist/src/mailTemplates/builder-types.d.ts +40 -0
  63. package/dist/src/mailTemplates/components/BlockRenderer.vue.d.ts +24 -0
  64. package/dist/src/mailTemplates/components/DesignPanel.vue.d.ts +13 -0
  65. package/dist/src/mailTemplates/components/EmailCanvas.vue.d.ts +44 -0
  66. package/dist/src/mailTemplates/components/RichTextEditor.vue.d.ts +10 -0
  67. package/dist/src/mailTemplates/components/RightSidebar.vue.d.ts +18 -0
  68. package/dist/src/mailTemplates/components/SettingsPanel.vue.d.ts +15 -0
  69. package/dist/src/mailTemplates/components/TemplateBuilder.vue.d.ts +2 -0
  70. package/dist/src/mailTemplates/components/TemplateList.vue.d.ts +19 -1
  71. package/dist/src/mailTemplates/components/rich-text.d.ts +6 -0
  72. package/dist/src/mailTemplates/config.d.ts +10 -4
  73. package/dist/src/mailTemplates/defaults.d.ts +10 -0
  74. package/dist/src/mailTemplates/editor-state.d.ts +21 -0
  75. package/dist/src/mailTemplates/index.d.ts +11 -5
  76. package/dist/src/mailTemplates/index.vue.d.ts +2 -4
  77. package/dist/src/mailTemplates/metadata.d.ts +1 -1
  78. package/dist/src/mailTemplates/pages/Detail.vue.d.ts +1 -13
  79. package/dist/src/mailTemplates/pages/Overview.vue.d.ts +1 -13
  80. package/dist/src/mailTemplates/server.d.ts +23 -0
  81. package/dist/src/server-handlers.d.ts +4 -0
  82. package/dist/src/table/badge-filter-utils.d.ts +8 -0
  83. package/dist/src/table/chat-components/TableOverviewCard.vue.d.ts +2 -7
  84. package/dist/src/table/chat-components/TableResultView.vue.d.ts +3 -7
  85. package/dist/src/table/components/TableDisplayCell.vue.d.ts +8 -0
  86. package/dist/src/table/components/columns/BadgeColumnSettings.vue.d.ts +9 -0
  87. package/dist/src/table/components/columns/ColumnColorSelect.vue.d.ts +11 -0
  88. package/dist/src/table/components/columns/ColumnDisplaySettings.vue.d.ts +9 -0
  89. package/dist/src/table/components/columns/ColumnTypeSelect.vue.d.ts +11 -0
  90. package/dist/src/table/components/columns/ColumnValueSourceInput.vue.d.ts +15 -0
  91. package/dist/src/table/components/columns/DialogTableColumnItem.vue.d.ts +8 -11
  92. package/dist/src/table/components/columns/ProgressColumnSettings.vue.d.ts +8 -0
  93. package/dist/src/table/components/stats/StatDialog.vue.d.ts +6 -10
  94. package/dist/src/table/components/stats/Stats.vue.d.ts +9 -15
  95. package/dist/src/table/composables/useTableClock.d.ts +4 -0
  96. package/dist/src/table/display-utils.d.ts +35 -0
  97. package/dist/src/table/row-value.d.ts +1 -0
  98. package/dist/src/table/stat-utils.d.ts +9 -0
  99. package/dist/src/table/tool-utils.d.ts +1 -1
  100. package/dist/src/table/types.d.ts +54 -1
  101. package/dist/src/whatsappBusiness/analytics.d.ts +4 -0
  102. package/dist/src/whatsappBusiness/components/AccountPanel.vue.d.ts +2 -0
  103. package/dist/src/whatsappBusiness/components/InsightsPanel.vue.d.ts +5 -0
  104. package/dist/src/whatsappBusiness/components/TemplateDialog.vue.d.ts +14 -0
  105. package/dist/src/whatsappBusiness/components/TemplatesPanel.vue.d.ts +5 -0
  106. package/dist/src/whatsappBusiness/components/presentation.d.ts +4 -0
  107. package/dist/src/whatsappBusiness/config.d.ts +51 -0
  108. package/dist/src/whatsappBusiness/connection.d.ts +77 -0
  109. package/dist/src/whatsappBusiness/index.d.ts +63 -0
  110. package/dist/src/whatsappBusiness/index.vue.d.ts +5 -0
  111. package/dist/src/whatsappBusiness/metadata.d.ts +2 -0
  112. package/dist/src/whatsappBusiness/pages/Overview.vue.d.ts +2 -0
  113. package/dist/src/whatsappBusiness/permissions.d.ts +5 -0
  114. package/dist/src/whatsappBusiness/provider.d.ts +21 -0
  115. package/dist/src/whatsappBusiness/routes.d.ts +5 -0
  116. package/dist/src/whatsappBusiness/server.d.ts +14 -0
  117. package/dist/src/whatsappBusiness/templates.d.ts +94 -0
  118. package/dist/src/whatsappBusiness/types.d.ts +162 -0
  119. package/dist/{tool-sandbox-DoF1PsyS.js → tool-sandbox-BSkKdH7V.js} +1 -1
  120. package/dist/{tool-sandbox-DdkMLkDK.mjs → tool-sandbox-DU9b1B7v.mjs} +1 -1
  121. package/dist/{types-ibC3-e1N.mjs → types-B5MifmeF.mjs} +339 -273
  122. package/dist/types-D5dgTskW.js +1 -0
  123. package/dist/{useTableAgentTools-D5mzGf3A.js → useTableAgentTools-BrUot49I.js} +1 -1
  124. package/dist/{useTableAgentTools-DcN3kYRL.mjs → useTableAgentTools-r5InEI4p.mjs} +8 -8
  125. package/dist/{vee-validate-zod-BQElPD0m.js → vee-validate-zod-CWZwNTWE.js} +1 -1
  126. package/dist/{vee-validate-zod-CN16K2x9.mjs → vee-validate-zod-D0WaDgDZ.mjs} +1 -1
  127. package/package.json +2 -2
  128. package/src/appointments/tools.ts +52 -2
  129. package/dist/AppointmentListTable-DZJNmTMb.mjs +0 -177
  130. package/dist/AppointmentListTable-Dieu9US_.js +0 -1
  131. package/dist/ContentEditor-BcIUumah.js +0 -467
  132. package/dist/Detail-Byk781b4.mjs +0 -26
  133. package/dist/Detail-mvSGbnFU.js +0 -1
  134. package/dist/Overview-BDlBCUI_.js +0 -1
  135. package/dist/Overview-Su8ZUbMs.mjs +0 -26
  136. package/dist/TableDataWidget-7qvC3Egd.js +0 -1
  137. package/dist/TableDataWidget-DMTSoGRO.mjs +0 -121
  138. package/dist/TableOverviewCard-AFq-puJs.js +0 -1
  139. package/dist/TableResultView.vue_vue_type_script_setup_true_lang-CBn-Oxl9.mjs +0 -534
  140. package/dist/TableResultView.vue_vue_type_script_setup_true_lang-C_Lv-SmJ.js +0 -1
  141. package/dist/TableRowActionCard-IzB6tNN-.js +0 -1
  142. package/dist/TableView-6mdrL3zx.js +0 -4
  143. package/dist/TableView-Du5nOE6R.mjs +0 -8228
  144. package/dist/TemplateList.vue_vue_type_script_setup_true_lang-B_AtWnHa.js +0 -1
  145. package/dist/TemplateList.vue_vue_type_script_setup_true_lang-Cmovy7kk.mjs +0 -40
  146. package/dist/dateRangePresets-B-l5b_wR.mjs +0 -48
  147. package/dist/dateRangePresets-CPWqst_x.js +0 -1
  148. package/dist/orders-DUa2PVoa.js +0 -1
  149. package/dist/types-BMraG1kN.js +0 -1
@@ -1,123 +1,219 @@
1
- import { createRouter as se, defineEventHandler as A, createError as y, getRouterParam as N, getQuery as R, readBody as Q, setResponseStatus as Ze } from "h3";
1
+ import { createRouter as J, defineEventHandler as b, createError as g, getRouterParam as U, getQuery as v, readBody as j, setResponseStatus as os, setHeader as se, setResponseHeader as ns } from "h3";
2
2
  import "vue";
3
- import { s as B, o as ae, b as re } from "./types-ibC3-e1N.mjs";
4
- function Gt(e) {
5
- const { initFirebase: t, normalizeTimestamps: s } = e, i = se();
6
- async function r(a) {
7
- const { supabase: n, instanceId: c } = a.context.module, { data: o, error: u } = await n.from("project_modules").select("config").eq("id", c).single();
8
- if (u || !o?.config)
9
- throw y({ statusCode: 500, statusMessage: "Failed to load module config." });
10
- const d = o.config, l = d.project, f = d.productCollection || "products";
3
+ import { s as x, o as O, b as _e, a as it, e as Ke, d as rs, l as ke } from "./types-B5MifmeF.mjs";
4
+ function Ma(e) {
5
+ const { initFirebase: t, normalizeTimestamps: s } = e, r = J();
6
+ async function n(a) {
7
+ const { supabase: c, instanceId: i } = a.context.module, { data: o, error: d } = await c.from("project_modules").select("config").eq("id", i).single();
8
+ if (d || !o?.config)
9
+ throw g({ statusCode: 500, statusMessage: "Failed to load module config." });
10
+ const u = o.config, l = u.project, f = u.productCollection || "products";
11
11
  if (!l)
12
- throw y({ statusCode: 400, statusMessage: "Products module has no Firebase integration configured." });
12
+ throw g({ statusCode: 400, statusMessage: "Products module has no Firebase integration configured." });
13
13
  return { firebase: await t(a, l), collection: f };
14
14
  }
15
- return i.get("/products", A(async (a) => {
15
+ return r.get("/products", b(async (a) => {
16
16
  try {
17
- const { firebase: n, collection: c } = await r(a);
18
- return (await n.firestore().collection(c).get()).docs.map((u) => s({
19
- id: u.id,
20
- ...u.data()
17
+ const { firebase: c, collection: i } = await n(a);
18
+ return (await c.firestore().collection(i).get()).docs.map((d) => s({
19
+ id: d.id,
20
+ ...d.data()
21
21
  }));
22
- } catch (n) {
23
- throw console.error("Products handler — list error:", n), y({
24
- statusCode: n.statusCode || 500,
25
- statusMessage: n.statusMessage || "Failed to list products"
22
+ } catch (c) {
23
+ throw console.error("Products handler — list error:", c), g({
24
+ statusCode: c.statusCode || 500,
25
+ statusMessage: c.statusMessage || "Failed to list products"
26
26
  });
27
27
  }
28
- })), i.get("/products/:productId", A(async (a) => {
29
- const n = N(a, "productId");
30
- if (!n)
31
- throw y({ statusCode: 400, statusMessage: "Product ID is required." });
28
+ })), r.get("/products/:productId", b(async (a) => {
29
+ const c = U(a, "productId");
30
+ if (!c)
31
+ throw g({ statusCode: 400, statusMessage: "Product ID is required." });
32
32
  try {
33
- const { firebase: c, collection: o } = await r(a), u = await c.firestore().collection(o).doc(n).get();
34
- if (!u.exists)
35
- throw y({ statusCode: 404, statusMessage: "Product not found." });
33
+ const { firebase: i, collection: o } = await n(a), d = await i.firestore().collection(o).doc(c).get();
34
+ if (!d.exists)
35
+ throw g({ statusCode: 404, statusMessage: "Product not found." });
36
36
  return s({
37
- id: u.id,
38
- ...u.data()
37
+ id: d.id,
38
+ ...d.data()
39
39
  });
40
- } catch (c) {
41
- throw console.error("Products handler — get error:", c), y({
42
- statusCode: c.statusCode || 500,
43
- statusMessage: c.statusMessage || "Failed to get product"
40
+ } catch (i) {
41
+ throw console.error("Products handler — get error:", i), g({
42
+ statusCode: i.statusCode || 500,
43
+ statusMessage: i.statusMessage || "Failed to get product"
44
44
  });
45
45
  }
46
- })), i.get("/empty-stock", A(async (a) => {
47
- const c = R(a).category;
46
+ })), r.get("/empty-stock", b(async (a) => {
47
+ const i = v(a).category;
48
48
  try {
49
- const { firebase: o, collection: u } = await r(a);
50
- let d = o.firestore().collection(u).where("stock", "==", 0);
51
- c && (d = d.where("collections", "array-contains", c));
52
- const f = (await d.get()).docs.map((g) => s({
53
- id: g.id,
54
- ...g.data()
49
+ const { firebase: o, collection: d } = await n(a);
50
+ let u = o.firestore().collection(d).where("stock", "==", 0);
51
+ i && (u = u.where("collections", "array-contains", i));
52
+ const f = (await u.get()).docs.map((p) => s({
53
+ id: p.id,
54
+ ...p.data()
55
55
  }));
56
56
  return {
57
57
  count: f.length,
58
- products: f.map((g) => ({
59
- id: g.id,
60
- title: g.title,
61
- slug: g.slug,
62
- stock: g.stock,
63
- price: g.price,
64
- currency: g.currency,
65
- status: g.status
58
+ products: f.map((p) => ({
59
+ id: p.id,
60
+ title: p.title,
61
+ slug: p.slug,
62
+ stock: p.stock,
63
+ price: p.price,
64
+ currency: p.currency,
65
+ status: p.status
66
66
  }))
67
67
  };
68
68
  } catch (o) {
69
- throw console.error("Products handler — empty-stock error:", o), y({
69
+ throw console.error("Products handler — empty-stock error:", o), g({
70
70
  statusCode: o.statusCode || 500,
71
71
  statusMessage: o.statusMessage || "Failed to query empty stock"
72
72
  });
73
73
  }
74
- })), i.handler;
74
+ })), r.handler;
75
+ }
76
+ const ct = 500, is = ["confirmed", "pending", "cancelled", "all"], cs = ["active", "approved", "needs_approval", "cancelled", "rejected", "all"];
77
+ function ne(e) {
78
+ throw g({ statusCode: 400, statusMessage: e });
79
+ }
80
+ function Ae(e, t, s) {
81
+ const r = e[t];
82
+ return r === void 0 && s !== void 0 ? s : ((typeof r != "string" || !r.trim()) && ne(`${t} must be a non-empty string.`), r.trim());
83
+ }
84
+ function dt(e, t, s, r, n = Number.MAX_SAFE_INTEGER) {
85
+ if (e[t] === void 0) return s;
86
+ const a = Ae(e, t), c = Number(a);
87
+ return (!/^\d+$/.test(a) || !Number.isSafeInteger(c) || c < r || c > n) && ne(`${t} must be an integer between ${r} and ${n}.`), c;
88
+ }
89
+ function q(e) {
90
+ return typeof e == "string" ? e : null;
91
+ }
92
+ function ds(e) {
93
+ if (typeof e != "number" && (typeof e != "string" || !e.trim())) return null;
94
+ const t = Number(e);
95
+ return Number.isFinite(t) ? t : null;
96
+ }
97
+ function ut(e, t, s) {
98
+ const r = { yesterday: -1, today: 0, tomorrow: 1 };
99
+ if (Object.prototype.hasOwnProperty.call(r, e)) {
100
+ const a = /* @__PURE__ */ new Date(`${t}T00:00:00.000Z`);
101
+ return a.setUTCDate(a.getUTCDate() + r[e]), a.toISOString().slice(0, 10);
102
+ }
103
+ /^\d{4}-\d{2}-\d{2}$/.test(e) || ne(`${s} must be YYYY-MM-DD, today, tomorrow, or yesterday.`);
104
+ const n = /* @__PURE__ */ new Date(`${e}T00:00:00.000Z`);
105
+ return (!Number.isFinite(n.getTime()) || n.toISOString().slice(0, 10) !== e) && ne(`${s} must be a valid calendar date.`), e;
106
+ }
107
+ async function us(e, t, s, r, n = /* @__PURE__ */ new Date()) {
108
+ let a;
109
+ try {
110
+ const I = new Intl.DateTimeFormat("en-US", { timeZone: r, year: "numeric", month: "2-digit", day: "2-digit" }).formatToParts(n), M = (D) => I.find((_) => _.type === D).value;
111
+ a = `${M("year")}-${M("month")}-${M("day")}`;
112
+ } catch {
113
+ ne("The project timezone is invalid.");
114
+ }
115
+ const c = ut(Ae(s, "startDate"), a, "startDate"), i = ut(Ae(s, "endDate", c), a, "endDate");
116
+ i < c && ne("endDate must be on or after startDate.");
117
+ const o = s.agendaId === void 0 ? null : Ae(s, "agendaId"), d = Ae(s, "orderStatus", "confirmed"), u = Ae(s, "reservationStatus", "active");
118
+ is.includes(d) || ne("Invalid orderStatus."), cs.includes(u) || ne("Invalid reservationStatus.");
119
+ const l = dt(s, "limit", 100, 1, 200), f = dt(s, "offset", 0, 0);
120
+ let p = e.collection(t);
121
+ o && (p = p.where("agendaId", "==", o)), d !== "all" && (p = p.where("status", "==", d)), p = p.orderBy("__name__").select("status", "agendaId", "reservations", "customerInfo").limit(ct);
122
+ const m = { reservationCount: 0, orderCount: 0, spotCount: 0 }, h = /* @__PURE__ */ new Map(), y = [];
123
+ let w;
124
+ for (; ; ) {
125
+ const I = await (w ? p.startAfter(w) : p).get();
126
+ for (const M of I.docs) {
127
+ const D = M.data(), _ = /* @__PURE__ */ new Set();
128
+ for (const T of Array.isArray(D.reservations) ? D.reservations : []) {
129
+ if (!T || typeof T.date != "string") continue;
130
+ const E = T.date;
131
+ if (E < c || E > i || u === "active" && ["cancelled", "rejected"].includes(T.status) || u !== "active" && u !== "all" && T.status !== u) continue;
132
+ const V = T.spots == null ? 1 : Number(T.spots), P = Number.isFinite(V) && V >= 0 ? V : 1, K = h.get(E) || { reservationCount: 0, orderCount: 0, spotCount: 0 };
133
+ K.reservationCount++, K.spotCount += P, h.set(E, K), _.add(E), m.reservationCount >= f && y.length < l && y.push({
134
+ orderId: M.id,
135
+ reservationId: q(T.id),
136
+ agendaId: q(D.agendaId),
137
+ date: E,
138
+ startTime: q(T.timeslot?.startTime),
139
+ endTime: q(T.timeslot?.endTime),
140
+ spots: P,
141
+ status: q(D.status),
142
+ reservationStatus: q(T.status),
143
+ resourceId: q(T.resourceId) ?? q(T.resource?.id),
144
+ resourceName: q(T.resource?.name) ?? q(T.resourceName),
145
+ customerInfo: {
146
+ firstName: q(D.customerInfo?.firstName),
147
+ lastName: q(D.customerInfo?.lastName),
148
+ email: q(D.customerInfo?.email)
149
+ },
150
+ reservationPrice: ds(T.totalPrice)
151
+ }), m.reservationCount++, m.spotCount += P;
152
+ }
153
+ _.size && m.orderCount++;
154
+ for (const T of _) h.get(T).orderCount++;
155
+ }
156
+ if (I.docs.length < ct) break;
157
+ w = I.docs[I.docs.length - 1];
158
+ }
159
+ const C = f + y.length, A = C < m.reservationCount;
160
+ return {
161
+ startDate: c,
162
+ endDate: i,
163
+ timeZone: r,
164
+ filters: { agendaId: o, orderStatus: d, reservationStatus: u },
165
+ ...m,
166
+ byDate: [...h].sort(([I], [M]) => I.localeCompare(M)).map(([I, M]) => ({ date: I, ...M })),
167
+ appointments: y,
168
+ pagination: { offset: f, limit: l, returnedCount: y.length, hasMore: A, nextOffset: A ? C : null }
169
+ };
75
170
  }
76
- function Qt(e) {
77
- const { initFirebase: t, normalizeTimestamps: s, deleteField: i } = e, r = se(), a = "privateSettings", n = "refundFlow", c = "metadataSchema";
171
+ function Sa(e) {
172
+ const { initFirebase: t, normalizeTimestamps: s, deleteField: r } = e, n = J(), a = "privateSettings", c = "refundFlow", i = "metadataSchema";
78
173
  async function o(m) {
79
- const { supabase: h, instanceId: p } = m.context.module, { data: w, error: C } = await h.from("project_modules").select("config").eq("id", p).single();
174
+ const { supabase: h, instanceId: y } = m.context.module, { data: w, error: C } = await h.from("project_modules").select("config, project_id").eq("id", y).single();
80
175
  if (C || !w?.config)
81
- throw y({ statusCode: 500, statusMessage: "Failed to load module config." });
82
- const b = w.config, D = b.project, F = b.reservationsCollection || "bookings_orders", M = b.agendaCollection || "agendas";
83
- if (!D)
84
- throw y({ statusCode: 400, statusMessage: "Appointments module has no Firebase integration configured." });
85
- return { firebase: await t(m, D), reservationsCollection: F, agendaCollection: M };
176
+ throw g({ statusCode: 500, statusMessage: "Failed to load module config." });
177
+ const A = w.config, I = A.project, M = A.reservationsCollection || "bookings_orders", D = A.agendaCollection || "agendas";
178
+ if (!I)
179
+ throw g({ statusCode: 400, statusMessage: "Appointments module has no Firebase integration configured." });
180
+ return { firebase: await t(m, I), reservationsCollection: M, agendaCollection: D, projectId: w.project_id };
86
181
  }
87
- function u(m) {
88
- return (m.reservations || []).map((p) => ({
182
+ function d(m) {
183
+ return (m.reservations || []).map((y) => ({
89
184
  orderId: m.id,
90
- reservationId: p.id,
185
+ agendaId: m.agendaId,
186
+ reservationId: y.id,
91
187
  customerInfo: m.customerInfo,
92
- date: p.date,
93
- startTime: p.timeslot?.startTime,
94
- endTime: p.timeslot?.endTime,
95
- spots: p.spots,
188
+ date: y.date,
189
+ startTime: y.timeslot?.startTime,
190
+ endTime: y.timeslot?.endTime,
191
+ spots: y.spots,
96
192
  status: m.status,
97
- reservationStatus: p.status,
98
- resourceId: p.resourceId,
99
- reservationPrice: p.totalPrice,
100
- reservationBasePrice: p.basePrice,
101
- reservationAddOnsPrice: p.addOnsPrice,
102
- pricingOption: p.pricingOption,
193
+ reservationStatus: y.status,
194
+ resourceId: y.resourceId,
195
+ reservationPrice: y.totalPrice,
196
+ reservationBasePrice: y.basePrice,
197
+ reservationAddOnsPrice: y.addOnsPrice,
198
+ pricingOption: y.pricingOption,
103
199
  amountDue: m.amountDue,
104
200
  amountPaid: m.amountPaid,
105
201
  createdAt: m.createdAt,
106
202
  metadata: m.metadata || {},
107
- reservationMetadata: p.metadata || {}
203
+ reservationMetadata: y.metadata || {}
108
204
  }));
109
205
  }
110
- function d(m) {
206
+ function u(m) {
111
207
  return {
112
208
  showAmount: m?.showAmount !== !1,
113
209
  fields: Array.isArray(m?.fields) ? m.fields : []
114
210
  };
115
211
  }
116
212
  function l() {
117
- return i ? {
118
- refundFlow: i(),
119
- refundFlowEnabled: i(),
120
- refundDialog: i()
213
+ return r ? {
214
+ refundFlow: r(),
215
+ refundFlowEnabled: r(),
216
+ refundDialog: r()
121
217
  } : {
122
218
  refundFlow: null,
123
219
  refundFlowEnabled: null,
@@ -127,21 +223,21 @@ function Qt(e) {
127
223
  function f(m) {
128
224
  return Array.isArray(m) ? m : [];
129
225
  }
130
- function g() {
131
- return i ? {
132
- metadataSchema: i()
226
+ function p() {
227
+ return r ? {
228
+ metadataSchema: r()
133
229
  } : {
134
230
  metadataSchema: null
135
231
  };
136
232
  }
137
- return r.get("/agendas", A(async (m) => {
233
+ return n.get("/agendas", b(async (m) => {
138
234
  try {
139
- const { firebase: h, agendaCollection: p } = await o(m), C = (await h.firestore().collection(p).get()).docs.map((b) => {
140
- const D = b.data();
235
+ const { firebase: h, agendaCollection: y } = await o(m), C = (await h.firestore().collection(y).get()).docs.map((A) => {
236
+ const I = A.data();
141
237
  return {
142
- id: b.id,
143
- serviceName: D.serviceName || "",
144
- type: D.type || "regular"
238
+ id: A.id,
239
+ serviceName: I.serviceName || "",
240
+ type: I.type || "regular"
145
241
  };
146
242
  });
147
243
  return {
@@ -149,253 +245,258 @@ function Qt(e) {
149
245
  agendas: C
150
246
  };
151
247
  } catch (h) {
152
- throw console.error("Appointments handler — list agendas error:", h), y({
248
+ throw console.error("Appointments handler — list agendas error:", h), g({
153
249
  statusCode: h.statusCode || 500,
154
250
  statusMessage: h.statusMessage || "Failed to list agendas"
155
251
  });
156
252
  }
157
- })), r.get("/agendas/:agendaId/opening-hours", A(async (m) => {
158
- const h = N(m, "agendaId"), w = R(m).date;
253
+ })), n.get("/agendas/:agendaId/opening-hours", b(async (m) => {
254
+ const h = U(m, "agendaId"), w = v(m).date;
159
255
  if (!h)
160
- throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
256
+ throw g({ statusCode: 400, statusMessage: "Agenda ID is required." });
161
257
  if (!w)
162
- throw y({ statusCode: 400, statusMessage: "Date is required (YYYY-MM-DD)." });
258
+ throw g({ statusCode: 400, statusMessage: "Date is required (YYYY-MM-DD)." });
163
259
  try {
164
- const { firebase: C, agendaCollection: b } = await o(m), D = await C.firestore().collection(b).doc(h).get();
165
- if (!D.exists)
166
- throw y({ statusCode: 404, statusMessage: "Agenda not found." });
167
- const F = D.data(), M = (F.resources || []).filter(($) => $.isActive), S = F.exceptions || [], j = (/* @__PURE__ */ new Date(w + "T00:00:00")).getDay(), ce = M.map(($) => {
168
- const Ae = $.openingHours?.[j] || [], de = S.find((V) => {
169
- const Je = w >= V.startDate && w <= V.endDate, Xe = !V.resourceIds || V.resourceIds.length === 0 || V.resourceIds.includes($.id);
170
- return Je && Xe;
260
+ const { firebase: C, agendaCollection: A } = await o(m), I = await C.firestore().collection(A).doc(h).get();
261
+ if (!I.exists)
262
+ throw g({ statusCode: 404, statusMessage: "Agenda not found." });
263
+ const M = I.data(), D = (M.resources || []).filter((P) => P.isActive), _ = M.exceptions || [], E = (/* @__PURE__ */ new Date(w + "T00:00:00")).getDay(), V = D.map((P) => {
264
+ const K = P.openingHours?.[E] || [], Q = _.find((N) => {
265
+ const de = w >= N.startDate && w <= N.endDate, Z = !N.resourceIds || N.resourceIds.length === 0 || N.resourceIds.includes(P.id);
266
+ return de && Z;
171
267
  });
172
- return de ? {
173
- resourceId: $.id,
174
- resourceName: $.name,
268
+ return Q ? {
269
+ resourceId: P.id,
270
+ resourceName: P.name,
175
271
  date: w,
176
- dayOfWeek: j,
177
- isClosed: de.isClosed,
178
- hours: de.isClosed ? [] : (de.timeslots || []).map((V) => ({
179
- start: V.startTime,
180
- end: V.endTime
272
+ dayOfWeek: E,
273
+ isClosed: Q.isClosed,
274
+ hours: Q.isClosed ? [] : (Q.timeslots || []).map((N) => ({
275
+ start: N.startTime,
276
+ end: N.endTime
181
277
  })),
182
278
  isException: !0
183
279
  } : {
184
- resourceId: $.id,
185
- resourceName: $.name,
280
+ resourceId: P.id,
281
+ resourceName: P.name,
186
282
  date: w,
187
- dayOfWeek: j,
188
- isClosed: Ae.length === 0,
189
- hours: Ae,
283
+ dayOfWeek: E,
284
+ isClosed: K.length === 0,
285
+ hours: K,
190
286
  isException: !1
191
287
  };
192
288
  });
193
289
  return {
194
290
  agendaId: h,
195
- serviceName: F.serviceName || "",
291
+ serviceName: M.serviceName || "",
196
292
  date: w,
197
- resources: ce
293
+ resources: V
198
294
  };
199
295
  } catch (C) {
200
- throw console.error("Appointments handler — opening hours error:", C), y({
296
+ throw console.error("Appointments handler — opening hours error:", C), g({
201
297
  statusCode: C.statusCode || 500,
202
298
  statusMessage: C.statusMessage || "Failed to get opening hours"
203
299
  });
204
300
  }
205
- })), r.get("/agendas/:agendaId/refund-flow", A(async (m) => {
206
- const h = N(m, "agendaId");
301
+ })), n.get("/agendas/:agendaId/refund-flow", b(async (m) => {
302
+ const h = U(m, "agendaId");
207
303
  if (!h)
208
- throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
304
+ throw g({ statusCode: 400, statusMessage: "Agenda ID is required." });
209
305
  try {
210
- const { firebase: p, agendaCollection: w } = await o(m), b = p.firestore().collection(w).doc(h), D = b.collection(a).doc(n), [F, M] = await Promise.all([
211
- b.get(),
212
- D.get()
306
+ const { firebase: y, agendaCollection: w } = await o(m), A = y.firestore().collection(w).doc(h), I = A.collection(a).doc(c), [M, D] = await Promise.all([
307
+ A.get(),
308
+ I.get()
213
309
  ]);
214
- if (!F.exists)
215
- throw y({ statusCode: 404, statusMessage: "Agenda not found." });
216
- const S = M.exists ? M.data() || {} : {};
310
+ if (!M.exists)
311
+ throw g({ statusCode: 404, statusMessage: "Agenda not found." });
312
+ const _ = D.exists ? D.data() || {} : {};
217
313
  return {
218
- refundFlow: S.flow || {},
219
- refundFlowEnabled: S.enabled !== !1,
220
- refundDialog: d(S.dialog)
314
+ refundFlow: _.flow || {},
315
+ refundFlowEnabled: _.enabled !== !1,
316
+ refundDialog: u(_.dialog)
221
317
  };
222
- } catch (p) {
223
- throw console.error("Appointments handler — refund flow load error:", p), y({
224
- statusCode: p.statusCode || 500,
225
- statusMessage: p.statusMessage || "Failed to load refund flow"
318
+ } catch (y) {
319
+ throw console.error("Appointments handler — refund flow load error:", y), g({
320
+ statusCode: y.statusCode || 500,
321
+ statusMessage: y.statusMessage || "Failed to load refund flow"
226
322
  });
227
323
  }
228
- })), r.patch("/agendas/:agendaId/refund-flow", A(async (m) => {
229
- const h = N(m, "agendaId");
324
+ })), n.patch("/agendas/:agendaId/refund-flow", b(async (m) => {
325
+ const h = U(m, "agendaId");
230
326
  if (!h)
231
- throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
327
+ throw g({ statusCode: 400, statusMessage: "Agenda ID is required." });
232
328
  try {
233
- const p = await Q(m), { firebase: w, agendaCollection: C } = await o(m), b = w.firestore(), D = b.collection(C).doc(h), F = D.collection(a).doc(n), M = d(p?.refundDialog);
234
- if (!(await D.get()).exists)
235
- throw y({ statusCode: 404, statusMessage: "Agenda not found." });
236
- const k = b.batch();
237
- return k.set(F, {
238
- flow: p?.refundFlow || {},
239
- enabled: p?.refundFlowEnabled !== !1,
240
- dialog: M,
329
+ const y = await j(m), { firebase: w, agendaCollection: C } = await o(m), A = w.firestore(), I = A.collection(C).doc(h), M = I.collection(a).doc(c), D = u(y?.refundDialog);
330
+ if (!(await I.get()).exists)
331
+ throw g({ statusCode: 404, statusMessage: "Agenda not found." });
332
+ const T = A.batch();
333
+ return T.set(M, {
334
+ flow: y?.refundFlow || {},
335
+ enabled: y?.refundFlowEnabled !== !1,
336
+ dialog: D,
241
337
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
242
- }, { merge: !0 }), k.set(D, l(), { merge: !0 }), await k.commit(), { success: !0 };
243
- } catch (p) {
244
- throw console.error("Appointments handler — refund flow save error:", p), y({
245
- statusCode: p.statusCode || 500,
246
- statusMessage: p.statusMessage || "Failed to save refund flow"
338
+ }, { merge: !0 }), T.set(I, l(), { merge: !0 }), await T.commit(), { success: !0 };
339
+ } catch (y) {
340
+ throw console.error("Appointments handler — refund flow save error:", y), g({
341
+ statusCode: y.statusCode || 500,
342
+ statusMessage: y.statusMessage || "Failed to save refund flow"
247
343
  });
248
344
  }
249
- })), r.get("/agendas/:agendaId/metadata-schema", A(async (m) => {
250
- const h = N(m, "agendaId");
345
+ })), n.get("/agendas/:agendaId/metadata-schema", b(async (m) => {
346
+ const h = U(m, "agendaId");
251
347
  if (!h)
252
- throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
348
+ throw g({ statusCode: 400, statusMessage: "Agenda ID is required." });
253
349
  try {
254
- const { firebase: p, agendaCollection: w } = await o(m), b = p.firestore().collection(w).doc(h), D = b.collection(a).doc(c), [F, M] = await Promise.all([
255
- b.get(),
256
- D.get()
350
+ const { firebase: y, agendaCollection: w } = await o(m), A = y.firestore().collection(w).doc(h), I = A.collection(a).doc(i), [M, D] = await Promise.all([
351
+ A.get(),
352
+ I.get()
257
353
  ]);
258
- if (!F.exists)
259
- throw y({ statusCode: 404, statusMessage: "Agenda not found." });
260
- const S = M.exists ? M.data() || {} : {};
354
+ if (!M.exists)
355
+ throw g({ statusCode: 404, statusMessage: "Agenda not found." });
356
+ const _ = D.exists ? D.data() || {} : {};
261
357
  return {
262
- metadataSchema: f(S.schema)
358
+ metadataSchema: f(_.schema)
263
359
  };
264
- } catch (p) {
265
- throw console.error("Appointments handler — metadata schema load error:", p), y({
266
- statusCode: p.statusCode || 500,
267
- statusMessage: p.statusMessage || "Failed to load metadata schema"
360
+ } catch (y) {
361
+ throw console.error("Appointments handler — metadata schema load error:", y), g({
362
+ statusCode: y.statusCode || 500,
363
+ statusMessage: y.statusMessage || "Failed to load metadata schema"
268
364
  });
269
365
  }
270
- })), r.patch("/agendas/:agendaId/metadata-schema", A(async (m) => {
271
- const h = N(m, "agendaId");
366
+ })), n.patch("/agendas/:agendaId/metadata-schema", b(async (m) => {
367
+ const h = U(m, "agendaId");
272
368
  if (!h)
273
- throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
369
+ throw g({ statusCode: 400, statusMessage: "Agenda ID is required." });
274
370
  try {
275
- const p = await Q(m), { firebase: w, agendaCollection: C } = await o(m), b = w.firestore(), D = b.collection(C).doc(h), F = D.collection(a).doc(c);
276
- if (!(await D.get()).exists)
277
- throw y({ statusCode: 404, statusMessage: "Agenda not found." });
278
- const S = b.batch();
279
- return S.set(F, {
280
- schema: f(p?.metadataSchema),
371
+ const y = await j(m), { firebase: w, agendaCollection: C } = await o(m), A = w.firestore(), I = A.collection(C).doc(h), M = I.collection(a).doc(i);
372
+ if (!(await I.get()).exists)
373
+ throw g({ statusCode: 404, statusMessage: "Agenda not found." });
374
+ const _ = A.batch();
375
+ return _.set(M, {
376
+ schema: f(y?.metadataSchema),
281
377
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
282
- }, { merge: !0 }), S.set(D, g(), { merge: !0 }), await S.commit(), { success: !0 };
283
- } catch (p) {
284
- throw console.error("Appointments handler — metadata schema save error:", p), y({
285
- statusCode: p.statusCode || 500,
286
- statusMessage: p.statusMessage || "Failed to save metadata schema"
378
+ }, { merge: !0 }), _.set(I, p(), { merge: !0 }), await _.commit(), { success: !0 };
379
+ } catch (y) {
380
+ throw console.error("Appointments handler — metadata schema save error:", y), g({
381
+ statusCode: y.statusCode || 500,
382
+ statusMessage: y.statusMessage || "Failed to save metadata schema"
287
383
  });
288
384
  }
289
- })), r.get("/appointments", A(async (m) => {
290
- const h = R(m), p = Math.min(Number(h.quantity) || 20, 100), w = h.status || "confirmed";
385
+ })), n.get("/appointments/summary", b(async (m) => {
386
+ const { firebase: h, reservationsCollection: y, projectId: w } = await o(m), { data: C, error: A } = await m.context.module.supabase.from("projects").select("timezone").eq("id", w).single();
387
+ if (A || !C)
388
+ throw g({ statusCode: 500, statusMessage: "Failed to load the booking project timezone." });
389
+ return us(h.firestore(), y, v(m), C.timezone || "UTC");
390
+ })), n.get("/appointments", b(async (m) => {
391
+ const h = v(m), y = Math.min(Number(h.quantity) || 20, 100), w = h.status || "confirmed";
291
392
  try {
292
- const { firebase: C, reservationsCollection: b } = await o(m), F = (await C.firestore().collection(b).orderBy("createdAt", "desc").where("status", "==", w).limit(p).get()).docs.flatMap(
293
- (M) => u(s({ id: M.id, ...M.data() }))
393
+ const { firebase: C, reservationsCollection: A } = await o(m), M = (await C.firestore().collection(A).orderBy("createdAt", "desc").where("status", "==", w).limit(y).get()).docs.flatMap(
394
+ (D) => d(s({ id: D.id, ...D.data() }))
294
395
  );
295
396
  return {
296
- count: F.length,
297
- appointments: F
397
+ count: M.length,
398
+ appointments: M
298
399
  };
299
400
  } catch (C) {
300
- throw console.error("Appointments handler — list error:", C), y({
401
+ throw console.error("Appointments handler — list error:", C), g({
301
402
  statusCode: C.statusCode || 500,
302
403
  statusMessage: C.statusMessage || "Failed to list appointments"
303
404
  });
304
405
  }
305
- })), r.get("/appointments/find", A(async (m) => {
306
- const h = R(m), p = (h.name || "").toLowerCase().trim(), w = (h.email || "").toLowerCase().trim(), C = h.date;
406
+ })), n.get("/appointments/find", b(async (m) => {
407
+ const h = v(m), y = (h.name || "").toLowerCase().trim(), w = (h.email || "").toLowerCase().trim(), C = h.date;
307
408
  try {
308
- const { firebase: b, reservationsCollection: D } = await o(m);
309
- let F = b.firestore().collection(D);
310
- w && (F = F.where("customerInfo.email", "==", w));
311
- let S = (await F.orderBy("createdAt", "desc").limit(200).get()).docs.flatMap(
312
- (k) => u(s({ id: k.id, ...k.data() }))
409
+ const { firebase: A, reservationsCollection: I } = await o(m);
410
+ let M = A.firestore().collection(I);
411
+ w && (M = M.where("customerInfo.email", "==", w));
412
+ let _ = (await M.orderBy("createdAt", "desc").limit(200).get()).docs.flatMap(
413
+ (T) => d(s({ id: T.id, ...T.data() }))
313
414
  );
314
- return C && (S = S.filter((k) => k.date === C)), p && (S = S.filter((k) => {
315
- const j = (k.customerInfo?.firstName || "").toLowerCase(), ce = (k.customerInfo?.lastName || "").toLowerCase();
316
- return j.includes(p) || ce.includes(p) || `${j} ${ce}`.includes(p);
415
+ return C && (_ = _.filter((T) => T.date === C)), y && (_ = _.filter((T) => {
416
+ const E = (T.customerInfo?.firstName || "").toLowerCase(), V = (T.customerInfo?.lastName || "").toLowerCase();
417
+ return E.includes(y) || V.includes(y) || `${E} ${V}`.includes(y);
317
418
  })), {
318
- count: S.length,
319
- appointments: S
419
+ count: _.length,
420
+ appointments: _
320
421
  };
321
- } catch (b) {
322
- throw console.error("Appointments handler — find error:", b), y({
323
- statusCode: b.statusCode || 500,
324
- statusMessage: b.statusMessage || "Failed to find appointments"
422
+ } catch (A) {
423
+ throw console.error("Appointments handler — find error:", A), g({
424
+ statusCode: A.statusCode || 500,
425
+ statusMessage: A.statusMessage || "Failed to find appointments"
325
426
  });
326
427
  }
327
- })), r.get("/appointments/:appointmentId", A(async (m) => {
328
- const h = N(m, "appointmentId");
428
+ })), n.get("/appointments/:appointmentId", b(async (m) => {
429
+ const h = U(m, "appointmentId");
329
430
  if (!h)
330
- throw y({ statusCode: 400, statusMessage: "Appointment ID is required." });
431
+ throw g({ statusCode: 400, statusMessage: "Appointment ID is required." });
331
432
  try {
332
- const { firebase: p, reservationsCollection: w } = await o(m), C = await p.firestore().collection(w).doc(h).get();
433
+ const { firebase: y, reservationsCollection: w } = await o(m), C = await y.firestore().collection(w).doc(h).get();
333
434
  if (!C.exists)
334
- throw y({ statusCode: 404, statusMessage: "Appointment not found." });
335
- const b = s({ id: C.id, ...C.data() });
435
+ throw g({ statusCode: 404, statusMessage: "Appointment not found." });
436
+ const A = s({ id: C.id, ...C.data() });
336
437
  return {
337
- ...b,
338
- reservations: u(b)
438
+ ...A,
439
+ reservations: d(A)
339
440
  };
340
- } catch (p) {
341
- throw console.error("Appointments handler — get error:", p), y({
342
- statusCode: p.statusCode || 500,
343
- statusMessage: p.statusMessage || "Failed to get appointment"
441
+ } catch (y) {
442
+ throw console.error("Appointments handler — get error:", y), g({
443
+ statusCode: y.statusCode || 500,
444
+ statusMessage: y.statusMessage || "Failed to get appointment"
344
445
  });
345
446
  }
346
- })), r.handler;
447
+ })), n.handler;
347
448
  }
348
- const De = "https://analyticsdata.googleapis.com/v1beta", We = [
449
+ const lt = "https://analyticsdata.googleapis.com/v1beta", ls = [
349
450
  "https://www.googleapis.com/auth/analytics.readonly",
350
451
  "https://www.googleapis.com/auth/webmasters.readonly"
351
- ], Fe = "https://searchconsole.googleapis.com/webmasters/v3";
352
- function Yt(e) {
353
- const { decrypt: t, getGoogleAccessToken: s } = e, i = se();
354
- async function r(o) {
355
- const { supabase: u, instanceId: d } = o.context.module, { data: l, error: f } = await u.from("project_modules").select("config").eq("id", d).single();
452
+ ], mt = "https://searchconsole.googleapis.com/webmasters/v3";
453
+ function Da(e) {
454
+ const { decrypt: t, getGoogleAccessToken: s } = e, r = J();
455
+ async function n(o) {
456
+ const { supabase: d, instanceId: u } = o.context.module, { data: l, error: f } = await d.from("project_modules").select("config").eq("id", u).single();
356
457
  if (f || !l?.config)
357
- throw y({ statusCode: 500, statusMessage: "Failed to load module config." });
358
- const g = l.config, m = g.propertyId, h = g.serviceAccount, p = g.siteUrl || "";
458
+ throw g({ statusCode: 500, statusMessage: "Failed to load module config." });
459
+ const p = l.config, m = p.propertyId, h = p.serviceAccount, y = p.siteUrl || "";
359
460
  if (!h)
360
- throw y({ statusCode: 400, statusMessage: "No Google Service Account configured for this module." });
461
+ throw g({ statusCode: 400, statusMessage: "No Google Service Account configured for this module." });
361
462
  if (!m)
362
- throw y({ statusCode: 400, statusMessage: "No GA4 Property ID configured for this module." });
363
- const { data: w, error: C } = await u.from("integrations").select("config").eq("id", h).single();
364
- let b = w?.config;
365
- if (C || !b) {
366
- const { data: k, error: j } = await u.from("agency_integrations").select("config").eq("id", h).single();
367
- if (j || !k?.config)
368
- throw y({ statusCode: 500, statusMessage: "Failed to load Google Service Account credentials." });
369
- b = k.config;
463
+ throw g({ statusCode: 400, statusMessage: "No GA4 Property ID configured for this module." });
464
+ const { data: w, error: C } = await d.from("integrations").select("config").eq("id", h).single();
465
+ let A = w?.config;
466
+ if (C || !A) {
467
+ const { data: T, error: E } = await d.from("agency_integrations").select("config").eq("id", h).single();
468
+ if (E || !T?.config)
469
+ throw g({ statusCode: 500, statusMessage: "Failed to load Google Service Account credentials." });
470
+ A = T.config;
370
471
  }
371
- const D = t(b.clientEmail), F = t(b.privateKey), M = t(b.projectId);
472
+ const I = t(A.clientEmail), M = t(A.privateKey), D = t(A.projectId);
372
473
  return { accessToken: await s(
373
- { clientEmail: D, privateKey: F, projectId: M },
374
- We
375
- ), propertyId: m, siteUrl: p };
474
+ { clientEmail: I, privateKey: M, projectId: D },
475
+ ls
476
+ ), propertyId: m, siteUrl: y };
376
477
  }
377
- async function a(o, u, d) {
378
- const l = await fetch(`${De}/properties/${u}:runReport`, {
478
+ async function a(o, d, u) {
479
+ const l = await fetch(`${lt}/properties/${d}:runReport`, {
379
480
  method: "POST",
380
481
  headers: {
381
482
  Authorization: `Bearer ${o}`,
382
483
  "Content-Type": "application/json"
383
484
  },
384
- body: JSON.stringify(d)
485
+ body: JSON.stringify(u)
385
486
  });
386
487
  if (!l.ok) {
387
488
  const f = await l.json().catch(() => ({}));
388
- throw console.error("GA4 runReport failed:", f), y({
489
+ throw console.error("GA4 runReport failed:", f), g({
389
490
  statusCode: l.status,
390
491
  statusMessage: f?.error?.message || "GA4 API request failed"
391
492
  });
392
493
  }
393
494
  return l.json();
394
495
  }
395
- i.get(
496
+ r.get(
396
497
  "/report",
397
- A(async (o) => {
398
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = f.match(/^(\d+)daysAgo$/), h = m ? parseInt(m[1], 10) : 30, p = `${h * 2}daysAgo`, w = `${h + 1}daysAgo`, C = [
498
+ b(async (o) => {
499
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = f.match(/^(\d+)daysAgo$/), h = m ? parseInt(m[1], 10) : 30, y = `${h * 2}daysAgo`, w = `${h + 1}daysAgo`, C = [
399
500
  { name: "sessions" },
400
501
  { name: "totalUsers" },
401
502
  { name: "screenPageViews" },
@@ -406,12 +507,12 @@ function Yt(e) {
406
507
  { name: "sessionsPerUser" },
407
508
  { name: "screenPageViewsPerSession" }
408
509
  ];
409
- let b, D = !0;
510
+ let A, I = !0;
410
511
  try {
411
- b = await a(u, d, {
512
+ A = await a(d, u, {
412
513
  dateRanges: [
413
- { startDate: f, endDate: g, name: "current" },
414
- { startDate: p, endDate: w, name: "previous" }
514
+ { startDate: f, endDate: p, name: "current" },
515
+ { startDate: y, endDate: w, name: "previous" }
415
516
  ],
416
517
  dimensions: [{ name: "date" }],
417
518
  metrics: C,
@@ -419,25 +520,25 @@ function Yt(e) {
419
520
  orderBys: [{ dimension: { dimensionName: "date" } }]
420
521
  });
421
522
  } catch {
422
- D = !1, b = await a(u, d, {
423
- dateRanges: [{ startDate: f, endDate: g }],
523
+ I = !1, A = await a(d, u, {
524
+ dateRanges: [{ startDate: f, endDate: p }],
424
525
  dimensions: [{ name: "date" }],
425
526
  metrics: C,
426
527
  metricAggregations: ["TOTAL"],
427
528
  orderBys: [{ dimension: { dimensionName: "date" } }]
428
529
  });
429
530
  }
430
- return et(b, D);
531
+ return ms(A, I);
431
532
  })
432
- ), i.get(
533
+ ), r.get(
433
534
  "/realtime",
434
- A(async (o) => {
435
- const { accessToken: u, propertyId: d } = await r(o), l = await fetch(
436
- `${De}/properties/${d}:runRealtimeReport`,
535
+ b(async (o) => {
536
+ const { accessToken: d, propertyId: u } = await n(o), l = await fetch(
537
+ `${lt}/properties/${u}:runRealtimeReport`,
437
538
  {
438
539
  method: "POST",
439
540
  headers: {
440
- Authorization: `Bearer ${u}`,
541
+ Authorization: `Bearer ${d}`,
441
542
  "Content-Type": "application/json"
442
543
  },
443
544
  body: JSON.stringify({
@@ -450,22 +551,22 @@ function Yt(e) {
450
551
  );
451
552
  if (!l.ok) {
452
553
  const h = await l.json().catch(() => ({}));
453
- throw y({ statusCode: l.status, statusMessage: h?.error?.message || "Realtime API failed" });
554
+ throw g({ statusCode: l.status, statusMessage: h?.error?.message || "Realtime API failed" });
454
555
  }
455
- const f = await l.json(), g = (f?.rows || []).reduce(
456
- (h, p) => h + parseInt(p.metricValues?.[0]?.value || "0", 10),
556
+ const f = await l.json(), p = (f?.rows || []).reduce(
557
+ (h, y) => h + parseInt(y.metricValues?.[0]?.value || "0", 10),
457
558
  0
458
559
  ), m = (f?.rows || []).map((h) => ({
459
560
  page: h.dimensionValues?.[0]?.value || "(not set)",
460
561
  activeUsers: parseInt(h.metricValues?.[0]?.value || "0", 10)
461
562
  }));
462
- return { activeUsers: g, activePages: m };
563
+ return { activeUsers: p, activePages: m };
463
564
  })
464
- ), i.get(
565
+ ), r.get(
465
566
  "/top-pages",
466
- A(async (o) => {
467
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = parseInt(l.limit || "10", 10), h = await a(u, d, {
468
- dateRanges: [{ startDate: f, endDate: g }],
567
+ b(async (o) => {
568
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = parseInt(l.limit || "10", 10), h = await a(d, u, {
569
+ dateRanges: [{ startDate: f, endDate: p }],
469
570
  dimensions: [{ name: "pagePath" }],
470
571
  metrics: [
471
572
  { name: "screenPageViews" },
@@ -475,23 +576,23 @@ function Yt(e) {
475
576
  orderBys: [{ metric: { metricName: "screenPageViews" }, desc: !0 }],
476
577
  limit: m * 2
477
578
  // fetch extra to account for duplicates before aggregation
478
- }), p = P(h, "pagePath"), w = /* @__PURE__ */ new Map();
479
- for (const b of p.rows) {
480
- const D = b.pagePath.toLowerCase().replace(/\/+$/, ""), F = w.get(D);
481
- if (F) {
482
- F.screenPageViews += b.screenPageViews || 0, F.totalUsers += b.totalUsers || 0;
483
- const M = F.screenPageViews;
484
- M > 0 && (F.averageSessionDuration = (F.averageSessionDuration * (M - (b.screenPageViews || 0)) + (b.averageSessionDuration || 0) * (b.screenPageViews || 0)) / M);
579
+ }), y = k(h, "pagePath"), w = /* @__PURE__ */ new Map();
580
+ for (const A of y.rows) {
581
+ const I = A.pagePath.toLowerCase().replace(/\/+$/, ""), M = w.get(I);
582
+ if (M) {
583
+ M.screenPageViews += A.screenPageViews || 0, M.totalUsers += A.totalUsers || 0;
584
+ const D = M.screenPageViews;
585
+ D > 0 && (M.averageSessionDuration = (M.averageSessionDuration * (D - (A.screenPageViews || 0)) + (A.averageSessionDuration || 0) * (A.screenPageViews || 0)) / D);
485
586
  } else
486
- w.set(D, { ...b });
587
+ w.set(I, { ...A });
487
588
  }
488
- return { rows: [...w.values()].sort((b, D) => (D.screenPageViews || 0) - (b.screenPageViews || 0)).slice(0, m), rowCount: p.rowCount };
589
+ return { rows: [...w.values()].sort((A, I) => (I.screenPageViews || 0) - (A.screenPageViews || 0)).slice(0, m), rowCount: y.rowCount };
489
590
  })
490
- ), i.get(
591
+ ), r.get(
491
592
  "/top-sources",
492
- A(async (o) => {
493
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
494
- dateRanges: [{ startDate: f, endDate: g }],
593
+ b(async (o) => {
594
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
595
+ dateRanges: [{ startDate: f, endDate: p }],
495
596
  dimensions: [{ name: "sessionSource" }],
496
597
  metrics: [
497
598
  { name: "sessions" },
@@ -500,13 +601,13 @@ function Yt(e) {
500
601
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
501
602
  limit: 10
502
603
  });
503
- return P(m, "sessionSource");
604
+ return k(m, "sessionSource");
504
605
  })
505
- ), i.get(
606
+ ), r.get(
506
607
  "/devices",
507
- A(async (o) => {
508
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
509
- dateRanges: [{ startDate: f, endDate: g }],
608
+ b(async (o) => {
609
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
610
+ dateRanges: [{ startDate: f, endDate: p }],
510
611
  dimensions: [{ name: "deviceCategory" }],
511
612
  metrics: [
512
613
  { name: "sessions" },
@@ -514,13 +615,13 @@ function Yt(e) {
514
615
  ],
515
616
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }]
516
617
  });
517
- return P(m, "deviceCategory");
618
+ return k(m, "deviceCategory");
518
619
  })
519
- ), i.get(
620
+ ), r.get(
520
621
  "/countries",
521
- A(async (o) => {
522
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
523
- dateRanges: [{ startDate: f, endDate: g }],
622
+ b(async (o) => {
623
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
624
+ dateRanges: [{ startDate: f, endDate: p }],
524
625
  dimensions: [{ name: "country" }],
525
626
  metrics: [
526
627
  { name: "sessions" },
@@ -529,13 +630,13 @@ function Yt(e) {
529
630
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
530
631
  limit: 10
531
632
  });
532
- return P(m, "country");
633
+ return k(m, "country");
533
634
  })
534
- ), i.get(
635
+ ), r.get(
535
636
  "/acquisition/channels",
536
- A(async (o) => {
537
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
538
- dateRanges: [{ startDate: f, endDate: g }],
637
+ b(async (o) => {
638
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
639
+ dateRanges: [{ startDate: f, endDate: p }],
539
640
  dimensions: [{ name: "sessionDefaultChannelGroup" }],
540
641
  metrics: [
541
642
  { name: "sessions" },
@@ -549,13 +650,13 @@ function Yt(e) {
549
650
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
550
651
  limit: 15
551
652
  });
552
- return P(m, "sessionDefaultChannelGroup");
653
+ return k(m, "sessionDefaultChannelGroup");
553
654
  })
554
- ), i.get(
655
+ ), r.get(
555
656
  "/acquisition/source-medium",
556
- A(async (o) => {
557
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
558
- dateRanges: [{ startDate: f, endDate: g }],
657
+ b(async (o) => {
658
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
659
+ dateRanges: [{ startDate: f, endDate: p }],
559
660
  dimensions: [{ name: "sessionSourceMedium" }],
560
661
  metrics: [
561
662
  { name: "sessions" },
@@ -568,13 +669,13 @@ function Yt(e) {
568
669
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
569
670
  limit: 20
570
671
  });
571
- return P(m, "sessionSourceMedium");
672
+ return k(m, "sessionSourceMedium");
572
673
  })
573
- ), i.get(
674
+ ), r.get(
574
675
  "/acquisition/referrals",
575
- A(async (o) => {
576
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
577
- dateRanges: [{ startDate: f, endDate: g }],
676
+ b(async (o) => {
677
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
678
+ dateRanges: [{ startDate: f, endDate: p }],
578
679
  dimensions: [{ name: "sessionSource" }],
579
680
  dimensionFilter: {
580
681
  filter: {
@@ -591,13 +692,13 @@ function Yt(e) {
591
692
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
592
693
  limit: 20
593
694
  });
594
- return P(m, "sessionSource");
695
+ return k(m, "sessionSource");
595
696
  })
596
- ), i.get(
697
+ ), r.get(
597
698
  "/acquisition/campaigns",
598
- A(async (o) => {
599
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
600
- dateRanges: [{ startDate: f, endDate: g }],
699
+ b(async (o) => {
700
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
701
+ dateRanges: [{ startDate: f, endDate: p }],
601
702
  dimensions: [{ name: "sessionCampaignName" }],
602
703
  dimensionFilter: {
603
704
  notExpression: {
@@ -616,13 +717,13 @@ function Yt(e) {
616
717
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
617
718
  limit: 20
618
719
  });
619
- return P(m, "sessionCampaignName");
720
+ return k(m, "sessionCampaignName");
620
721
  })
621
- ), i.get(
722
+ ), r.get(
622
723
  "/content/all-pages",
623
- A(async (o) => {
624
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = parseInt(l.limit || "50", 10), h = await a(u, d, {
625
- dateRanges: [{ startDate: f, endDate: g }],
724
+ b(async (o) => {
725
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = parseInt(l.limit || "50", 10), h = await a(d, u, {
726
+ dateRanges: [{ startDate: f, endDate: p }],
626
727
  dimensions: [{ name: "pagePath" }],
627
728
  metrics: [
628
729
  { name: "screenPageViews" },
@@ -636,13 +737,13 @@ function Yt(e) {
636
737
  orderBys: [{ metric: { metricName: "screenPageViews" }, desc: !0 }],
637
738
  limit: m
638
739
  });
639
- return P(h, "pagePath");
740
+ return k(h, "pagePath");
640
741
  })
641
- ), i.get(
742
+ ), r.get(
642
743
  "/content/landing-pages",
643
- A(async (o) => {
644
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
645
- dateRanges: [{ startDate: f, endDate: g }],
744
+ b(async (o) => {
745
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
746
+ dateRanges: [{ startDate: f, endDate: p }],
646
747
  dimensions: [{ name: "landingPagePlusQueryString" }],
647
748
  metrics: [
648
749
  { name: "sessions" },
@@ -655,13 +756,13 @@ function Yt(e) {
655
756
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
656
757
  limit: 30
657
758
  });
658
- return P(m, "landingPagePlusQueryString");
759
+ return k(m, "landingPagePlusQueryString");
659
760
  })
660
- ), i.get(
761
+ ), r.get(
661
762
  "/content/exit-pages",
662
- A(async (o) => {
663
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
664
- dateRanges: [{ startDate: f, endDate: g }],
763
+ b(async (o) => {
764
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
765
+ dateRanges: [{ startDate: f, endDate: p }],
665
766
  dimensions: [{ name: "pagePath" }],
666
767
  metrics: [
667
768
  { name: "sessions" },
@@ -671,51 +772,51 @@ function Yt(e) {
671
772
  ],
672
773
  orderBys: [{ metric: { metricName: "screenPageViews" }, desc: !0 }],
673
774
  limit: 20
674
- }), h = P(m, "pagePath");
675
- return h.rows = h.rows.map((p) => ({
676
- ...p,
677
- exitRate: p.bounceRate || 0
775
+ }), h = k(m, "pagePath");
776
+ return h.rows = h.rows.map((y) => ({
777
+ ...y,
778
+ exitRate: y.bounceRate || 0
678
779
  })), h;
679
780
  })
680
- ), i.get(
781
+ ), r.get(
681
782
  "/content/search-terms",
682
- A(async (o) => {
683
- const { accessToken: u, propertyId: d, siteUrl: l } = await r(o), f = R(o), g = f.startDate || "30daysAgo", m = f.endDate || "today";
783
+ b(async (o) => {
784
+ const { accessToken: d, propertyId: u, siteUrl: l } = await n(o), f = v(o), p = f.startDate || "30daysAgo", m = f.endDate || "today";
684
785
  if (l)
685
786
  try {
686
- const w = `${Fe}/sites/${encodeURIComponent(l)}/searchAnalytics/query`, C = await fetch(
787
+ const w = `${mt}/sites/${encodeURIComponent(l)}/searchAnalytics/query`, C = await fetch(
687
788
  w,
688
789
  {
689
790
  method: "POST",
690
791
  headers: {
691
- Authorization: `Bearer ${u}`,
792
+ Authorization: `Bearer ${d}`,
692
793
  "Content-Type": "application/json"
693
794
  },
694
795
  body: JSON.stringify({
695
- startDate: n(g),
696
- endDate: n(m),
796
+ startDate: c(p),
797
+ endDate: c(m),
697
798
  dimensions: ["query"],
698
799
  rowLimit: 30
699
800
  })
700
801
  }
701
802
  );
702
803
  if (C.ok) {
703
- const D = ((await C.json()).rows || []).map((F) => ({
704
- query: F.keys[0],
705
- clicks: F.clicks,
706
- impressions: F.impressions,
707
- ctr: F.ctr,
708
- position: F.position
804
+ const I = ((await C.json()).rows || []).map((M) => ({
805
+ query: M.keys[0],
806
+ clicks: M.clicks,
807
+ impressions: M.impressions,
808
+ ctr: M.ctr,
809
+ position: M.position
709
810
  }));
710
- if (D.length > 0)
811
+ if (I.length > 0)
711
812
  return {
712
- rows: D,
713
- rowCount: D.length,
813
+ rows: I,
814
+ rowCount: I.length,
714
815
  source: "search_console"
715
816
  };
716
817
  } else {
717
- const b = await C.text().catch(() => "");
718
- console.error(`[GA Module] Search Console API error (${C.status}):`, b);
818
+ const A = await C.text().catch(() => "");
819
+ console.error(`[GA Module] Search Console API error (${C.status}):`, A);
719
820
  }
720
821
  } catch (w) {
721
822
  console.error("[GA Module] Search Console request failed:", w?.message || w);
@@ -723,8 +824,8 @@ function Yt(e) {
723
824
  else
724
825
  console.log("[GA Module] No siteUrl configured, skipping Search Console");
725
826
  try {
726
- const w = await a(u, d, {
727
- dateRanges: [{ startDate: g, endDate: m }],
827
+ const w = await a(d, u, {
828
+ dateRanges: [{ startDate: p, endDate: m }],
728
829
  dimensions: [{ name: "sessionGoogleAdsQuery" }],
729
830
  metrics: [
730
831
  { name: "sessions" },
@@ -755,13 +856,13 @@ function Yt(e) {
755
856
  },
756
857
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
757
858
  limit: 30
758
- }), C = P(w, "sessionGoogleAdsQuery");
859
+ }), C = k(w, "sessionGoogleAdsQuery");
759
860
  if (C.rows.length > 0)
760
861
  return { ...C, source: "google_ads" };
761
862
  } catch {
762
863
  }
763
- const h = await a(u, d, {
764
- dateRanges: [{ startDate: g, endDate: m }],
864
+ const h = await a(d, u, {
865
+ dateRanges: [{ startDate: p, endDate: m }],
765
866
  dimensions: [{ name: "landingPagePlusQueryString" }],
766
867
  metrics: [
767
868
  { name: "sessions" },
@@ -794,13 +895,13 @@ function Yt(e) {
794
895
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
795
896
  limit: 30
796
897
  });
797
- return { ...P(h, "landingPagePlusQueryString"), source: "organic_landing_pages" };
898
+ return { ...k(h, "landingPagePlusQueryString"), source: "organic_landing_pages" };
798
899
  })
799
- ), i.get(
900
+ ), r.get(
800
901
  "/audience/overview",
801
- A(async (o) => {
802
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
803
- dateRanges: [{ startDate: f, endDate: g }],
902
+ b(async (o) => {
903
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
904
+ dateRanges: [{ startDate: f, endDate: p }],
804
905
  dimensions: [{ name: "newVsReturning" }],
805
906
  metrics: [
806
907
  { name: "totalUsers" },
@@ -811,14 +912,14 @@ function Yt(e) {
811
912
  ],
812
913
  metricAggregations: ["TOTAL"]
813
914
  });
814
- return P(m, "newVsReturning");
915
+ return k(m, "newVsReturning");
815
916
  })
816
- ), i.get(
917
+ ), r.get(
817
918
  "/audience/technology",
818
- A(async (o) => {
819
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = l.dimension || "browser", p = ["browser", "operatingSystem", "screenResolution"].includes(m) ? m : "browser", w = await a(u, d, {
820
- dateRanges: [{ startDate: f, endDate: g }],
821
- dimensions: [{ name: p }],
919
+ b(async (o) => {
920
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = l.dimension || "browser", y = ["browser", "operatingSystem", "screenResolution"].includes(m) ? m : "browser", w = await a(d, u, {
921
+ dateRanges: [{ startDate: f, endDate: p }],
922
+ dimensions: [{ name: y }],
822
923
  metrics: [
823
924
  { name: "totalUsers" },
824
925
  { name: "sessions" },
@@ -827,13 +928,13 @@ function Yt(e) {
827
928
  orderBys: [{ metric: { metricName: "totalUsers" }, desc: !0 }],
828
929
  limit: 10
829
930
  });
830
- return P(w, p);
931
+ return k(w, y);
831
932
  })
832
- ), i.get(
933
+ ), r.get(
833
934
  "/audience/languages",
834
- A(async (o) => {
835
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
836
- dateRanges: [{ startDate: f, endDate: g }],
935
+ b(async (o) => {
936
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
937
+ dateRanges: [{ startDate: f, endDate: p }],
837
938
  dimensions: [{ name: "language" }],
838
939
  metrics: [
839
940
  { name: "totalUsers" },
@@ -842,13 +943,13 @@ function Yt(e) {
842
943
  orderBys: [{ metric: { metricName: "totalUsers" }, desc: !0 }],
843
944
  limit: 15
844
945
  });
845
- return P(m, "language");
946
+ return k(m, "language");
846
947
  })
847
- ), i.get(
948
+ ), r.get(
848
949
  "/audience/hours",
849
- A(async (o) => {
850
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
851
- dateRanges: [{ startDate: f, endDate: g }],
950
+ b(async (o) => {
951
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
952
+ dateRanges: [{ startDate: f, endDate: p }],
852
953
  dimensions: [{ name: "dayOfWeekName" }, { name: "hour" }],
853
954
  metrics: [{ name: "sessions" }],
854
955
  orderBys: [
@@ -858,13 +959,13 @@ function Yt(e) {
858
959
  limit: 168
859
960
  // 7 days × 24 hours
860
961
  });
861
- return Ie(m, ["dayOfWeekName", "hour"]);
962
+ return ft(m, ["dayOfWeekName", "hour"]);
862
963
  })
863
- ), i.get(
964
+ ), r.get(
864
965
  "/audience/cities",
865
- A(async (o) => {
866
- const { accessToken: u, propertyId: d } = await r(o), l = R(o), f = l.startDate || "30daysAgo", g = l.endDate || "today", m = await a(u, d, {
867
- dateRanges: [{ startDate: f, endDate: g }],
966
+ b(async (o) => {
967
+ const { accessToken: d, propertyId: u } = await n(o), l = v(o), f = l.startDate || "30daysAgo", p = l.endDate || "today", m = await a(d, u, {
968
+ dateRanges: [{ startDate: f, endDate: p }],
868
969
  dimensions: [{ name: "city" }, { name: "country" }],
869
970
  metrics: [
870
971
  { name: "totalUsers" },
@@ -881,95 +982,95 @@ function Yt(e) {
881
982
  orderBys: [{ metric: { metricName: "totalUsers" }, desc: !0 }],
882
983
  limit: 20
883
984
  });
884
- return Ie(m, ["city", "country"]);
985
+ return ft(m, ["city", "country"]);
885
986
  })
886
987
  );
887
- function n(o) {
888
- const u = o.match(/^(\d+)daysAgo$/);
889
- if (u) {
890
- const d = /* @__PURE__ */ new Date();
891
- return d.setDate(d.getDate() - parseInt(u[1], 10)), d.toISOString().slice(0, 10);
988
+ function c(o) {
989
+ const d = o.match(/^(\d+)daysAgo$/);
990
+ if (d) {
991
+ const u = /* @__PURE__ */ new Date();
992
+ return u.setDate(u.getDate() - parseInt(d[1], 10)), u.toISOString().slice(0, 10);
892
993
  }
893
994
  if (o === "today") return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
894
995
  if (o === "yesterday") {
895
- const d = /* @__PURE__ */ new Date();
896
- return d.setDate(d.getDate() - 1), d.toISOString().slice(0, 10);
996
+ const u = /* @__PURE__ */ new Date();
997
+ return u.setDate(u.getDate() - 1), u.toISOString().slice(0, 10);
897
998
  }
898
999
  return o;
899
1000
  }
900
- async function c(o, u, d) {
901
- const l = `${Fe}/sites/${encodeURIComponent(u)}/searchAnalytics/query`, f = await fetch(l, {
1001
+ async function i(o, d, u) {
1002
+ const l = `${mt}/sites/${encodeURIComponent(d)}/searchAnalytics/query`, f = await fetch(l, {
902
1003
  method: "POST",
903
1004
  headers: {
904
1005
  Authorization: `Bearer ${o}`,
905
1006
  "Content-Type": "application/json"
906
1007
  },
907
- body: JSON.stringify(d)
1008
+ body: JSON.stringify(u)
908
1009
  });
909
1010
  if (!f.ok) {
910
- const g = await f.json().catch(() => ({}));
911
- throw y({
1011
+ const p = await f.json().catch(() => ({}));
1012
+ throw g({
912
1013
  statusCode: f.status,
913
- statusMessage: g?.error?.message || "Search Console API request failed"
1014
+ statusMessage: p?.error?.message || "Search Console API request failed"
914
1015
  });
915
1016
  }
916
1017
  return f.json();
917
1018
  }
918
- return i.get(
1019
+ return r.get(
919
1020
  "/seo/keywords",
920
- A(async (o) => {
921
- const { accessToken: u, siteUrl: d } = await r(o);
922
- if (!d)
923
- throw y({ statusCode: 400, statusMessage: "Search Console Site URL is not configured. Add it in module settings." });
924
- const l = R(o), f = n(l.startDate || "30daysAgo"), g = n(l.endDate || "today"), m = Math.min(parseInt(l.limit) || 50, 100), h = await c(u, d, {
1021
+ b(async (o) => {
1022
+ const { accessToken: d, siteUrl: u } = await n(o);
1023
+ if (!u)
1024
+ throw g({ statusCode: 400, statusMessage: "Search Console Site URL is not configured. Add it in module settings." });
1025
+ const l = v(o), f = c(l.startDate || "30daysAgo"), p = c(l.endDate || "today"), m = Math.min(parseInt(l.limit) || 50, 100), h = await i(d, u, {
925
1026
  startDate: f,
926
- endDate: g,
1027
+ endDate: p,
927
1028
  dimensions: ["query"],
928
1029
  rowLimit: m
929
1030
  });
930
1031
  return {
931
- rows: (h.rows || []).map((p) => ({
932
- query: p.keys[0],
933
- clicks: p.clicks,
934
- impressions: p.impressions,
935
- ctr: p.ctr,
936
- position: p.position
1032
+ rows: (h.rows || []).map((y) => ({
1033
+ query: y.keys[0],
1034
+ clicks: y.clicks,
1035
+ impressions: y.impressions,
1036
+ ctr: y.ctr,
1037
+ position: y.position
937
1038
  })),
938
1039
  rowCount: h.rows?.length || 0
939
1040
  };
940
1041
  })
941
- ), i.get(
1042
+ ), r.get(
942
1043
  "/seo/pages",
943
- A(async (o) => {
944
- const { accessToken: u, siteUrl: d } = await r(o);
945
- if (!d)
946
- throw y({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
947
- const l = R(o), f = n(l.startDate || "30daysAgo"), g = n(l.endDate || "today"), m = Math.min(parseInt(l.limit) || 50, 100), h = await c(u, d, {
1044
+ b(async (o) => {
1045
+ const { accessToken: d, siteUrl: u } = await n(o);
1046
+ if (!u)
1047
+ throw g({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
1048
+ const l = v(o), f = c(l.startDate || "30daysAgo"), p = c(l.endDate || "today"), m = Math.min(parseInt(l.limit) || 50, 100), h = await i(d, u, {
948
1049
  startDate: f,
949
- endDate: g,
1050
+ endDate: p,
950
1051
  dimensions: ["page"],
951
1052
  rowLimit: m
952
1053
  });
953
1054
  return {
954
- rows: (h.rows || []).map((p) => ({
955
- page: p.keys[0],
956
- clicks: p.clicks,
957
- impressions: p.impressions,
958
- ctr: p.ctr,
959
- position: p.position
1055
+ rows: (h.rows || []).map((y) => ({
1056
+ page: y.keys[0],
1057
+ clicks: y.clicks,
1058
+ impressions: y.impressions,
1059
+ ctr: y.ctr,
1060
+ position: y.position
960
1061
  })),
961
1062
  rowCount: h.rows?.length || 0
962
1063
  };
963
1064
  })
964
- ), i.get(
1065
+ ), r.get(
965
1066
  "/seo/trends",
966
- A(async (o) => {
967
- const { accessToken: u, siteUrl: d } = await r(o);
968
- if (!d)
969
- throw y({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
970
- const l = R(o), f = n(l.startDate || "30daysAgo"), g = n(l.endDate || "today"), h = ((await c(u, d, {
1067
+ b(async (o) => {
1068
+ const { accessToken: d, siteUrl: u } = await n(o);
1069
+ if (!u)
1070
+ throw g({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
1071
+ const l = v(o), f = c(l.startDate || "30daysAgo"), p = c(l.endDate || "today"), h = ((await i(d, u, {
971
1072
  startDate: f,
972
- endDate: g,
1073
+ endDate: p,
973
1074
  dimensions: ["date"],
974
1075
  rowLimit: 500
975
1076
  })).rows || []).map((w) => ({
@@ -978,24 +1079,24 @@ function Yt(e) {
978
1079
  impressions: w.impressions,
979
1080
  ctr: w.ctr,
980
1081
  position: w.position
981
- })).sort((w, C) => w.date.localeCompare(C.date)), p = h.reduce(
1082
+ })).sort((w, C) => w.date.localeCompare(C.date)), y = h.reduce(
982
1083
  (w, C) => ({
983
1084
  clicks: w.clicks + C.clicks,
984
1085
  impressions: w.impressions + C.impressions
985
1086
  }),
986
1087
  { clicks: 0, impressions: 0 }
987
1088
  );
988
- return p.ctr = p.impressions > 0 ? p.clicks / p.impressions : 0, p.avgPosition = h.length > 0 ? h.reduce((w, C) => w + C.position, 0) / h.length : 0, { rows: h, totals: p, rowCount: h.length };
1089
+ return y.ctr = y.impressions > 0 ? y.clicks / y.impressions : 0, y.avgPosition = h.length > 0 ? h.reduce((w, C) => w + C.position, 0) / h.length : 0, { rows: h, totals: y, rowCount: h.length };
989
1090
  })
990
- ), i.get(
1091
+ ), r.get(
991
1092
  "/seo/query-pages",
992
- A(async (o) => {
993
- const { accessToken: u, siteUrl: d } = await r(o);
994
- if (!d)
995
- throw y({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
996
- const l = R(o), f = n(l.startDate || "30daysAgo"), g = n(l.endDate || "today"), m = await c(u, d, {
1093
+ b(async (o) => {
1094
+ const { accessToken: d, siteUrl: u } = await n(o);
1095
+ if (!u)
1096
+ throw g({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
1097
+ const l = v(o), f = c(l.startDate || "30daysAgo"), p = c(l.endDate || "today"), m = await i(d, u, {
997
1098
  startDate: f,
998
- endDate: g,
1099
+ endDate: p,
999
1100
  dimensions: ["query", "page"],
1000
1101
  rowLimit: 100
1001
1102
  });
@@ -1011,88 +1112,88 @@ function Yt(e) {
1011
1112
  rowCount: m.rows?.length || 0
1012
1113
  };
1013
1114
  })
1014
- ), i.handler;
1115
+ ), r.handler;
1015
1116
  }
1016
- function et(e, t = !0) {
1017
- const s = (e.metricHeaders || []).map((f) => f.name), r = (e.dimensionHeaders || []).map((f) => f.name).indexOf("date"), a = [];
1117
+ function ms(e, t = !0) {
1118
+ const s = (e.metricHeaders || []).map((f) => f.name), n = (e.dimensionHeaders || []).map((f) => f.name).indexOf("date"), a = [];
1018
1119
  (e.rows || []).forEach((f) => {
1019
- const g = r >= 0 ? f.dimensionValues[r]?.value : f.dimensionValues[0]?.value;
1020
- if (!g || g.length < 8) return;
1021
- const h = { date: `${g.slice(0, 4)}-${g.slice(4, 6)}-${g.slice(6, 8)}` };
1022
- s.forEach((p, w) => {
1023
- h[p] = parseFloat(f.metricValues[w]?.value || "0");
1120
+ const p = n >= 0 ? f.dimensionValues[n]?.value : f.dimensionValues[0]?.value;
1121
+ if (!p || p.length < 8) return;
1122
+ const h = { date: `${p.slice(0, 4)}-${p.slice(4, 6)}-${p.slice(6, 8)}` };
1123
+ s.forEach((y, w) => {
1124
+ h[y] = parseFloat(f.metricValues[w]?.value || "0");
1024
1125
  }), a.push(h);
1025
1126
  });
1026
- const n = {}, c = {};
1027
- e.totals && e.totals.length >= 2 ? s.forEach((f, g) => {
1028
- n[f] = parseFloat(e.totals[0]?.metricValues?.[g]?.value || "0"), c[f] = parseFloat(e.totals[1]?.metricValues?.[g]?.value || "0");
1029
- }) : e.totals && e.totals.length === 1 && s.forEach((f, g) => {
1030
- n[f] = parseFloat(e.totals[0]?.metricValues?.[g]?.value || "0");
1127
+ const c = {}, i = {};
1128
+ e.totals && e.totals.length >= 2 ? s.forEach((f, p) => {
1129
+ c[f] = parseFloat(e.totals[0]?.metricValues?.[p]?.value || "0"), i[f] = parseFloat(e.totals[1]?.metricValues?.[p]?.value || "0");
1130
+ }) : e.totals && e.totals.length === 1 && s.forEach((f, p) => {
1131
+ c[f] = parseFloat(e.totals[0]?.metricValues?.[p]?.value || "0");
1031
1132
  });
1032
1133
  const o = {};
1033
1134
  s.forEach((f) => {
1034
- const g = n[f] || 0, m = c[f];
1035
- m !== void 0 && m !== 0 ? o[f] = (g - m) / m * 100 : o[f] = null;
1135
+ const p = c[f] || 0, m = i[f];
1136
+ m !== void 0 && m !== 0 ? o[f] = (p - m) / m * 100 : o[f] = null;
1036
1137
  });
1037
- const u = /* @__PURE__ */ new Map();
1138
+ const d = /* @__PURE__ */ new Map();
1038
1139
  for (const f of a)
1039
- u.has(f.date) || u.set(f.date, f);
1040
- const d = Array.from(u.values()).sort((f, g) => f.date.localeCompare(g.date)), l = t && e.totals && e.totals.length >= 2 ? d.slice(-Math.ceil(d.length / 2)) : d;
1140
+ d.has(f.date) || d.set(f.date, f);
1141
+ const u = Array.from(d.values()).sort((f, p) => f.date.localeCompare(p.date)), l = t && e.totals && e.totals.length >= 2 ? u.slice(-Math.ceil(u.length / 2)) : u;
1041
1142
  return {
1042
1143
  rows: l,
1043
- totals: n,
1044
- previousTotals: c,
1144
+ totals: c,
1145
+ previousTotals: i,
1045
1146
  changes: o,
1046
1147
  rowCount: l.length
1047
1148
  };
1048
1149
  }
1049
- function P(e, t) {
1050
- const s = (e.metricHeaders || []).map((r) => r.name), i = (e.rows || []).map((r) => {
1150
+ function k(e, t) {
1151
+ const s = (e.metricHeaders || []).map((n) => n.name), r = (e.rows || []).map((n) => {
1051
1152
  const a = {
1052
- [t]: r.dimensionValues[0].value
1153
+ [t]: n.dimensionValues[0].value
1053
1154
  };
1054
- return s.forEach((n, c) => {
1055
- a[n] = parseFloat(r.metricValues[c].value);
1155
+ return s.forEach((c, i) => {
1156
+ a[c] = parseFloat(n.metricValues[i].value);
1056
1157
  }), a;
1057
1158
  });
1058
- return { rows: i, rowCount: e.rowCount || i.length };
1159
+ return { rows: r, rowCount: e.rowCount || r.length };
1059
1160
  }
1060
- function Ie(e, t) {
1061
- const s = (e.metricHeaders || []).map((r) => r.name), i = (e.rows || []).map((r) => {
1161
+ function ft(e, t) {
1162
+ const s = (e.metricHeaders || []).map((n) => n.name), r = (e.rows || []).map((n) => {
1062
1163
  const a = {};
1063
- return t.forEach((n, c) => {
1064
- a[n] = r.dimensionValues[c]?.value || "";
1065
- }), s.forEach((n, c) => {
1066
- a[n] = parseFloat(r.metricValues[c].value);
1164
+ return t.forEach((c, i) => {
1165
+ a[c] = n.dimensionValues[i]?.value || "";
1166
+ }), s.forEach((c, i) => {
1167
+ a[c] = parseFloat(n.metricValues[i].value);
1067
1168
  }), a;
1068
1169
  });
1069
- return { rows: i, rowCount: e.rowCount || i.length };
1070
- }
1071
- function Kt(e) {
1072
- const { decrypt: t } = e, s = se();
1073
- async function i(r) {
1074
- const { supabase: a, instanceId: n } = r.context.module, { data: c, error: o } = await a.from("project_modules").select("config").eq("id", n).single();
1075
- if (o || !c?.config)
1076
- throw y({ statusCode: 500, statusMessage: "Failed to load module config." });
1077
- const u = c.config, d = u.githubIntegration, l = u.githubRepo, f = u.githubOwner;
1078
- if (!d || !l || !f)
1079
- throw y({ statusCode: 400, statusMessage: "No GitHub integration configured for this module." });
1080
- const { data: g, error: m } = await a.from("integrations").select("config").eq("id", d).single();
1081
- let h = g?.config;
1170
+ return { rows: r, rowCount: e.rowCount || r.length };
1171
+ }
1172
+ function Ta(e) {
1173
+ const { decrypt: t } = e, s = J();
1174
+ async function r(n) {
1175
+ const { supabase: a, instanceId: c } = n.context.module, { data: i, error: o } = await a.from("project_modules").select("config").eq("id", c).single();
1176
+ if (o || !i?.config)
1177
+ throw g({ statusCode: 500, statusMessage: "Failed to load module config." });
1178
+ const d = i.config, u = d.githubIntegration, l = d.githubRepo, f = d.githubOwner;
1179
+ if (!u || !l || !f)
1180
+ throw g({ statusCode: 400, statusMessage: "No GitHub integration configured for this module." });
1181
+ const { data: p, error: m } = await a.from("integrations").select("config").eq("id", u).single();
1182
+ let h = p?.config;
1082
1183
  if (m || !h) {
1083
- const { data: w, error: C } = await a.from("agency_integrations").select("config").eq("id", d).single();
1184
+ const { data: w, error: C } = await a.from("agency_integrations").select("config").eq("id", u).single();
1084
1185
  if (C || !w?.config)
1085
- throw y({ statusCode: 500, statusMessage: "Failed to load Github credentials." });
1186
+ throw g({ statusCode: 500, statusMessage: "Failed to load Github credentials." });
1086
1187
  h = w.config;
1087
1188
  }
1088
1189
  return { token: t(h.token), repo: l, owner: f };
1089
1190
  }
1090
1191
  return s.post(
1091
1192
  "/github/deploy",
1092
- A(async (r) => {
1193
+ b(async (n) => {
1093
1194
  try {
1094
- const { token: a, repo: n, owner: c } = await i(r);
1095
- await fetch(`https://api.github.com/repos/${c}/${n}/dispatches`, {
1195
+ const { token: a, repo: c, owner: i } = await r(n);
1196
+ await fetch(`https://api.github.com/repos/${i}/${c}/dispatches`, {
1096
1197
  method: "POST",
1097
1198
  headers: {
1098
1199
  Authorization: `Bearer ${a}`,
@@ -1103,12 +1204,12 @@ function Kt(e) {
1103
1204
  })
1104
1205
  });
1105
1206
  } catch (a) {
1106
- throw console.error("Error triggering GitHub deployment:", a), y({ statusCode: 500, statusMessage: "Failed to trigger deployment." });
1207
+ throw console.error("Error triggering GitHub deployment:", a), g({ statusCode: 500, statusMessage: "Failed to trigger deployment." });
1107
1208
  }
1108
1209
  })
1109
1210
  ), s.handler;
1110
1211
  }
1111
- const Oe = "firebaseAuthManager", v = {
1212
+ const Ot = "firebaseAuthManager", $ = {
1112
1213
  viewUsers: "view-auth-users",
1113
1214
  viewPii: "view-auth-user-pii",
1114
1215
  createUsers: "create-auth-users",
@@ -1119,39 +1220,39 @@ const Oe = "firebaseAuthManager", v = {
1119
1220
  manageRoles: "manage-auth-roles",
1120
1221
  manageProfiles: "manage-auth-profiles",
1121
1222
  deleteUsers: "delete-auth-users"
1122
- }, Be = B().trim().email().max(254), he = B().min(1).max(128), tt = he.refine((e) => e === e.trim(), {
1223
+ }, jt = x().trim().email().max(254), Qe = x().min(1).max(128), fs = Qe.refine((e) => e === e.trim(), {
1123
1224
  message: "Custom UID may not begin or end with whitespace."
1124
- }), je = B().trim().regex(/^\+[1-9]\d{1,14}$/, "Phone number must use E.164 format."), st = B().email().max(254), at = B().regex(/^\+[1-9]\d{1,14}$/, "Phone number must use E.164 format."), ne = B().trim().min(3).max(500), $e = B().trim().min(1).max(128), ot = ae({
1125
- email: Be,
1126
- password: B().min(8).max(128),
1127
- uid: tt.optional(),
1128
- displayName: $e.optional(),
1129
- phoneNumber: je.optional(),
1130
- emailVerified: re().optional(),
1131
- disabled: re().optional(),
1132
- createProfile: re().optional().default(!1)
1133
- }).strict(), rt = ae({
1134
- reason: ne,
1135
- displayName: $e.nullable().optional(),
1136
- email: Be.optional(),
1137
- phoneNumber: je.nullable().optional(),
1138
- emailVerified: re().optional()
1139
- }).strict().refine((e) => Y(e, "displayName") || Y(e, "email") || Y(e, "phoneNumber") || Y(e, "emailVerified"), {
1225
+ }), qt = x().trim().regex(/^\+[1-9]\d{1,14}$/, "Phone number must use E.164 format."), ps = x().email().max(254), gs = x().regex(/^\+[1-9]\d{1,14}$/, "Phone number must use E.164 format."), Re = x().trim().min(3).max(500), $t = x().trim().min(1).max(128), hs = O({
1226
+ email: jt,
1227
+ password: x().min(8).max(128),
1228
+ uid: fs.optional(),
1229
+ displayName: $t.optional(),
1230
+ phoneNumber: qt.optional(),
1231
+ emailVerified: _e().optional(),
1232
+ disabled: _e().optional(),
1233
+ createProfile: _e().optional().default(!1)
1234
+ }).strict(), ys = O({
1235
+ reason: Re,
1236
+ displayName: $t.nullable().optional(),
1237
+ email: jt.optional(),
1238
+ phoneNumber: qt.nullable().optional(),
1239
+ emailVerified: _e().optional()
1240
+ }).strict().refine((e) => re(e, "displayName") || re(e, "email") || re(e, "phoneNumber") || re(e, "emailVerified"), {
1140
1241
  message: "At least one editable user field is required."
1141
- }), nt = ae({
1142
- disabled: re(),
1143
- reason: ne
1144
- }).strict(), fe = ae({
1145
- reason: ne
1146
- }).strict(), it = ae({
1147
- role: B().trim().min(1).max(64).nullable(),
1148
- reason: ne
1149
- }).strict(), ct = ae({
1150
- reason: ne,
1242
+ }), ws = O({
1243
+ disabled: _e(),
1244
+ reason: Re
1245
+ }).strict(), $e = O({
1246
+ reason: Re
1247
+ }).strict(), bs = O({
1248
+ role: x().trim().min(1).max(64).nullable(),
1249
+ reason: Re
1250
+ }).strict(), Cs = O({
1251
+ reason: Re,
1151
1252
  // Deliberately do not trim this value: destructive confirmation must be an
1152
1253
  // exact byte-for-byte match with the UID shown to the operator.
1153
- confirmation: B().min(1).max(128)
1154
- }).strict(), dt = /* @__PURE__ */ new Set([
1254
+ confirmation: x().min(1).max(128)
1255
+ }).strict(), As = /* @__PURE__ */ new Set([
1155
1256
  "acr",
1156
1257
  "amr",
1157
1258
  "at_hash",
@@ -1174,188 +1275,188 @@ const Oe = "firebaseAuthManager", v = {
1174
1275
  "picture",
1175
1276
  "sub",
1176
1277
  "user_id"
1177
- ]), ut = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
1178
- function Y(e, t) {
1278
+ ]), Is = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
1279
+ function re(e, t) {
1179
1280
  return Object.prototype.hasOwnProperty.call(e, t);
1180
1281
  }
1181
- function K(e) {
1182
- throw y({ statusCode: 400, statusMessage: e });
1282
+ function ce(e) {
1283
+ throw g({ statusCode: 400, statusMessage: e });
1183
1284
  }
1184
- function Re(e, t) {
1285
+ function pt(e, t) {
1185
1286
  return typeof e == "boolean" ? e : e === "true" ? !0 : e === "false" ? !1 : t;
1186
1287
  }
1187
- function Ve(e) {
1288
+ function Bt(e) {
1188
1289
  const t = typeof e == "number" ? e : Number(e);
1189
1290
  return Number.isFinite(t) ? Math.min(100, Math.max(10, Math.trunc(t))) : 50;
1190
1291
  }
1191
- function lt(e) {
1292
+ function Ms(e) {
1192
1293
  const t = String(e || "users").trim();
1193
- return t.length === 0 || t.length > 256 || t.includes("/") || t === "." || t === ".." || /^__.*__$/.test(t) ? K("The configured Firestore profile collection is invalid.") : t;
1294
+ return t.length === 0 || t.length > 256 || t.includes("/") || t === "." || t === ".." || /^__.*__$/.test(t) ? ce("The configured Firestore profile collection is invalid.") : t;
1194
1295
  }
1195
- function W(e, t, s) {
1196
- const i = String(e ?? t).trim() || t;
1197
- return i.length > 128 || !/^[A-Za-z_][A-Za-z0-9_-]*$/.test(i) || ut.has(i) ? K(`The configured ${s} field is invalid.`) : i;
1296
+ function ge(e, t, s) {
1297
+ const r = String(e ?? t).trim() || t;
1298
+ return r.length > 128 || !/^[A-Za-z_][A-Za-z0-9_-]*$/.test(r) || Is.has(r) ? ce(`The configured ${s} field is invalid.`) : r;
1198
1299
  }
1199
- function mt(e) {
1300
+ function Ss(e) {
1200
1301
  const t = Array.isArray(e) ? e : String(e || "").split(","), s = [];
1201
- for (const i of t) {
1202
- if (typeof i != "string")
1203
- return K("Configured role options must be strings.");
1204
- const r = i.trim();
1205
- if (r) {
1206
- if (r.length > 64)
1207
- return K("Configured role options may not exceed 64 characters.");
1208
- s.includes(r) || s.push(r);
1302
+ for (const r of t) {
1303
+ if (typeof r != "string")
1304
+ return ce("Configured role options must be strings.");
1305
+ const n = r.trim();
1306
+ if (n) {
1307
+ if (n.length > 64)
1308
+ return ce("Configured role options may not exceed 64 characters.");
1309
+ s.includes(n) || s.push(n);
1209
1310
  }
1210
1311
  }
1211
- return s.length > 50 ? K("No more than 50 role options may be configured.") : s;
1312
+ return s.length > 50 ? ce("No more than 50 role options may be configured.") : s;
1212
1313
  }
1213
- function ft(e) {
1314
+ function Ds(e) {
1214
1315
  const t = typeof e.project == "string" ? e.project.trim() : "";
1215
- t || K("Firebase Auth Manager has no Firebase integration configured.");
1216
- const s = Re(e.manageRoleClaim, !1), i = W(e.roleClaimKey, "role", "role claim");
1217
- s && dt.has(i) && K("The configured role claim key is reserved by Firebase.");
1218
- const r = {
1219
- profileUidField: W(e.profileUidField, "uid", "profile UID"),
1220
- profileNameField: W(e.profileNameField, "displayName", "profile name"),
1221
- profileEmailField: W(e.profileEmailField, "email", "profile email"),
1222
- profileRoleField: W(e.profileRoleField, "role", "profile role"),
1223
- profileStatusField: W(e.profileStatusField, "status", "profile status")
1316
+ t || ce("Firebase Auth Manager has no Firebase integration configured.");
1317
+ const s = pt(e.manageRoleClaim, !1), r = ge(e.roleClaimKey, "role", "role claim");
1318
+ s && As.has(r) && ce("The configured role claim key is reserved by Firebase.");
1319
+ const n = {
1320
+ profileUidField: ge(e.profileUidField, "uid", "profile UID"),
1321
+ profileNameField: ge(e.profileNameField, "displayName", "profile name"),
1322
+ profileEmailField: ge(e.profileEmailField, "email", "profile email"),
1323
+ profileRoleField: ge(e.profileRoleField, "role", "profile role"),
1324
+ profileStatusField: ge(e.profileStatusField, "status", "profile status")
1224
1325
  };
1225
- return new Set(Object.values(r)).size !== Object.keys(r).length && K("Each configured Firestore profile field must use a distinct field name."), {
1326
+ return new Set(Object.values(n)).size !== Object.keys(n).length && ce("Each configured Firestore profile field must use a distinct field name."), {
1226
1327
  project: t,
1227
- pageSize: Ve(e.pageSize),
1228
- linkFirestoreProfiles: Re(e.linkFirestoreProfiles, !0),
1229
- profileCollection: lt(e.profileCollection),
1230
- ...r,
1328
+ pageSize: Bt(e.pageSize),
1329
+ linkFirestoreProfiles: pt(e.linkFirestoreProfiles, !0),
1330
+ profileCollection: Ms(e.profileCollection),
1331
+ ...n,
1231
1332
  manageRoleClaim: s,
1232
- roleClaimKey: i,
1233
- roleOptions: mt(e.roleOptions)
1333
+ roleClaimKey: r,
1334
+ roleOptions: Ss(e.roleOptions)
1234
1335
  };
1235
1336
  }
1236
- function Me(e) {
1337
+ function gt(e) {
1237
1338
  const t = Array.isArray(e) ? e[0] : e;
1238
1339
  return typeof t != "string" ? void 0 : t.trim() || void 0;
1239
1340
  }
1240
- function Se(e) {
1341
+ function ht(e) {
1241
1342
  const t = Array.isArray(e) ? e[0] : e;
1242
1343
  if (!(typeof t != "string" || t.length === 0))
1243
1344
  return t;
1244
1345
  }
1245
- function gt(e, t = 50) {
1246
- const s = Me(e.limit);
1247
- let i = Ve(t);
1346
+ function Ts(e, t = 50) {
1347
+ const s = gt(e.limit);
1348
+ let r = Bt(t);
1248
1349
  if (s !== void 0) {
1249
1350
  if (!/^\d+$/.test(s))
1250
- throw y({ statusCode: 422, statusMessage: "Limit must be a whole number." });
1251
- if (i = Number(s), i < 1 || i > 100)
1252
- throw y({ statusCode: 422, statusMessage: "Limit must be between 1 and 100." });
1351
+ throw g({ statusCode: 422, statusMessage: "Limit must be a whole number." });
1352
+ if (r = Number(s), r < 1 || r > 100)
1353
+ throw g({ statusCode: 422, statusMessage: "Limit must be between 1 and 100." });
1253
1354
  }
1254
- const r = Se(e.pageToken);
1255
- if (r && r.length > 4096)
1256
- throw y({ statusCode: 422, statusMessage: "Page token is too long." });
1257
- const a = Se(e.search), n = Me(e.searchBy);
1258
- if (n && !a)
1259
- throw y({ statusCode: 422, statusMessage: "Search mode requires a search value." });
1260
- if (!a) return { limit: i, pageToken: r };
1261
- if (r)
1262
- throw y({ statusCode: 422, statusMessage: "Exact search cannot be combined with a page token." });
1263
- const c = n || "uid";
1264
- if (!["uid", "email", "phone"].includes(c))
1265
- throw y({ statusCode: 422, statusMessage: "Search mode must be uid, email, or phone." });
1266
- if (c === "phone") {
1267
- const u = at.safeParse(a);
1268
- if (!u.success)
1269
- throw y({ statusCode: 422, statusMessage: "Phone search must use E.164 format." });
1270
- return { limit: 1, search: { kind: "phone", value: u.data } };
1355
+ const n = ht(e.pageToken);
1356
+ if (n && n.length > 4096)
1357
+ throw g({ statusCode: 422, statusMessage: "Page token is too long." });
1358
+ const a = ht(e.search), c = gt(e.searchBy);
1359
+ if (c && !a)
1360
+ throw g({ statusCode: 422, statusMessage: "Search mode requires a search value." });
1361
+ if (!a) return { limit: r, pageToken: n };
1362
+ if (n)
1363
+ throw g({ statusCode: 422, statusMessage: "Exact search cannot be combined with a page token." });
1364
+ const i = c || "uid";
1365
+ if (!["uid", "email", "phone"].includes(i))
1366
+ throw g({ statusCode: 422, statusMessage: "Search mode must be uid, email, or phone." });
1367
+ if (i === "phone") {
1368
+ const d = gs.safeParse(a);
1369
+ if (!d.success)
1370
+ throw g({ statusCode: 422, statusMessage: "Phone search must use E.164 format." });
1371
+ return { limit: 1, search: { kind: "phone", value: d.data } };
1271
1372
  }
1272
- if (c === "email") {
1273
- const u = st.safeParse(a);
1274
- if (!u.success)
1275
- throw y({ statusCode: 422, statusMessage: "Email search is invalid." });
1276
- return { limit: 1, search: { kind: "email", value: u.data } };
1373
+ if (i === "email") {
1374
+ const d = ps.safeParse(a);
1375
+ if (!d.success)
1376
+ throw g({ statusCode: 422, statusMessage: "Email search is invalid." });
1377
+ return { limit: 1, search: { kind: "email", value: d.data } };
1277
1378
  }
1278
- const o = he.safeParse(a);
1379
+ const o = Qe.safeParse(a);
1279
1380
  if (!o.success)
1280
- throw y({ statusCode: 422, statusMessage: "UID search is invalid." });
1381
+ throw g({ statusCode: 422, statusMessage: "UID search is invalid." });
1281
1382
  return { limit: 1, search: { kind: "uid", value: o.data } };
1282
1383
  }
1283
- function pt(e) {
1384
+ function vs(e) {
1284
1385
  const t = new TextEncoder().encode(e);
1285
1386
  let s = "";
1286
- for (const i of t) s += String.fromCharCode(i);
1387
+ for (const r of t) s += String.fromCharCode(r);
1287
1388
  return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
1288
1389
  }
1289
- function ht(e) {
1390
+ function _s(e) {
1290
1391
  if (!/^[A-Za-z0-9_-]{1,1024}$/.test(e))
1291
- throw y({ statusCode: 400, statusMessage: "Firebase UID token is invalid." });
1392
+ throw g({ statusCode: 400, statusMessage: "Firebase UID token is invalid." });
1292
1393
  const t = e.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(e.length / 4) * 4, "=");
1293
1394
  let s;
1294
1395
  try {
1295
- const i = atob(t), r = Uint8Array.from(i, (a) => a.charCodeAt(0));
1296
- s = new TextDecoder("utf-8", { fatal: !0 }).decode(r);
1396
+ const r = atob(t), n = Uint8Array.from(r, (a) => a.charCodeAt(0));
1397
+ s = new TextDecoder("utf-8", { fatal: !0 }).decode(n);
1297
1398
  } catch {
1298
- throw y({ statusCode: 400, statusMessage: "Firebase UID token is invalid." });
1399
+ throw g({ statusCode: 400, statusMessage: "Firebase UID token is invalid." });
1299
1400
  }
1300
- if (pt(s) !== e || !he.safeParse(s).success)
1301
- throw y({ statusCode: 400, statusMessage: "Firebase UID token is invalid." });
1401
+ if (vs(s) !== e || !Qe.safeParse(s).success)
1402
+ throw g({ statusCode: 400, statusMessage: "Firebase UID token is invalid." });
1302
1403
  return s;
1303
1404
  }
1304
- function ye(e, t) {
1405
+ function Ze(e, t) {
1305
1406
  return e.isAdmin === !0 || Array.isArray(e.permissions) && e.permissions.includes(t);
1306
1407
  }
1307
- function yt(e, t) {
1308
- return t.kind === "uid" || ye(e, v.viewPii);
1408
+ function Rs(e, t) {
1409
+ return t.kind === "uid" || Ze(e, $.viewPii);
1309
1410
  }
1310
- function wt(e, t) {
1411
+ function xs(e, t) {
1311
1412
  let s = e.length ^ t.length;
1312
- const i = Math.max(e.length, t.length);
1313
- for (let r = 0; r < i; r += 1)
1314
- s |= (e.charCodeAt(r) || 0) ^ (t.charCodeAt(r) || 0);
1413
+ const r = Math.max(e.length, t.length);
1414
+ for (let n = 0; n < r; n += 1)
1415
+ s |= (e.charCodeAt(n) || 0) ^ (t.charCodeAt(n) || 0);
1315
1416
  return s === 0;
1316
1417
  }
1317
- function T(e, t) {
1318
- if (!ye(e, t))
1319
- throw y({ statusCode: 403, statusMessage: "You do not have permission to perform this action." });
1418
+ function H(e, t) {
1419
+ if (!Ze(e, t))
1420
+ throw g({ statusCode: 403, statusMessage: "You do not have permission to perform this action." });
1320
1421
  }
1321
- function ze(e) {
1422
+ function Lt(e) {
1322
1423
  if (!e) return null;
1323
1424
  const t = e.lastIndexOf("@");
1324
1425
  if (t <= 0) return "••••";
1325
- const s = e.slice(0, t), i = e.slice(t + 1), r = i.lastIndexOf("."), a = r > 0 ? i.slice(0, r) : i, n = r > 0 ? i.slice(r) : "";
1326
- return `${s.slice(0, 1)}•••@${a.slice(0, 1)}•••${n}`;
1426
+ const s = e.slice(0, t), r = e.slice(t + 1), n = r.lastIndexOf("."), a = n > 0 ? r.slice(0, n) : r, c = n > 0 ? r.slice(n) : "";
1427
+ return `${s.slice(0, 1)}•••@${a.slice(0, 1)}•••${c}`;
1327
1428
  }
1328
- function bt(e) {
1429
+ function Fs(e) {
1329
1430
  return e ? `+••••••${e.replace(/\D/g, "").slice(-2)}` : null;
1330
1431
  }
1331
- function Ct(e) {
1432
+ function Ns(e) {
1332
1433
  return e.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, "[redacted-email]").replace(/\+[1-9][\d\s().-]{5,}\d/g, "[redacted-phone]").replace(
1333
1434
  /\b(password|passcode|token|secret|api[-_\s]?key|authorization)\b\s*[:=]?\s*\S+/gi,
1334
1435
  "$1 [redacted]"
1335
1436
  );
1336
1437
  }
1337
- function Le(e) {
1438
+ function zt(e) {
1338
1439
  return e ? `${e.slice(0, 1)}•••` : null;
1339
1440
  }
1340
- function U(e) {
1441
+ function B(e) {
1341
1442
  return typeof e == "string" ? e : null;
1342
1443
  }
1343
- function At(e) {
1444
+ function Es(e) {
1344
1445
  const t = [];
1345
1446
  if (Array.isArray(e?.providerData))
1346
1447
  for (const s of e.providerData) {
1347
- const i = U(s?.providerId);
1348
- i && t.push(i);
1448
+ const r = B(s?.providerId);
1449
+ r && t.push(r);
1349
1450
  }
1350
1451
  return [...new Set(t)].sort();
1351
1452
  }
1352
- function He(e) {
1453
+ function Vt(e) {
1353
1454
  return Array.isArray(e?.multiFactor?.enrolledFactors) ? e.multiFactor.enrolledFactors.length : 0;
1354
1455
  }
1355
- function we(e, t) {
1356
- return t.manageRoleClaim ? U(e?.customClaims?.[t.roleClaimKey]) : null;
1456
+ function Xe(e, t) {
1457
+ return t.manageRoleClaim ? B(e?.customClaims?.[t.roleClaimKey]) : null;
1357
1458
  }
1358
- function Dt() {
1459
+ function Ps() {
1359
1460
  return {
1360
1461
  enabled: !1,
1361
1462
  exists: !1,
@@ -1365,40 +1466,40 @@ function Dt() {
1365
1466
  status: null
1366
1467
  };
1367
1468
  }
1368
- function Ft(e, t, s) {
1369
- const i = e ? U(e[s.profileNameField]) : null, r = e ? U(e[s.profileEmailField]) : null;
1469
+ function ks(e, t, s) {
1470
+ const r = e ? B(e[s.profileNameField]) : null, n = e ? B(e[s.profileEmailField]) : null;
1370
1471
  return {
1371
1472
  enabled: !0,
1372
1473
  exists: !!e,
1373
- name: t ? i : Le(i),
1374
- email: t ? r : ze(r),
1375
- role: t && e ? U(e[s.profileRoleField]) : null,
1376
- status: t && e ? U(e[s.profileStatusField]) : null
1474
+ name: t ? r : zt(r),
1475
+ email: t ? n : Lt(n),
1476
+ role: t && e ? B(e[s.profileRoleField]) : null,
1477
+ status: t && e ? B(e[s.profileStatusField]) : null
1377
1478
  };
1378
1479
  }
1379
- function le(e, t) {
1380
- const s = U(e?.email), i = U(e?.displayName), r = U(e?.phoneNumber);
1480
+ function je(e, t) {
1481
+ const s = B(e?.email), r = B(e?.displayName), n = B(e?.phoneNumber);
1381
1482
  let a;
1382
- return t.config.linkFirestoreProfiles ? t.profileAvailable === !1 ? a = null : a = Ft(t.profile || null, t.canViewPii, t.config) : a = Dt(), {
1483
+ return t.config.linkFirestoreProfiles ? t.profileAvailable === !1 ? a = null : a = ks(t.profile || null, t.canViewPii, t.config) : a = Ps(), {
1383
1484
  uid: String(e?.uid || ""),
1384
- displayName: t.canViewPii ? i : Le(i),
1385
- email: t.canViewPii ? s : ze(s),
1386
- phoneNumber: t.canViewPii ? r : bt(r),
1387
- photoURL: t.canViewPii ? U(e?.photoURL) : null,
1485
+ displayName: t.canViewPii ? r : zt(r),
1486
+ email: t.canViewPii ? s : Lt(s),
1487
+ phoneNumber: t.canViewPii ? n : Fs(n),
1488
+ photoURL: t.canViewPii ? B(e?.photoURL) : null,
1388
1489
  emailVerified: e?.emailVerified === !0,
1389
1490
  disabled: e?.disabled === !0,
1390
- providers: At(e),
1391
- createdAt: U(e?.metadata?.creationTime),
1392
- lastSignInAt: U(e?.metadata?.lastSignInTime),
1393
- lastRefreshAt: U(e?.metadata?.lastRefreshTime),
1394
- mfaFactorCount: He(e),
1395
- role: we(e, t.config),
1491
+ providers: Es(e),
1492
+ createdAt: B(e?.metadata?.creationTime),
1493
+ lastSignInAt: B(e?.metadata?.lastSignInTime),
1494
+ lastRefreshAt: B(e?.metadata?.lastRefreshTime),
1495
+ mfaFactorCount: Vt(e),
1496
+ role: Xe(e, t.config),
1396
1497
  profile: a
1397
1498
  };
1398
1499
  }
1399
- function Pe(e, t) {
1500
+ function yt(e, t) {
1400
1501
  if (!e) return null;
1401
- const s = le(e, {
1502
+ const s = je(e, {
1402
1503
  canViewPii: !1,
1403
1504
  config: t,
1404
1505
  profileAvailable: !1
@@ -1415,27 +1516,27 @@ function Pe(e, t) {
1415
1516
  role: s.role
1416
1517
  };
1417
1518
  }
1418
- function It(e, t, s) {
1419
- const i = { ...e || {} };
1420
- return s === null ? delete i[t] : i[t] = s, i;
1519
+ function Us(e, t, s) {
1520
+ const r = { ...e || {} };
1521
+ return s === null ? delete r[t] : r[t] = s, r;
1421
1522
  }
1422
- function ke(e, t) {
1523
+ function wt(e, t) {
1423
1524
  const s = {
1424
1525
  [t.profileUidField]: String(e.uid),
1425
1526
  [t.profileStatusField]: e.disabled === !0 ? "disabled" : "active"
1426
1527
  };
1427
1528
  typeof e.displayName == "string" && (s[t.profileNameField] = e.displayName), typeof e.email == "string" && (s[t.profileEmailField] = e.email);
1428
- const i = we(e, t);
1429
- return i !== null && (s[t.profileRoleField] = i), s;
1529
+ const r = Xe(e, t);
1530
+ return r !== null && (s[t.profileRoleField] = r), s;
1430
1531
  }
1431
- function ie(e) {
1532
+ function xe(e) {
1432
1533
  if (!e || typeof e != "object") return;
1433
1534
  const t = e;
1434
1535
  if (typeof t.code == "string") return t.code;
1435
1536
  if (typeof t.errorInfo?.code == "string") return t.errorInfo.code;
1436
1537
  }
1437
- function Rt(e, t = "Firebase Authentication request failed.") {
1438
- const s = ie(e);
1538
+ function Os(e, t = "Firebase Authentication request failed.") {
1539
+ const s = xe(e);
1439
1540
  return s === "auth/user-not-found" ? { statusCode: 404, statusMessage: "Firebase user not found." } : s && [
1440
1541
  "auth/email-already-exists",
1441
1542
  "auth/phone-number-already-exists",
@@ -1449,91 +1550,91 @@ function Rt(e, t = "Firebase Authentication request failed.") {
1449
1550
  "auth/configuration-not-found"
1450
1551
  ].includes(s) ? { statusCode: 424, statusMessage: "The Firebase integration is not authorized for this operation." } : { statusCode: 502, statusMessage: t };
1451
1552
  }
1452
- function _(e) {
1553
+ function W(e) {
1453
1554
  const t = e?.context?.module;
1454
1555
  if (!t || !t.supabase || typeof t.instanceId != "string" || typeof t.projectId != "string" || typeof t.userId != "string")
1455
- throw y({ statusCode: 500, statusMessage: "Firebase Auth Manager request context is unavailable." });
1556
+ throw g({ statusCode: 500, statusMessage: "Firebase Auth Manager request context is unavailable." });
1456
1557
  return {
1457
1558
  ...t,
1458
1559
  isAdmin: t.isAdmin === !0,
1459
1560
  permissions: Array.isArray(t.permissions) ? t.permissions : []
1460
1561
  };
1461
1562
  }
1462
- async function z(e, t) {
1463
- const s = t.safeParse(await Q(e));
1563
+ async function X(e, t) {
1564
+ const s = t.safeParse(await j(e));
1464
1565
  if (!s.success)
1465
- throw y({
1566
+ throw g({
1466
1567
  statusCode: 422,
1467
1568
  statusMessage: s.error.issues[0]?.message || "Request body is invalid."
1468
1569
  });
1469
1570
  return s.data;
1470
1571
  }
1471
- function L(e) {
1472
- const t = N(e, "uid");
1572
+ function ee(e) {
1573
+ const t = U(e, "uid");
1473
1574
  if (typeof t != "string")
1474
- throw y({ statusCode: 400, statusMessage: "A valid Firebase UID is required." });
1475
- return ht(t);
1575
+ throw g({ statusCode: 400, statusMessage: "A valid Firebase UID is required." });
1576
+ return _s(t);
1476
1577
  }
1477
- function q(e, t) {
1578
+ function G(e, t) {
1478
1579
  if (typeof e?.statusCode == "number" && typeof e?.statusMessage == "string")
1479
1580
  throw e;
1480
- const s = Rt(e, t), i = ie(e);
1481
- throw console.error("Firebase Auth Manager request failed", i ? { code: i } : { code: "unknown" }), y(s);
1581
+ const s = Os(e, t), r = xe(e);
1582
+ throw console.error("Firebase Auth Manager request failed", r ? { code: r } : { code: "unknown" }), g(s);
1482
1583
  }
1483
- function Mt(e) {
1484
- return ie(e) === "auth/user-not-found";
1584
+ function js(e) {
1585
+ return xe(e) === "auth/user-not-found";
1485
1586
  }
1486
- function pe(e) {
1487
- return ye(e, v.viewPii);
1587
+ function Ye(e) {
1588
+ return Ze(e, $.viewPii);
1488
1589
  }
1489
- function St(e, t) {
1590
+ function qs(e, t) {
1490
1591
  const s = [];
1491
- for (let i = 0; i < e.length; i += t)
1492
- s.push(e.slice(i, i + t));
1592
+ for (let r = 0; r < e.length; r += t)
1593
+ s.push(e.slice(r, r + t));
1493
1594
  return s;
1494
1595
  }
1495
- function me(e) {
1596
+ function qe(e) {
1496
1597
  return e.length > 0 && e !== "." && e !== ".." && !e.includes("/") && !/^__.*__$/.test(e);
1497
1598
  }
1498
- async function Pt(e, t, s) {
1499
- const i = /* @__PURE__ */ new Map();
1500
- if (!s.linkFirestoreProfiles || t.length === 0) return i;
1501
- const r = [...new Set(t.map((d) => String(d.uid)).filter(Boolean))], a = e.collection(s.profileCollection), n = r.filter(me), c = n.map((d) => a.doc(d)), o = c.length === 0 ? [] : typeof e.getAll == "function" ? await e.getAll(...c) : await Promise.all(c.map((d) => d.get()));
1502
- for (let d = 0; d < o.length; d += 1) {
1503
- const l = o[d], f = n[d];
1504
- f && l?.exists && i.set(f, l.data());
1599
+ async function $s(e, t, s) {
1600
+ const r = /* @__PURE__ */ new Map();
1601
+ if (!s.linkFirestoreProfiles || t.length === 0) return r;
1602
+ const n = [...new Set(t.map((u) => String(u.uid)).filter(Boolean))], a = e.collection(s.profileCollection), c = n.filter(qe), i = c.map((u) => a.doc(u)), o = i.length === 0 ? [] : typeof e.getAll == "function" ? await e.getAll(...i) : await Promise.all(i.map((u) => u.get()));
1603
+ for (let u = 0; u < o.length; u += 1) {
1604
+ const l = o[u], f = c[u];
1605
+ f && l?.exists && r.set(f, l.data());
1505
1606
  }
1506
- const u = r.filter((d) => !i.has(d));
1507
- for (const d of St(u, 30)) {
1508
- const l = await a.where(s.profileUidField, "in", d).get();
1607
+ const d = n.filter((u) => !r.has(u));
1608
+ for (const u of qs(d, 30)) {
1609
+ const l = await a.where(s.profileUidField, "in", u).get();
1509
1610
  for (const f of l.docs || []) {
1510
- const g = f.data(), m = g[s.profileUidField];
1511
- typeof m == "string" && d.includes(m) && !i.has(m) && i.set(m, g);
1611
+ const p = f.data(), m = p[s.profileUidField];
1612
+ typeof m == "string" && u.includes(m) && !r.has(m) && r.set(m, p);
1512
1613
  }
1513
1614
  }
1514
- return i;
1515
- }
1516
- async function ve(e, t, s) {
1517
- const i = e.collection(s.profileCollection);
1518
- if (me(t)) {
1519
- const n = await i.doc(t).get();
1520
- if (n.exists)
1521
- return { id: String(n.id), data: n.data() };
1615
+ return r;
1616
+ }
1617
+ async function bt(e, t, s) {
1618
+ const r = e.collection(s.profileCollection);
1619
+ if (qe(t)) {
1620
+ const c = await r.doc(t).get();
1621
+ if (c.exists)
1622
+ return { id: String(c.id), data: c.data() };
1522
1623
  }
1523
- const a = (await i.where(s.profileUidField, "==", t).limit(1).get()).docs?.[0];
1624
+ const a = (await r.where(s.profileUidField, "==", t).limit(1).get()).docs?.[0];
1524
1625
  return a ? { id: String(a.id), data: a.data() } : null;
1525
1626
  }
1526
- async function O(e, t) {
1527
- const s = _(e), { data: i, error: r } = await s.supabase.from("project_modules").select("type, config").eq("id", s.instanceId).eq("project_id", s.projectId).maybeSingle();
1528
- if (r)
1529
- throw y({ statusCode: 500, statusMessage: "Failed to load Firebase Auth Manager configuration." });
1530
- if (!i || i.type !== Oe || !i.config)
1531
- throw y({ statusCode: 404, statusMessage: "Firebase Auth Manager module instance not found." });
1532
- const a = ft(i.config), { data: n, error: c } = await s.supabase.from("integrations").select("id, project_id, type").eq("id", a.project).eq("project_id", s.projectId).eq("type", "FIREBASE").maybeSingle();
1533
- if (c)
1534
- throw y({ statusCode: 500, statusMessage: "Failed to verify the Firebase integration." });
1535
- if (!n)
1536
- throw y({ statusCode: 424, statusMessage: "The configured Firebase integration is unavailable for this project." });
1627
+ async function Y(e, t) {
1628
+ const s = W(e), { data: r, error: n } = await s.supabase.from("project_modules").select("type, config").eq("id", s.instanceId).eq("project_id", s.projectId).maybeSingle();
1629
+ if (n)
1630
+ throw g({ statusCode: 500, statusMessage: "Failed to load Firebase Auth Manager configuration." });
1631
+ if (!r || r.type !== Ot || !r.config)
1632
+ throw g({ statusCode: 404, statusMessage: "Firebase Auth Manager module instance not found." });
1633
+ const a = Ds(r.config), { data: c, error: i } = await s.supabase.from("integrations").select("id, project_id, type").eq("id", a.project).eq("project_id", s.projectId).eq("type", "FIREBASE").maybeSingle();
1634
+ if (i)
1635
+ throw g({ statusCode: 500, statusMessage: "Failed to verify the Firebase integration." });
1636
+ if (!c)
1637
+ throw g({ statusCode: 424, statusMessage: "The configured Firebase integration is unavailable for this project." });
1537
1638
  const o = await t.initFirebase(e, a.project);
1538
1639
  return {
1539
1640
  module: s,
@@ -1544,427 +1645,427 @@ async function O(e, t) {
1544
1645
  firestore: o.firestore()
1545
1646
  };
1546
1647
  }
1547
- async function H(e, t, s) {
1548
- const i = {
1648
+ async function te(e, t, s) {
1649
+ const r = {
1549
1650
  project_id: t.module.projectId,
1550
1651
  module_id: t.module.instanceId,
1551
1652
  user_id: t.module.userId,
1552
1653
  message: `Firebase Auth: ${s.action}`,
1553
1654
  level: "INFO",
1554
1655
  params: {
1555
- source: Oe,
1656
+ source: Ot,
1556
1657
  action: s.action,
1557
1658
  targetUid: s.targetUid,
1558
1659
  integrationId: t.integrationId,
1559
- reason: Ct(s.reason),
1560
- before: Pe(s.before, t.config),
1561
- after: Pe(s.after, t.config),
1660
+ reason: Ns(s.reason),
1661
+ before: yt(s.before, t.config),
1662
+ after: yt(s.after, t.config),
1562
1663
  ...s.details || {}
1563
1664
  }
1564
1665
  };
1565
1666
  try {
1566
- const { error: r } = await t.module.supabase.from("project_logs").insert(i);
1567
- return r ? (console.error("Firebase Auth Manager audit insert failed", { code: r.code || "unknown" }), !1) : !0;
1568
- } catch (r) {
1569
- const a = r && typeof r == "object" && "code" in r ? String(r.code) : "unknown";
1667
+ const { error: n } = await t.module.supabase.from("project_logs").insert(r);
1668
+ return n ? (console.error("Firebase Auth Manager audit insert failed", { code: n.code || "unknown" }), !1) : !0;
1669
+ } catch (n) {
1670
+ const a = n && typeof n == "object" && "code" in n ? String(n.code) : "unknown";
1570
1671
  return console.error("Firebase Auth Manager audit insert failed", { code: a }), !1;
1571
1672
  }
1572
1673
  }
1573
- async function kt(e, t) {
1674
+ async function Bs(e, t) {
1574
1675
  try {
1575
1676
  return t.kind === "email" ? [await e.getUserByEmail(t.value)] : t.kind === "phone" ? [await e.getUserByPhoneNumber(t.value)] : [await e.getUser(t.value)];
1576
1677
  } catch (s) {
1577
- if (Mt(s)) return [];
1678
+ if (js(s)) return [];
1578
1679
  throw s;
1579
1680
  }
1580
1681
  }
1581
- async function Ue(e, t, s) {
1682
+ async function Ct(e, t, s) {
1582
1683
  try {
1583
1684
  return await e.getUser(t);
1584
- } catch (i) {
1685
+ } catch (r) {
1585
1686
  return console.error("Firebase Auth Manager post-mutation refresh failed", {
1586
- code: ie(i) || "unknown"
1687
+ code: xe(r) || "unknown"
1587
1688
  }), s;
1588
1689
  }
1589
1690
  }
1590
- async function J(e, t) {
1591
- let s = /* @__PURE__ */ new Map(), i = !0;
1691
+ async function ue(e, t) {
1692
+ let s = /* @__PURE__ */ new Map(), r = !0;
1592
1693
  if (t.config.linkFirestoreProfiles)
1593
1694
  try {
1594
- s = await Pt(t.firestore, e, t.config);
1595
- } catch (r) {
1596
- i = !1;
1597
- const a = ie(r);
1695
+ s = await $s(t.firestore, e, t.config);
1696
+ } catch (n) {
1697
+ r = !1;
1698
+ const a = xe(n);
1598
1699
  console.error("Firebase Auth Manager profile join failed", { code: a || "unknown" });
1599
1700
  }
1600
- return e.map((r) => le(r, {
1601
- canViewPii: pe(t.module),
1701
+ return e.map((n) => je(n, {
1702
+ canViewPii: Ye(t.module),
1602
1703
  config: t.config,
1603
- profile: s.get(String(r.uid)) || null,
1604
- profileAvailable: i
1704
+ profile: s.get(String(n.uid)) || null,
1705
+ profileAvailable: r
1605
1706
  }));
1606
1707
  }
1607
- function Jt(e) {
1608
- const t = se();
1609
- return t.get("/users", A(async (s) => {
1610
- const i = _(s);
1611
- T(i, v.viewUsers);
1708
+ function va(e) {
1709
+ const t = J();
1710
+ return t.get("/users", b(async (s) => {
1711
+ const r = W(s);
1712
+ H(r, $.viewUsers);
1612
1713
  try {
1613
- const r = await O(s, e), a = gt(R(s), r.config.pageSize);
1614
- if (a.search && !yt(r.module, a.search))
1615
- throw y({
1714
+ const n = await Y(s, e), a = Ts(v(s), n.config.pageSize);
1715
+ if (a.search && !Rs(n.module, a.search))
1716
+ throw g({
1616
1717
  statusCode: 403,
1617
1718
  statusMessage: "Viewing personal data is required to search by email or phone number."
1618
1719
  });
1619
- let n, c = null;
1720
+ let c, i = null;
1620
1721
  if (a.search)
1621
- n = await kt(r.auth, a.search);
1722
+ c = await Bs(n.auth, a.search);
1622
1723
  else {
1623
- const o = await r.auth.listUsers(a.limit, a.pageToken);
1624
- n = Array.isArray(o.users) ? o.users : [], c = typeof o.pageToken == "string" ? o.pageToken : null;
1724
+ const o = await n.auth.listUsers(a.limit, a.pageToken);
1725
+ c = Array.isArray(o.users) ? o.users : [], i = typeof o.pageToken == "string" ? o.pageToken : null;
1625
1726
  }
1626
1727
  return {
1627
- users: await J(n, r),
1628
- nextPageToken: c
1728
+ users: await ue(c, n),
1729
+ nextPageToken: i
1629
1730
  };
1630
- } catch (r) {
1631
- q(r, "Failed to list Firebase users.");
1731
+ } catch (n) {
1732
+ G(n, "Failed to list Firebase users.");
1632
1733
  }
1633
- })), t.get("/users/:uid", A(async (s) => {
1634
- const i = _(s);
1635
- T(i, v.viewUsers);
1636
- const r = L(s);
1734
+ })), t.get("/users/:uid", b(async (s) => {
1735
+ const r = W(s);
1736
+ H(r, $.viewUsers);
1737
+ const n = ee(s);
1637
1738
  try {
1638
- const a = await O(s, e), n = await a.auth.getUser(r), [c] = await J([n], a);
1639
- return { user: c };
1739
+ const a = await Y(s, e), c = await a.auth.getUser(n), [i] = await ue([c], a);
1740
+ return { user: i };
1640
1741
  } catch (a) {
1641
- q(a, "Failed to load the Firebase user.");
1742
+ G(a, "Failed to load the Firebase user.");
1642
1743
  }
1643
- })), t.post("/users", A(async (s) => {
1644
- const i = _(s);
1645
- T(i, v.createUsers);
1646
- const r = await z(s, ot);
1647
- r.createProfile && T(i, v.manageProfiles);
1744
+ })), t.post("/users", b(async (s) => {
1745
+ const r = W(s);
1746
+ H(r, $.createUsers);
1747
+ const n = await X(s, hs);
1748
+ n.createProfile && H(r, $.manageProfiles);
1648
1749
  try {
1649
- const a = await O(s, e);
1650
- if (r.createProfile && !a.config.linkFirestoreProfiles)
1651
- throw y({ statusCode: 409, statusMessage: "Firestore profile linking is disabled for this module." });
1652
- if (r.uid && a.config.linkFirestoreProfiles && await ve(a.firestore, r.uid, a.config))
1653
- throw y({
1750
+ const a = await Y(s, e);
1751
+ if (n.createProfile && !a.config.linkFirestoreProfiles)
1752
+ throw g({ statusCode: 409, statusMessage: "Firestore profile linking is disabled for this module." });
1753
+ if (n.uid && a.config.linkFirestoreProfiles && await bt(a.firestore, n.uid, a.config))
1754
+ throw g({
1654
1755
  statusCode: 409,
1655
1756
  statusMessage: "A retained Firestore profile already uses this UID. Resolve that profile before reusing the Authentication UID."
1656
1757
  });
1657
- const n = await a.auth.createUser({
1658
- email: r.email,
1659
- password: r.password,
1660
- uid: r.uid,
1661
- displayName: r.displayName,
1662
- phoneNumber: r.phoneNumber,
1663
- emailVerified: r.emailVerified,
1664
- disabled: r.disabled
1758
+ const c = await a.auth.createUser({
1759
+ email: n.email,
1760
+ password: n.password,
1761
+ uid: n.uid,
1762
+ displayName: n.displayName,
1763
+ phoneNumber: n.phoneNumber,
1764
+ emailVerified: n.emailVerified,
1765
+ disabled: n.disabled
1665
1766
  });
1666
- let c = null, o = !1, u = null;
1667
- if (r.createProfile) {
1668
- c = ke(n, a.config);
1767
+ let i = null, o = !1, d = null;
1768
+ if (n.createProfile) {
1769
+ i = wt(c, a.config);
1669
1770
  try {
1670
1771
  const l = a.firestore.collection(a.config.profileCollection);
1671
- await (me(n.uid) ? l.doc(n.uid) : l.doc()).create(c), o = !0;
1772
+ await (qe(c.uid) ? l.doc(c.uid) : l.doc()).create(i), o = !0;
1672
1773
  } catch {
1673
- c = null, u = "The Authentication user was created, but its Firestore profile could not be created.";
1774
+ i = null, d = "The Authentication user was created, but its Firestore profile could not be created.";
1674
1775
  }
1675
1776
  }
1676
- const d = await H(s, a, {
1777
+ const u = await te(s, a, {
1677
1778
  action: "user.create",
1678
- targetUid: n.uid,
1779
+ targetUid: c.uid,
1679
1780
  reason: "Created through Firebase Auth Manager.",
1680
1781
  before: null,
1681
- after: n,
1782
+ after: c,
1682
1783
  details: {
1683
- profileRequested: r.createProfile === !0,
1784
+ profileRequested: n.createProfile === !0,
1684
1785
  profileCreated: o
1685
1786
  }
1686
1787
  });
1687
- return Ze(s, 201), {
1688
- user: le(n, {
1689
- canViewPii: pe(a.module),
1788
+ return os(s, 201), {
1789
+ user: je(c, {
1790
+ canViewPii: Ye(a.module),
1690
1791
  config: a.config,
1691
- profile: c
1792
+ profile: i
1692
1793
  }),
1693
1794
  profileCreated: o,
1694
- profileError: u,
1695
- auditRecorded: d
1795
+ profileError: d,
1796
+ auditRecorded: u
1696
1797
  };
1697
1798
  } catch (a) {
1698
- q(a, "Failed to create the Firebase user.");
1799
+ G(a, "Failed to create the Firebase user.");
1699
1800
  }
1700
- })), t.patch("/users/:uid", A(async (s) => {
1701
- const i = _(s);
1702
- T(i, v.editUsers);
1703
- const r = L(s), a = await z(s, rt);
1801
+ })), t.patch("/users/:uid", b(async (s) => {
1802
+ const r = W(s);
1803
+ H(r, $.editUsers);
1804
+ const n = ee(s), a = await X(s, ys);
1704
1805
  try {
1705
- const n = await O(s, e), c = await n.auth.getUser(r), o = {};
1706
- Y(a, "displayName") && (o.displayName = a.displayName), Y(a, "email") && (o.email = a.email), Y(a, "phoneNumber") && (o.phoneNumber = a.phoneNumber), Y(a, "emailVerified") && (o.emailVerified = a.emailVerified);
1707
- const u = await n.auth.updateUser(r, o), d = await H(s, n, {
1806
+ const c = await Y(s, e), i = await c.auth.getUser(n), o = {};
1807
+ re(a, "displayName") && (o.displayName = a.displayName), re(a, "email") && (o.email = a.email), re(a, "phoneNumber") && (o.phoneNumber = a.phoneNumber), re(a, "emailVerified") && (o.emailVerified = a.emailVerified);
1808
+ const d = await c.auth.updateUser(n, o), u = await te(s, c, {
1708
1809
  action: "user.update",
1709
- targetUid: r,
1810
+ targetUid: n,
1710
1811
  reason: a.reason,
1711
- before: c,
1712
- after: u,
1812
+ before: i,
1813
+ after: d,
1713
1814
  details: { changedFieldCount: Object.keys(o).length }
1714
- }), [l] = await J([u], n);
1715
- return { user: l, auditRecorded: d };
1716
- } catch (n) {
1717
- q(n, "Failed to update the Firebase user.");
1815
+ }), [l] = await ue([d], c);
1816
+ return { user: l, auditRecorded: u };
1817
+ } catch (c) {
1818
+ G(c, "Failed to update the Firebase user.");
1718
1819
  }
1719
- })), t.post("/users/:uid/status", A(async (s) => {
1720
- const i = _(s);
1721
- T(i, v.manageStatus);
1722
- const r = L(s), a = await z(s, nt);
1820
+ })), t.post("/users/:uid/status", b(async (s) => {
1821
+ const r = W(s);
1822
+ H(r, $.manageStatus);
1823
+ const n = ee(s), a = await X(s, ws);
1723
1824
  try {
1724
- const n = await O(s, e), c = await n.auth.getUser(r), o = c.disabled !== a.disabled, u = o ? await n.auth.updateUser(r, { disabled: a.disabled }) : c, d = await H(s, n, {
1825
+ const c = await Y(s, e), i = await c.auth.getUser(n), o = i.disabled !== a.disabled, d = o ? await c.auth.updateUser(n, { disabled: a.disabled }) : i, u = await te(s, c, {
1725
1826
  action: a.disabled ? "user.disable" : "user.enable",
1726
- targetUid: r,
1827
+ targetUid: n,
1727
1828
  reason: a.reason,
1728
- before: c,
1729
- after: u,
1829
+ before: i,
1830
+ after: d,
1730
1831
  details: { changed: o }
1731
- }), [l] = await J([u], n);
1732
- return { user: l, changed: o, auditRecorded: d };
1733
- } catch (n) {
1734
- q(n, "Failed to change the Firebase user status.");
1832
+ }), [l] = await ue([d], c);
1833
+ return { user: l, changed: o, auditRecorded: u };
1834
+ } catch (c) {
1835
+ G(c, "Failed to change the Firebase user status.");
1735
1836
  }
1736
- })), t.post("/users/:uid/revoke-sessions", A(async (s) => {
1737
- const i = _(s);
1738
- T(i, v.manageSessions);
1739
- const r = L(s), a = await z(s, fe);
1837
+ })), t.post("/users/:uid/revoke-sessions", b(async (s) => {
1838
+ const r = W(s);
1839
+ H(r, $.manageSessions);
1840
+ const n = ee(s), a = await X(s, $e);
1740
1841
  try {
1741
- const n = await O(s, e), c = await n.auth.getUser(r);
1742
- await n.auth.revokeRefreshTokens(r);
1743
- const o = await H(s, n, {
1842
+ const c = await Y(s, e), i = await c.auth.getUser(n);
1843
+ await c.auth.revokeRefreshTokens(n);
1844
+ const o = await te(s, c, {
1744
1845
  action: "user.revoke_sessions",
1745
- targetUid: r,
1846
+ targetUid: n,
1746
1847
  reason: a.reason,
1747
- before: c,
1748
- after: c,
1848
+ before: i,
1849
+ after: i,
1749
1850
  details: { sessionsRevoked: !0 }
1750
- }), u = await Ue(n.auth, r, c), [d] = await J([u], n);
1751
- return { user: d, sessionsRevoked: !0, auditRecorded: o };
1752
- } catch (n) {
1753
- q(n, "Failed to revoke Firebase user sessions.");
1851
+ }), d = await Ct(c.auth, n, i), [u] = await ue([d], c);
1852
+ return { user: u, sessionsRevoked: !0, auditRecorded: o };
1853
+ } catch (c) {
1854
+ G(c, "Failed to revoke Firebase user sessions.");
1754
1855
  }
1755
- })), t.post("/users/:uid/reset-mfa", A(async (s) => {
1756
- const i = _(s);
1757
- T(i, v.manageMfa);
1758
- const r = L(s), a = await z(s, fe);
1856
+ })), t.post("/users/:uid/reset-mfa", b(async (s) => {
1857
+ const r = W(s);
1858
+ H(r, $.manageMfa);
1859
+ const n = ee(s), a = await X(s, $e);
1759
1860
  try {
1760
- const n = await O(s, e), c = await n.auth.getUser(r), o = He(c) > 0, u = o ? await n.auth.updateUser(r, { multiFactor: { enrolledFactors: [] } }) : c, d = await H(s, n, {
1861
+ const c = await Y(s, e), i = await c.auth.getUser(n), o = Vt(i) > 0, d = o ? await c.auth.updateUser(n, { multiFactor: { enrolledFactors: [] } }) : i, u = await te(s, c, {
1761
1862
  action: "user.reset_mfa",
1762
- targetUid: r,
1863
+ targetUid: n,
1763
1864
  reason: a.reason,
1764
- before: c,
1765
- after: u,
1865
+ before: i,
1866
+ after: d,
1766
1867
  details: { changed: o }
1767
- }), [l] = await J([u], n);
1768
- return { user: l, changed: o, auditRecorded: d };
1769
- } catch (n) {
1770
- q(n, "Failed to reset Firebase multi-factor authentication.");
1868
+ }), [l] = await ue([d], c);
1869
+ return { user: l, changed: o, auditRecorded: u };
1870
+ } catch (c) {
1871
+ G(c, "Failed to reset Firebase multi-factor authentication.");
1771
1872
  }
1772
- })), t.post("/users/:uid/role", A(async (s) => {
1773
- const i = _(s);
1774
- T(i, v.manageRoles);
1775
- const r = L(s), a = await z(s, it);
1873
+ })), t.post("/users/:uid/role", b(async (s) => {
1874
+ const r = W(s);
1875
+ H(r, $.manageRoles);
1876
+ const n = ee(s), a = await X(s, bs);
1776
1877
  try {
1777
- const n = await O(s, e);
1778
- if (!n.config.manageRoleClaim)
1779
- throw y({ statusCode: 409, statusMessage: "Role claim management is disabled for this module." });
1780
- if (a.role !== null && !n.config.roleOptions.includes(a.role))
1781
- throw y({ statusCode: 422, statusMessage: "Role must be one of the configured values." });
1782
- const c = await n.auth.getUser(r), u = we(c, n.config) !== a.role;
1783
- let d = c;
1784
- if (u) {
1785
- const g = It(c.customClaims, n.config.roleClaimKey, a.role);
1786
- await n.auth.setCustomUserClaims(r, g), d = { ...c, customClaims: g };
1878
+ const c = await Y(s, e);
1879
+ if (!c.config.manageRoleClaim)
1880
+ throw g({ statusCode: 409, statusMessage: "Role claim management is disabled for this module." });
1881
+ if (a.role !== null && !c.config.roleOptions.includes(a.role))
1882
+ throw g({ statusCode: 422, statusMessage: "Role must be one of the configured values." });
1883
+ const i = await c.auth.getUser(n), d = Xe(i, c.config) !== a.role;
1884
+ let u = i;
1885
+ if (d) {
1886
+ const p = Us(i.customClaims, c.config.roleClaimKey, a.role);
1887
+ await c.auth.setCustomUserClaims(n, p), u = { ...i, customClaims: p };
1787
1888
  }
1788
- const l = await H(s, n, {
1889
+ const l = await te(s, c, {
1789
1890
  action: "user.set_role",
1790
- targetUid: r,
1891
+ targetUid: n,
1791
1892
  reason: a.reason,
1792
- before: c,
1793
- after: d,
1794
- details: { changed: u, role: a.role }
1893
+ before: i,
1894
+ after: u,
1895
+ details: { changed: d, role: a.role }
1795
1896
  });
1796
- u && (d = await Ue(n.auth, r, d));
1797
- const [f] = await J([d], n);
1798
- return { user: f, changed: u, auditRecorded: l };
1799
- } catch (n) {
1800
- q(n, "Failed to update the Firebase role claim.");
1897
+ d && (u = await Ct(c.auth, n, u));
1898
+ const [f] = await ue([u], c);
1899
+ return { user: f, changed: d, auditRecorded: l };
1900
+ } catch (c) {
1901
+ G(c, "Failed to update the Firebase role claim.");
1801
1902
  }
1802
- })), t.post("/users/:uid/profile", A(async (s) => {
1803
- const i = _(s);
1804
- T(i, v.manageProfiles);
1805
- const r = L(s), a = await z(s, fe);
1903
+ })), t.post("/users/:uid/profile", b(async (s) => {
1904
+ const r = W(s);
1905
+ H(r, $.manageProfiles);
1906
+ const n = ee(s), a = await X(s, $e);
1806
1907
  try {
1807
- const n = await O(s, e);
1808
- if (!n.config.linkFirestoreProfiles)
1809
- throw y({ statusCode: 409, statusMessage: "Firestore profile linking is disabled for this module." });
1810
- const c = await n.auth.getUser(r), o = await ve(n.firestore, r, n.config);
1811
- let u = o?.data || null, d = !1;
1908
+ const c = await Y(s, e);
1909
+ if (!c.config.linkFirestoreProfiles)
1910
+ throw g({ statusCode: 409, statusMessage: "Firestore profile linking is disabled for this module." });
1911
+ const i = await c.auth.getUser(n), o = await bt(c.firestore, n, c.config);
1912
+ let d = o?.data || null, u = !1;
1812
1913
  if (!o) {
1813
- u = ke(c, n.config);
1814
- const f = n.firestore.collection(n.config.profileCollection);
1815
- await (me(r) ? f.doc(r) : f.doc()).create(u), d = !0;
1914
+ d = wt(i, c.config);
1915
+ const f = c.firestore.collection(c.config.profileCollection);
1916
+ await (qe(n) ? f.doc(n) : f.doc()).create(d), u = !0;
1816
1917
  }
1817
- const l = await H(s, n, {
1918
+ const l = await te(s, c, {
1818
1919
  action: "user.create_profile",
1819
- targetUid: r,
1920
+ targetUid: n,
1820
1921
  reason: a.reason,
1821
- before: c,
1822
- after: c,
1823
- details: { changed: d }
1922
+ before: i,
1923
+ after: i,
1924
+ details: { changed: u }
1824
1925
  });
1825
1926
  return {
1826
- user: le(c, {
1827
- canViewPii: pe(n.module),
1828
- config: n.config,
1829
- profile: u
1927
+ user: je(i, {
1928
+ canViewPii: Ye(c.module),
1929
+ config: c.config,
1930
+ profile: d
1830
1931
  }),
1831
- profileCreated: d,
1932
+ profileCreated: u,
1832
1933
  auditRecorded: l
1833
1934
  };
1834
- } catch (n) {
1835
- q(n, "Failed to create the Firestore profile.");
1935
+ } catch (c) {
1936
+ G(c, "Failed to create the Firestore profile.");
1836
1937
  }
1837
- })), t.delete("/users/:uid", A(async (s) => {
1838
- const i = _(s);
1839
- T(i, v.deleteUsers);
1840
- const r = L(s), a = await z(s, ct);
1841
- if (!wt(r, a.confirmation))
1842
- throw y({ statusCode: 422, statusMessage: "Deletion confirmation must exactly match the Firebase UID." });
1938
+ })), t.delete("/users/:uid", b(async (s) => {
1939
+ const r = W(s);
1940
+ H(r, $.deleteUsers);
1941
+ const n = ee(s), a = await X(s, Cs);
1942
+ if (!xs(n, a.confirmation))
1943
+ throw g({ statusCode: 422, statusMessage: "Deletion confirmation must exactly match the Firebase UID." });
1843
1944
  try {
1844
- const n = await O(s, e), c = await n.auth.getUser(r);
1845
- await n.auth.deleteUser(r);
1846
- const o = await H(s, n, {
1945
+ const c = await Y(s, e), i = await c.auth.getUser(n);
1946
+ await c.auth.deleteUser(n);
1947
+ const o = await te(s, c, {
1847
1948
  action: "user.delete",
1848
- targetUid: r,
1949
+ targetUid: n,
1849
1950
  reason: a.reason,
1850
- before: c,
1951
+ before: i,
1851
1952
  after: null,
1852
1953
  details: { firestoreProfilePreserved: !0 }
1853
1954
  });
1854
1955
  return {
1855
- uid: r,
1956
+ uid: n,
1856
1957
  deleted: !0,
1857
1958
  firestoreProfilePreserved: !0,
1858
1959
  auditRecorded: o
1859
1960
  };
1860
- } catch (n) {
1861
- q(n, "Failed to delete the Firebase user.");
1961
+ } catch (c) {
1962
+ G(c, "Failed to delete the Firebase user.");
1862
1963
  }
1863
1964
  })), t.handler;
1864
1965
  }
1865
- const be = 1, Ne = 700 * 1024, xe = 20, vt = 5e4, Ut = 120, Nt = 80, Ee = 2e3, Te = 120, xt = "studio_forms", Ge = /* @__PURE__ */ new Set(["draft", "published", "archived"]), Et = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]), x = {
1966
+ const et = 1, At = 700 * 1024, It = 20, Ls = 5e4, zs = 120, Vs = 80, Mt = 2e3, St = 120, Hs = "studio_forms", Ht = /* @__PURE__ */ new Set(["draft", "published", "archived"]), Ws = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]), L = {
1866
1967
  view: "view-forms",
1867
1968
  create: "create-form",
1868
1969
  edit: "edit-form",
1869
1970
  publish: "publish-form",
1870
1971
  archive: "archive-form"
1871
1972
  };
1872
- function I(e) {
1873
- throw y({ statusCode: 400, statusMessage: e });
1973
+ function R(e) {
1974
+ throw g({ statusCode: 400, statusMessage: e });
1874
1975
  }
1875
- function G(e) {
1876
- throw y({ statusCode: 409, statusMessage: e });
1976
+ function ae(e) {
1977
+ throw g({ statusCode: 409, statusMessage: e });
1877
1978
  }
1878
- function Ce(e, t) {
1879
- (!e || typeof e != "object" || Array.isArray(e)) && I(`${t} must be an object.`);
1979
+ function tt(e, t) {
1980
+ (!e || typeof e != "object" || Array.isArray(e)) && R(`${t} must be an object.`);
1880
1981
  const s = Object.getPrototypeOf(e);
1881
- return s !== Object.prototype && s !== null && I(`${t} must be a plain object.`), e;
1982
+ return s !== Object.prototype && s !== null && R(`${t} must be a plain object.`), e;
1882
1983
  }
1883
- function Qe(e, t, s) {
1884
- typeof e != "string" && I(`${t} is required.`);
1885
- const i = e.trim();
1886
- return i || I(`${t} is required.`), i.length > s && I(`${t} cannot exceed ${s} characters.`), i;
1984
+ function Wt(e, t, s) {
1985
+ typeof e != "string" && R(`${t} is required.`);
1986
+ const r = e.trim();
1987
+ return r || R(`${t} is required.`), r.length > s && R(`${t} cannot exceed ${s} characters.`), r;
1887
1988
  }
1888
- function Tt(e) {
1989
+ function Gs(e) {
1889
1990
  if (e == null) return "";
1890
- typeof e != "string" && I("Form description must be a string.");
1991
+ typeof e != "string" && R("Form description must be a string.");
1891
1992
  const t = e.trim();
1892
- return t.length > Ee && I(`Form description cannot exceed ${Ee} characters.`), t;
1993
+ return t.length > Mt && R(`Form description cannot exceed ${Mt} characters.`), t;
1893
1994
  }
1894
- function _t(e) {
1895
- const t = Qe(e, "Form key", Nt).toLowerCase();
1896
- return /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/.test(t) || I("Form key must start with a letter and contain only lowercase letters, numbers, hyphens, or underscores."), t;
1995
+ function Ys(e) {
1996
+ const t = Wt(e, "Form key", Vs).toLowerCase();
1997
+ return /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/.test(t) || R("Form key must start with a letter and contain only lowercase letters, numbers, hyphens, or underscores."), t;
1897
1998
  }
1898
- function qt(e) {
1999
+ function Js(e) {
1899
2000
  if (e == null || e === "")
1900
- return xt;
1901
- typeof e != "string" && I("The configured forms collection must be a string.");
2001
+ return Hs;
2002
+ typeof e != "string" && R("The configured forms collection must be a string.");
1902
2003
  const t = e.trim();
1903
- (!t || t.length > 500) && I("The configured forms collection path is invalid."), (t.startsWith("/") || t.endsWith("/") || t.includes("//")) && I("The configured forms collection path is invalid.");
2004
+ (!t || t.length > 500) && R("The configured forms collection path is invalid."), (t.startsWith("/") || t.endsWith("/") || t.includes("//")) && R("The configured forms collection path is invalid.");
1904
2005
  const s = t.split("/");
1905
- s.length % 2 === 0 && I("The configured forms collection path must point to a collection.");
1906
- for (const i of s)
1907
- (!/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/.test(i) || i === "." || i === ".." || /^__.*__$/.test(i)) && I("The configured forms collection path contains an invalid segment.");
2006
+ s.length % 2 === 0 && R("The configured forms collection path must point to a collection.");
2007
+ for (const r of s)
2008
+ (!/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/.test(r) || r === "." || r === ".." || /^__.*__$/.test(r)) && R("The configured forms collection path contains an invalid segment.");
1908
2009
  return t;
1909
2010
  }
1910
- function Ot(e) {
1911
- (!e || typeof e != "object") && I("Form definition must be an object or array.");
2011
+ function Ks(e) {
2012
+ (!e || typeof e != "object") && R("Form definition must be an object or array.");
1912
2013
  const t = /* @__PURE__ */ new Set();
1913
2014
  let s = 0;
1914
- const i = (n, c, o) => {
1915
- if (s += 1, s > vt && I("Form definition is too complex."), c > xe && I(`Form definition cannot be nested deeper than ${xe} levels.`), n === null || typeof n == "string" || typeof n == "boolean") return;
1916
- if (typeof n == "number") {
1917
- Number.isFinite(n) || I("Form definition contains an invalid number.");
2015
+ const r = (c, i, o) => {
2016
+ if (s += 1, s > Ls && R("Form definition is too complex."), i > It && R(`Form definition cannot be nested deeper than ${It} levels.`), c === null || typeof c == "string" || typeof c == "boolean") return;
2017
+ if (typeof c == "number") {
2018
+ Number.isFinite(c) || R("Form definition contains an invalid number.");
1918
2019
  return;
1919
2020
  }
1920
- if (typeof n != "object" && I("Form definition contains a value that cannot be stored."), t.has(n) && I("Form definition cannot contain circular references."), t.add(n), Array.isArray(n)) {
1921
- o && I("Form definition cannot contain an array directly inside another array.");
1922
- for (const d of n) i(d, c + 1, !0);
1923
- t.delete(n);
2021
+ if (typeof c != "object" && R("Form definition contains a value that cannot be stored."), t.has(c) && R("Form definition cannot contain circular references."), t.add(c), Array.isArray(c)) {
2022
+ o && R("Form definition cannot contain an array directly inside another array.");
2023
+ for (const u of c) r(u, i + 1, !0);
2024
+ t.delete(c);
1924
2025
  return;
1925
2026
  }
1926
- const u = Object.getPrototypeOf(n);
1927
- u !== Object.prototype && u !== null && I("Form definition can contain only plain JSON objects.");
1928
- for (const [d, l] of Object.entries(n))
1929
- Et.has(d) && I(`Form definition contains a forbidden object key: ${d}.`), new TextEncoder().encode(d).byteLength > 1500 && I("Form definition contains an object key that is too long."), i(l, c + 1, !1);
1930
- t.delete(n);
2027
+ const d = Object.getPrototypeOf(c);
2028
+ d !== Object.prototype && d !== null && R("Form definition can contain only plain JSON objects.");
2029
+ for (const [u, l] of Object.entries(c))
2030
+ Ws.has(u) && R(`Form definition contains a forbidden object key: ${u}.`), new TextEncoder().encode(u).byteLength > 1500 && R("Form definition contains an object key that is too long."), r(l, i + 1, !1);
2031
+ t.delete(c);
1931
2032
  };
1932
- i(e, 1, !1);
1933
- let r;
2033
+ r(e, 1, !1);
2034
+ let n;
1934
2035
  try {
1935
- r = JSON.stringify(e);
2036
+ n = JSON.stringify(e);
1936
2037
  } catch {
1937
- I("Form definition must be valid JSON.");
2038
+ R("Form definition must be valid JSON.");
1938
2039
  }
1939
- new TextEncoder().encode(r).byteLength > Ne && I(`Form definition cannot exceed ${Ne} bytes.`);
2040
+ new TextEncoder().encode(n).byteLength > At && R(`Form definition cannot exceed ${At} bytes.`);
1940
2041
  }
1941
- function Ye(e) {
1942
- const t = Ce(e, "Request body"), s = t.definition;
1943
- return Ot(s), {
1944
- name: Qe(t.name, "Form name", Ut),
1945
- key: _t(t.key),
1946
- description: Tt(t.description),
2042
+ function Gt(e) {
2043
+ const t = tt(e, "Request body"), s = t.definition;
2044
+ return Ks(s), {
2045
+ name: Wt(t.name, "Form name", zs),
2046
+ key: Ys(t.key),
2047
+ description: Gs(t.description),
1947
2048
  definition: s
1948
2049
  };
1949
2050
  }
1950
- function Bt(e) {
1951
- return Ye(e);
2051
+ function Qs(e) {
2052
+ return Gt(e);
1952
2053
  }
1953
- function Ke(e) {
1954
- return (!Number.isInteger(e) || e < 1) && I("expectedRevision must be a positive integer."), e;
2054
+ function Yt(e) {
2055
+ return (!Number.isInteger(e) || e < 1) && R("expectedRevision must be a positive integer."), e;
1955
2056
  }
1956
- function jt(e) {
1957
- const t = Ce(e, "Request body");
2057
+ function Zs(e) {
2058
+ const t = tt(e, "Request body");
1958
2059
  return {
1959
- ...Ye(t),
1960
- expectedRevision: Ke(t.expectedRevision)
2060
+ ...Gt(t),
2061
+ expectedRevision: Yt(t.expectedRevision)
1961
2062
  };
1962
2063
  }
1963
- function ge(e) {
1964
- const t = Ce(e, "Request body");
1965
- return { expectedRevision: Ke(t.expectedRevision) };
2064
+ function Be(e) {
2065
+ const t = tt(e, "Request body");
2066
+ return { expectedRevision: Yt(t.expectedRevision) };
1966
2067
  }
1967
- function $t(e) {
2068
+ function Xs(e) {
1968
2069
  return {
1969
2070
  id: e.revisionId,
1970
2071
  formId: e.formId,
@@ -1972,7 +2073,7 @@ function $t(e) {
1972
2073
  name: e.form.name,
1973
2074
  description: e.form.description || "",
1974
2075
  definition: e.form.draftDefinition,
1975
- schemaVersion: e.form.schemaVersion || be,
2076
+ schemaVersion: e.form.schemaVersion || et,
1976
2077
  revision: e.revision,
1977
2078
  draftRevision: e.form.draftRevision,
1978
2079
  previousRevisionId: e.form.publishedRevisionId || null,
@@ -1980,295 +2081,1126 @@ function $t(e) {
1980
2081
  publishedBy: e.publishedBy
1981
2082
  };
1982
2083
  }
1983
- function ee(e) {
1984
- typeof e != "string" && I("Form ID is required.");
2084
+ function he(e) {
2085
+ typeof e != "string" && R("Form ID is required.");
1985
2086
  const t = e.trim();
1986
- return (!t || t === "." || t === ".." || t.includes("/") || /[\u0000-\u001f\u007f]/.test(t) || new TextEncoder().encode(t).byteLength > 1500) && I("Form ID is invalid."), t;
2087
+ return (!t || t === "." || t === ".." || t.includes("/") || /[\u0000-\u001f\u007f]/.test(t) || new TextEncoder().encode(t).byteLength > 1500) && R("Form ID is invalid."), t;
1987
2088
  }
1988
- function oe(e) {
2089
+ function Me(e) {
1989
2090
  const s = e?.context?.module?.userId || e?.context?.user?.id || null;
1990
2091
  return typeof s == "string" && s.trim() ? s : null;
1991
2092
  }
1992
- function E(e, t) {
2093
+ function z(e, t) {
1993
2094
  const s = e?.context?.module;
1994
2095
  if (!s)
1995
- throw y({ statusCode: 500, statusMessage: "Module context is unavailable." });
2096
+ throw g({ statusCode: 500, statusMessage: "Module context is unavailable." });
1996
2097
  if (!s.userId)
1997
- throw y({ statusCode: 401, statusMessage: "Unauthorized" });
2098
+ throw g({ statusCode: 401, statusMessage: "Unauthorized" });
1998
2099
  if (s.isAdmin === !0) return;
1999
2100
  if (!(Array.isArray(s.permissions) ? s.permissions : []).includes(t))
2000
- throw y({ statusCode: 403, statusMessage: `Missing module permission: ${t}.` });
2101
+ throw g({ statusCode: 403, statusMessage: `Missing module permission: ${t}.` });
2001
2102
  }
2002
- function te(e) {
2103
+ function ye(e) {
2003
2104
  if (!e || typeof e != "object" || Array.isArray(e))
2004
- throw y({ statusCode: 500, statusMessage: "Stored form data is invalid." });
2105
+ throw g({ statusCode: 500, statusMessage: "Stored form data is invalid." });
2005
2106
  const t = e;
2006
- if (typeof t.name != "string" || typeof t.key != "string" || !Ge.has(String(t.status)) || !Number.isInteger(t.revision) || !Number.isInteger(t.draftRevision) || !t.draftDefinition || typeof t.draftDefinition != "object")
2007
- throw y({ statusCode: 500, statusMessage: "Stored form data is invalid." });
2107
+ if (typeof t.name != "string" || typeof t.key != "string" || !Ht.has(String(t.status)) || !Number.isInteger(t.revision) || !Number.isInteger(t.draftRevision) || !t.draftDefinition || typeof t.draftDefinition != "object")
2108
+ throw g({ statusCode: 500, statusMessage: "Stored form data is invalid." });
2008
2109
  return t;
2009
2110
  }
2010
- function ue(e, t) {
2011
- e.revision !== t && G(`Form has changed. Expected revision ${t}, current revision is ${e.revision}.`);
2111
+ function Ne(e, t) {
2112
+ e.revision !== t && ae(`Form has changed. Expected revision ${t}, current revision is ${e.revision}.`);
2012
2113
  }
2013
- function Vt(e) {
2014
- (Array.isArray(e) || !Array.isArray(e.layout) || e.layout.length === 0) && I("Add at least one form element before publishing.");
2114
+ function ea(e) {
2115
+ (Array.isArray(e) || !Array.isArray(e.layout) || e.layout.length === 0) && R("Add at least one form element before publishing.");
2015
2116
  }
2016
- function X(e, t, s, i = !0) {
2017
- const { draftDefinition: r, ...a } = t, n = i ? { id: e, ...a, draftDefinition: r } : { id: e, ...a }, c = s ? s(n) : n, o = Number.isInteger(c.publishedRevision) ? c.publishedRevision : null, u = Number.isInteger(c.publishedDraftRevision) ? c.publishedDraftRevision : null;
2117
+ function le(e, t, s, r = !0) {
2118
+ const { draftDefinition: n, ...a } = t, c = r ? { id: e, ...a, draftDefinition: n } : { id: e, ...a }, i = s ? s(c) : c, o = Number.isInteger(i.publishedRevision) ? i.publishedRevision : null, d = Number.isInteger(i.publishedDraftRevision) ? i.publishedDraftRevision : null;
2018
2119
  return {
2019
- id: c.id,
2020
- name: c.name,
2021
- key: c.key,
2022
- description: c.description || "",
2023
- ...i ? { definition: r } : {},
2024
- status: c.status,
2025
- revision: c.revision,
2026
- draftRevision: c.draftRevision,
2120
+ id: i.id,
2121
+ name: i.name,
2122
+ key: i.key,
2123
+ description: i.description || "",
2124
+ ...r ? { definition: n } : {},
2125
+ status: i.status,
2126
+ revision: i.revision,
2127
+ draftRevision: i.draftRevision,
2027
2128
  publishedRevision: o,
2028
- publishedRevisionId: c.publishedRevisionId || null,
2029
- hasUnpublishedChanges: !c.publishedRevisionId || c.draftRevision !== u,
2030
- schemaVersion: c.schemaVersion || be,
2031
- createdAt: c.createdAt || null,
2032
- createdBy: c.createdBy || null,
2033
- updatedAt: c.updatedAt || null,
2034
- updatedBy: c.updatedBy || null,
2035
- publishedAt: c.publishedAt || null,
2036
- publishedBy: c.publishedBy || null,
2037
- archivedAt: c.archivedAt || null,
2038
- archivedBy: c.archivedBy || null
2129
+ publishedRevisionId: i.publishedRevisionId || null,
2130
+ hasUnpublishedChanges: !i.publishedRevisionId || i.draftRevision !== d,
2131
+ schemaVersion: i.schemaVersion || et,
2132
+ createdAt: i.createdAt || null,
2133
+ createdBy: i.createdBy || null,
2134
+ updatedAt: i.updatedAt || null,
2135
+ updatedBy: i.updatedBy || null,
2136
+ publishedAt: i.publishedAt || null,
2137
+ publishedBy: i.publishedBy || null,
2138
+ archivedAt: i.archivedAt || null,
2139
+ archivedBy: i.archivedBy || null
2039
2140
  };
2040
2141
  }
2041
- function _e(e, t) {
2142
+ function Dt(e, t) {
2042
2143
  if (!(e == null || e === ""))
2043
- return (Array.isArray(e) || typeof e != "string") && I(`${t} must be a single string.`), e.trim();
2144
+ return (Array.isArray(e) || typeof e != "string") && R(`${t} must be a single string.`), e.trim();
2044
2145
  }
2045
- function qe(e) {
2146
+ function Tt(e) {
2046
2147
  if (typeof e == "string") {
2047
2148
  const t = Date.parse(e);
2048
2149
  return Number.isNaN(t) ? 0 : t;
2049
2150
  }
2050
2151
  return e instanceof Date ? e.getTime() : e && typeof e.toMillis == "function" ? e.toMillis() : 0;
2051
2152
  }
2052
- function Z(e, t, s) {
2053
- throw Number.isInteger(t?.statusCode) && t.statusCode >= 400 && t.statusCode < 600 ? t : (console.error(`Form Builder handler — ${e} error:`, t), y({ statusCode: 500, statusMessage: s }));
2153
+ function me(e, t, s) {
2154
+ throw Number.isInteger(t?.statusCode) && t.statusCode >= 400 && t.statusCode < 600 ? t : (console.error(`Form Builder handler — ${e} error:`, t), g({ statusCode: 500, statusMessage: s }));
2054
2155
  }
2055
- function Xt(e) {
2056
- const { initFirebase: t, normalizeTimestamps: s } = e, i = se();
2057
- async function r(a) {
2058
- const n = a?.context?.module, { supabase: c, instanceId: o, projectId: u, moduleType: d } = n || {};
2059
- if (!c || !o)
2060
- throw y({ statusCode: 500, statusMessage: "Module context is unavailable." });
2061
- const { data: l, error: f } = await c.from("project_modules").select("config, project_id, type").eq("id", o).single();
2156
+ function _a(e) {
2157
+ const { initFirebase: t, normalizeTimestamps: s } = e, r = J();
2158
+ async function n(a) {
2159
+ const c = a?.context?.module, { supabase: i, instanceId: o, projectId: d, moduleType: u } = c || {};
2160
+ if (!i || !o)
2161
+ throw g({ statusCode: 500, statusMessage: "Module context is unavailable." });
2162
+ const { data: l, error: f } = await i.from("project_modules").select("config, project_id, type").eq("id", o).single();
2062
2163
  if (f || !l?.config)
2063
- throw y({ statusCode: 500, statusMessage: "Failed to load module config." });
2064
- if (u && l.project_id !== u)
2065
- throw y({ statusCode: 403, statusMessage: "Module project context does not match." });
2066
- if (d && l.type !== d)
2067
- throw y({ statusCode: 409, statusMessage: "Module type context does not match." });
2068
- const g = l.config, m = g.databaseIntegration;
2164
+ throw g({ statusCode: 500, statusMessage: "Failed to load module config." });
2165
+ if (d && l.project_id !== d)
2166
+ throw g({ statusCode: 403, statusMessage: "Module project context does not match." });
2167
+ if (u && l.type !== u)
2168
+ throw g({ statusCode: 409, statusMessage: "Module type context does not match." });
2169
+ const p = l.config, m = p.databaseIntegration;
2069
2170
  if (typeof m != "string" || !m.trim())
2070
- throw y({
2171
+ throw g({
2071
2172
  statusCode: 400,
2072
2173
  statusMessage: "Form Builder has no Firebase integration configured."
2073
2174
  });
2074
2175
  if (m.length > 200 || !/^[A-Za-z0-9_-]+$/.test(m))
2075
- throw y({ statusCode: 500, statusMessage: "Configured Firebase integration ID is invalid." });
2076
- const h = u || l.project_id, { data: p, error: w } = await c.from("integrations").select("id").eq("id", m).eq("project_id", h).eq("type", "FIREBASE").single();
2077
- if (w || !p)
2078
- throw y({
2176
+ throw g({ statusCode: 500, statusMessage: "Configured Firebase integration ID is invalid." });
2177
+ const h = d || l.project_id, { data: y, error: w } = await i.from("integrations").select("id").eq("id", m).eq("project_id", h).eq("type", "FIREBASE").single();
2178
+ if (w || !y)
2179
+ throw g({
2079
2180
  statusCode: 400,
2080
2181
  statusMessage: "Configured Firebase integration is unavailable for this project."
2081
2182
  });
2082
- const C = qt(g.formsCollection), b = ee(o), F = (await t(a, m)).firestore();
2183
+ const C = Js(p.formsCollection), A = he(o), M = (await t(a, m)).firestore();
2083
2184
  return {
2084
- firestore: F,
2185
+ firestore: M,
2085
2186
  // Access is granted per module instance in Studio, so storage must be
2086
2187
  // isolated at the same boundary even when multiple instances retain the
2087
2188
  // default root collection.
2088
- forms: F.collection(C).doc(b).collection("forms")
2189
+ forms: M.collection(C).doc(A).collection("forms")
2089
2190
  };
2090
2191
  }
2091
- return i.get("/forms", A(async (a) => {
2092
- E(a, x.view);
2192
+ return r.get("/forms", b(async (a) => {
2193
+ z(a, L.view);
2093
2194
  try {
2094
- const n = R(a), c = _e(n.status, "status"), o = _e(n.search, "search");
2095
- c && !Ge.has(c) && I("status must be draft, published, or archived."), o && o.length > Te && I(`search cannot exceed ${Te} characters.`);
2096
- const { forms: u } = await r(a), d = c ? await u.where("status", "==", c).get() : await u.get(), l = o?.toLocaleLowerCase();
2097
- return d.docs.map((f) => X(
2195
+ const c = v(a), i = Dt(c.status, "status"), o = Dt(c.search, "search");
2196
+ i && !Ht.has(i) && R("status must be draft, published, or archived."), o && o.length > St && R(`search cannot exceed ${St} characters.`);
2197
+ const { forms: d } = await n(a), u = i ? await d.where("status", "==", i).get() : await d.get(), l = o?.toLocaleLowerCase();
2198
+ return u.docs.map((f) => le(
2098
2199
  f.id,
2099
- te(f.data()),
2200
+ ye(f.data()),
2100
2201
  s,
2101
2202
  !1
2102
- )).filter((f) => l ? [f.name, f.key, f.description].some((g) => String(g || "").toLocaleLowerCase().includes(l)) : !0).sort((f, g) => qe(g.updatedAt) - qe(f.updatedAt));
2103
- } catch (n) {
2104
- Z("list", n, "Failed to list forms.");
2203
+ )).filter((f) => l ? [f.name, f.key, f.description].some((p) => String(p || "").toLocaleLowerCase().includes(l)) : !0).sort((f, p) => Tt(p.updatedAt) - Tt(f.updatedAt));
2204
+ } catch (c) {
2205
+ me("list", c, "Failed to list forms.");
2105
2206
  }
2106
- })), i.get("/forms/:formId", A(async (a) => {
2107
- E(a, x.view);
2108
- const n = ee(N(a, "formId"));
2207
+ })), r.get("/forms/:formId", b(async (a) => {
2208
+ z(a, L.view);
2209
+ const c = he(U(a, "formId"));
2109
2210
  try {
2110
- const { forms: c } = await r(a), o = await c.doc(n).get();
2211
+ const { forms: i } = await n(a), o = await i.doc(c).get();
2111
2212
  if (!o.exists)
2112
- throw y({ statusCode: 404, statusMessage: "Form not found." });
2113
- return X(o.id, te(o.data()), s);
2114
- } catch (c) {
2115
- Z("get", c, "Failed to load form.");
2213
+ throw g({ statusCode: 404, statusMessage: "Form not found." });
2214
+ return le(o.id, ye(o.data()), s);
2215
+ } catch (i) {
2216
+ me("get", i, "Failed to load form.");
2116
2217
  }
2117
- })), i.post("/forms", A(async (a) => {
2118
- E(a, x.view), E(a, x.create);
2218
+ })), r.post("/forms", b(async (a) => {
2219
+ z(a, L.view), z(a, L.create);
2119
2220
  try {
2120
- const n = Bt(await Q(a)), c = oe(a), o = (/* @__PURE__ */ new Date()).toISOString(), { firestore: u, forms: d } = await r(a), l = d.doc(n.key), f = {
2121
- name: n.name,
2122
- key: n.key,
2123
- description: n.description,
2221
+ const c = Qs(await j(a)), i = Me(a), o = (/* @__PURE__ */ new Date()).toISOString(), { firestore: d, forms: u } = await n(a), l = u.doc(c.key), f = {
2222
+ name: c.name,
2223
+ key: c.key,
2224
+ description: c.description,
2124
2225
  status: "draft",
2125
- draftDefinition: n.definition,
2126
- schemaVersion: be,
2226
+ draftDefinition: c.definition,
2227
+ schemaVersion: et,
2127
2228
  revision: 1,
2128
2229
  draftRevision: 1,
2129
2230
  publishedRevision: null,
2130
2231
  publishedRevisionId: null,
2131
2232
  publishedDraftRevision: null,
2132
2233
  createdAt: o,
2133
- createdBy: c,
2234
+ createdBy: i,
2134
2235
  updatedAt: o,
2135
- updatedBy: c,
2236
+ updatedBy: i,
2136
2237
  draftUpdatedAt: o,
2137
- draftUpdatedBy: c,
2238
+ draftUpdatedBy: i,
2138
2239
  publishedAt: null,
2139
2240
  publishedBy: null,
2140
2241
  archivedAt: null,
2141
2242
  archivedBy: null,
2142
2243
  statusBeforeArchive: null
2143
2244
  };
2144
- return await u.runTransaction(async (g) => {
2145
- (await g.get(l)).exists && G(`A form with key "${n.key}" already exists.`), g.create(l, f);
2146
- }), X(l.id, f, s);
2147
- } catch (n) {
2148
- Z("create", n, "Failed to create form.");
2245
+ return await d.runTransaction(async (p) => {
2246
+ (await p.get(l)).exists && ae(`A form with key "${c.key}" already exists.`), p.create(l, f);
2247
+ }), le(l.id, f, s);
2248
+ } catch (c) {
2249
+ me("create", c, "Failed to create form.");
2149
2250
  }
2150
- })), i.patch("/forms/:formId/draft", A(async (a) => {
2151
- E(a, x.view), E(a, x.edit);
2152
- const n = ee(N(a, "formId"));
2251
+ })), r.patch("/forms/:formId/draft", b(async (a) => {
2252
+ z(a, L.view), z(a, L.edit);
2253
+ const c = he(U(a, "formId"));
2153
2254
  try {
2154
- const c = jt(await Q(a)), o = oe(a), u = (/* @__PURE__ */ new Date()).toISOString(), { firestore: d, forms: l } = await r(a), f = l.doc(n);
2155
- return await d.runTransaction(async (g) => {
2156
- const m = await g.get(f);
2255
+ const i = Zs(await j(a)), o = Me(a), d = (/* @__PURE__ */ new Date()).toISOString(), { firestore: u, forms: l } = await n(a), f = l.doc(c);
2256
+ return await u.runTransaction(async (p) => {
2257
+ const m = await p.get(f);
2157
2258
  if (!m.exists)
2158
- throw y({ statusCode: 404, statusMessage: "Form not found." });
2159
- const h = te(m.data());
2160
- ue(h, c.expectedRevision), h.status === "archived" && G("Restore this form before editing its draft."), h.key !== c.key && G("A form key cannot be changed after the form is created.");
2161
- const p = {
2162
- name: c.name,
2163
- key: c.key,
2164
- description: c.description,
2165
- draftDefinition: c.definition,
2259
+ throw g({ statusCode: 404, statusMessage: "Form not found." });
2260
+ const h = ye(m.data());
2261
+ Ne(h, i.expectedRevision), h.status === "archived" && ae("Restore this form before editing its draft."), h.key !== i.key && ae("A form key cannot be changed after the form is created.");
2262
+ const y = {
2263
+ name: i.name,
2264
+ key: i.key,
2265
+ description: i.description,
2266
+ draftDefinition: i.definition,
2166
2267
  revision: h.revision + 1,
2167
2268
  draftRevision: h.draftRevision + 1,
2168
- updatedAt: u,
2269
+ updatedAt: d,
2169
2270
  updatedBy: o,
2170
- draftUpdatedAt: u,
2271
+ draftUpdatedAt: d,
2171
2272
  draftUpdatedBy: o
2172
2273
  };
2173
- return g.update(f, p), X(n, { ...h, ...p }, s);
2274
+ return p.update(f, y), le(c, { ...h, ...y }, s);
2174
2275
  });
2175
- } catch (c) {
2176
- Z("update draft", c, "Failed to update form draft.");
2276
+ } catch (i) {
2277
+ me("update draft", i, "Failed to update form draft.");
2177
2278
  }
2178
- })), i.post("/forms/:formId/publish", A(async (a) => {
2179
- E(a, x.view), E(a, x.publish);
2180
- const n = ee(N(a, "formId"));
2279
+ })), r.post("/forms/:formId/publish", b(async (a) => {
2280
+ z(a, L.view), z(a, L.publish);
2281
+ const c = he(U(a, "formId"));
2181
2282
  try {
2182
- const { expectedRevision: c } = ge(await Q(a)), o = oe(a), u = (/* @__PURE__ */ new Date()).toISOString(), { firestore: d, forms: l } = await r(a), f = l.doc(n), g = f.collection("revisions").doc();
2183
- return await d.runTransaction(async (m) => {
2283
+ const { expectedRevision: i } = Be(await j(a)), o = Me(a), d = (/* @__PURE__ */ new Date()).toISOString(), { firestore: u, forms: l } = await n(a), f = l.doc(c), p = f.collection("revisions").doc();
2284
+ return await u.runTransaction(async (m) => {
2184
2285
  const h = await m.get(f);
2185
2286
  if (!h.exists)
2186
- throw y({ statusCode: 404, statusMessage: "Form not found." });
2187
- const p = te(h.data());
2188
- ue(p, c), p.status === "archived" && G("Restore this form before publishing it."), Vt(p.draftDefinition), p.publishedRevisionId && p.publishedDraftRevision === p.draftRevision && G("This form has no unpublished changes.");
2189
- const w = p.revision + 1, C = $t({
2190
- formId: n,
2191
- form: p,
2287
+ throw g({ statusCode: 404, statusMessage: "Form not found." });
2288
+ const y = ye(h.data());
2289
+ Ne(y, i), y.status === "archived" && ae("Restore this form before publishing it."), ea(y.draftDefinition), y.publishedRevisionId && y.publishedDraftRevision === y.draftRevision && ae("This form has no unpublished changes.");
2290
+ const w = y.revision + 1, C = Xs({
2291
+ formId: c,
2292
+ form: y,
2192
2293
  revision: w,
2193
- revisionId: g.id,
2194
- publishedAt: u,
2294
+ revisionId: p.id,
2295
+ publishedAt: d,
2195
2296
  publishedBy: o
2196
- }), b = {
2297
+ }), A = {
2197
2298
  status: "published",
2198
2299
  revision: w,
2199
2300
  publishedRevision: w,
2200
- publishedRevisionId: g.id,
2201
- publishedDraftRevision: p.draftRevision,
2202
- publishedAt: u,
2301
+ publishedRevisionId: p.id,
2302
+ publishedDraftRevision: y.draftRevision,
2303
+ publishedAt: d,
2203
2304
  publishedBy: o,
2204
- updatedAt: u,
2305
+ updatedAt: d,
2205
2306
  updatedBy: o,
2206
2307
  archivedAt: null,
2207
2308
  archivedBy: null,
2208
2309
  statusBeforeArchive: null
2209
2310
  };
2210
- return m.create(g, C), m.update(f, b), X(n, { ...p, ...b }, s);
2311
+ return m.create(p, C), m.update(f, A), le(c, { ...y, ...A }, s);
2211
2312
  });
2212
- } catch (c) {
2213
- Z("publish", c, "Failed to publish form.");
2313
+ } catch (i) {
2314
+ me("publish", i, "Failed to publish form.");
2214
2315
  }
2215
- })), i.post("/forms/:formId/archive", A(async (a) => {
2216
- E(a, x.view), E(a, x.archive);
2217
- const n = ee(N(a, "formId"));
2316
+ })), r.post("/forms/:formId/archive", b(async (a) => {
2317
+ z(a, L.view), z(a, L.archive);
2318
+ const c = he(U(a, "formId"));
2218
2319
  try {
2219
- const { expectedRevision: c } = ge(await Q(a)), o = oe(a), u = (/* @__PURE__ */ new Date()).toISOString(), { firestore: d, forms: l } = await r(a), f = l.doc(n);
2220
- return await d.runTransaction(async (g) => {
2221
- const m = await g.get(f);
2320
+ const { expectedRevision: i } = Be(await j(a)), o = Me(a), d = (/* @__PURE__ */ new Date()).toISOString(), { firestore: u, forms: l } = await n(a), f = l.doc(c);
2321
+ return await u.runTransaction(async (p) => {
2322
+ const m = await p.get(f);
2222
2323
  if (!m.exists)
2223
- throw y({ statusCode: 404, statusMessage: "Form not found." });
2224
- const h = te(m.data());
2225
- ue(h, c), h.status === "archived" && G("Form is already archived.");
2226
- const p = {
2324
+ throw g({ statusCode: 404, statusMessage: "Form not found." });
2325
+ const h = ye(m.data());
2326
+ Ne(h, i), h.status === "archived" && ae("Form is already archived.");
2327
+ const y = {
2227
2328
  status: "archived",
2228
2329
  statusBeforeArchive: h.status,
2229
2330
  revision: h.revision + 1,
2230
- archivedAt: u,
2331
+ archivedAt: d,
2231
2332
  archivedBy: o,
2232
- updatedAt: u,
2333
+ updatedAt: d,
2233
2334
  updatedBy: o
2234
2335
  };
2235
- return g.update(f, p), X(n, { ...h, ...p }, s);
2336
+ return p.update(f, y), le(c, { ...h, ...y }, s);
2236
2337
  });
2237
- } catch (c) {
2238
- Z("archive", c, "Failed to archive form.");
2338
+ } catch (i) {
2339
+ me("archive", i, "Failed to archive form.");
2239
2340
  }
2240
- })), i.post("/forms/:formId/restore", A(async (a) => {
2241
- E(a, x.view), E(a, x.archive);
2242
- const n = ee(N(a, "formId"));
2341
+ })), r.post("/forms/:formId/restore", b(async (a) => {
2342
+ z(a, L.view), z(a, L.archive);
2343
+ const c = he(U(a, "formId"));
2243
2344
  try {
2244
- const { expectedRevision: c } = ge(await Q(a)), o = oe(a), u = (/* @__PURE__ */ new Date()).toISOString(), { firestore: d, forms: l } = await r(a), f = l.doc(n);
2245
- return await d.runTransaction(async (g) => {
2246
- const m = await g.get(f);
2345
+ const { expectedRevision: i } = Be(await j(a)), o = Me(a), d = (/* @__PURE__ */ new Date()).toISOString(), { firestore: u, forms: l } = await n(a), f = l.doc(c);
2346
+ return await u.runTransaction(async (p) => {
2347
+ const m = await p.get(f);
2247
2348
  if (!m.exists)
2248
- throw y({ statusCode: 404, statusMessage: "Form not found." });
2249
- const h = te(m.data());
2250
- ue(h, c), h.status !== "archived" && G("Only archived forms can be restored.");
2349
+ throw g({ statusCode: 404, statusMessage: "Form not found." });
2350
+ const h = ye(m.data());
2351
+ Ne(h, i), h.status !== "archived" && ae("Only archived forms can be restored.");
2251
2352
  const w = {
2252
2353
  status: h.publishedRevisionId ? "published" : "draft",
2253
2354
  statusBeforeArchive: null,
2254
2355
  revision: h.revision + 1,
2255
2356
  archivedAt: null,
2256
2357
  archivedBy: null,
2257
- updatedAt: u,
2358
+ updatedAt: d,
2258
2359
  updatedBy: o
2259
2360
  };
2260
- return g.update(f, w), X(n, { ...h, ...w }, s);
2361
+ return p.update(f, w), le(c, { ...h, ...w }, s);
2261
2362
  });
2262
- } catch (c) {
2263
- Z("restore", c, "Failed to restore form.");
2363
+ } catch (i) {
2364
+ me("restore", i, "Failed to restore form.");
2365
+ }
2366
+ })), r.handler;
2367
+ }
2368
+ const Jt = ["authentication", "billing", "notifications", "onboarding", "system"], Kt = ["draft", "active", "inactive"];
2369
+ function ta(e) {
2370
+ const t = e.context?.module;
2371
+ if (!t?.supabase || !t.instanceId || !t.projectId || !t.userId || t.moduleType !== "mailTemplates")
2372
+ throw g({ statusCode: 403, statusMessage: "Mail Templates module access is required." });
2373
+ return t;
2374
+ }
2375
+ function we(e, t) {
2376
+ const s = ta(e), r = Array.isArray(t) ? t : t ? [t] : [];
2377
+ if (r.length && !s.isAdmin && !r.some((n) => s.permissions?.includes(n)))
2378
+ throw g({ statusCode: 403, statusMessage: "You do not have permission for this template action." });
2379
+ return se(e, "Cache-Control", "private, no-store"), s;
2380
+ }
2381
+ function sa(e) {
2382
+ const t = typeof e == "string" ? e.trim() : "";
2383
+ if (!t || t.length > 512 || /[\\\u0000-\u001f\u007f]/.test(t) || t.split("/").length % 2 !== 1 || t.split("/").some((s) => !s || s === "." || s === ".." || /^__.*__$/.test(s)))
2384
+ throw g({ statusCode: 400, statusMessage: "Configure a valid Firestore templates collection." });
2385
+ return t;
2386
+ }
2387
+ function Le(e) {
2388
+ const t = U(e, "templateId");
2389
+ if (!t || t.length > 200 || /[\/\\\u0000-\u001f\u007f]/.test(t) || t === "." || t === ".." || /^__.*__$/.test(t))
2390
+ throw g({ statusCode: 400, statusMessage: "Invalid template ID." });
2391
+ return t;
2392
+ }
2393
+ function Ue(e, t, s, r = !1) {
2394
+ if (r && e === void 0) return "";
2395
+ if (typeof e != "string" || e.length > s || !r && !e.trim())
2396
+ throw g({ statusCode: 400, statusMessage: `${t} is required and must be at most ${s} characters.` });
2397
+ return e.trim();
2398
+ }
2399
+ function ze(e) {
2400
+ if (!e || !Array.isArray(e.blocks) || e.blocks.length > 200 || JSON.stringify(e.blocks).length > 4e5)
2401
+ throw g({ statusCode: 400, statusMessage: "Provide up to 200 email blocks (400 KB maximum)." });
2402
+ if (!e.styles || typeof e.styles != "object" || Array.isArray(e.styles) || JSON.stringify(e.styles).length > 2e4)
2403
+ throw g({ statusCode: 400, statusMessage: "Provide valid email styles." });
2404
+ return { blocks: e.blocks, styles: e.styles, preheader: Ue(e.preheader, "Preheader", 300, !0) };
2405
+ }
2406
+ function aa(e) {
2407
+ if (e.preserveVariables === !0) return {};
2408
+ const t = e.variables && typeof e.variables == "object" && !Array.isArray(e.variables) ? e.variables : {};
2409
+ if (JSON.stringify(t).length > 5e4) throw g({ statusCode: 400, statusMessage: "Preview variables are too large." });
2410
+ return { year: (/* @__PURE__ */ new Date()).getFullYear().toString(), ...Object.fromEntries(Object.entries(t).filter(([s, r]) => /^\w+$/.test(s) && typeof r == "string")) };
2411
+ }
2412
+ function oa(e, t) {
2413
+ return e.replace(/\{\{(\w+)\}\}/g, (s, r) => Object.prototype.hasOwnProperty.call(t, r) ? t[r] : s);
2414
+ }
2415
+ function Se(e) {
2416
+ throw Number.isInteger(e?.statusCode) && e.statusCode >= 400 && e.statusCode < 600 ? e : g({ statusCode: 500, statusMessage: "The template request could not be completed. Check the Firebase integration and try again." });
2417
+ }
2418
+ function Ve(e, t = !0) {
2419
+ const s = e.data() || {};
2420
+ return {
2421
+ id: e.id,
2422
+ name: typeof s.name == "string" ? s.name : "Untitled template",
2423
+ subject: typeof s.subject == "string" ? s.subject : "",
2424
+ description: typeof s.description == "string" ? s.description : "",
2425
+ preheader: typeof s.preheader == "string" ? s.preheader : "",
2426
+ category: Jt.includes(s.category) ? s.category : "notifications",
2427
+ status: Kt.includes(s.status) ? s.status : "draft",
2428
+ blocks: Array.isArray(s.blocks) ? s.blocks : [],
2429
+ styles: s.styles && typeof s.styles == "object" ? s.styles : {},
2430
+ createdAt: typeof s.createdAt == "string" ? s.createdAt : s.createdAt?.toDate?.().toISOString() || null,
2431
+ updatedAt: typeof s.updatedAt == "string" ? s.updatedAt : s.updatedAt?.toDate?.().toISOString() || null,
2432
+ ...t ? { mjml: typeof s.mjml == "string" ? s.mjml : "", html: typeof s.html == "string" ? s.html : "" } : {}
2433
+ };
2434
+ }
2435
+ function Ra(e) {
2436
+ const t = J();
2437
+ async function s(a, c) {
2438
+ const { data: i, error: o } = await c.supabase.from("project_modules").select("type, project_id, config").eq("id", c.instanceId).maybeSingle();
2439
+ if (o || i?.type !== "mailTemplates" || i.project_id !== c.projectId)
2440
+ throw g({ statusCode: 404, statusMessage: "Mail Templates module is unavailable." });
2441
+ const d = i.config?.project;
2442
+ if (typeof d != "string" || !d) throw g({ statusCode: 400, statusMessage: "Choose a Firebase integration in the module settings." });
2443
+ const u = sa(i.config?.templateCollection || "mail-templates"), { data: l, error: f } = await c.supabase.from("integrations").select("id, type").eq("id", d).eq("project_id", c.projectId).maybeSingle();
2444
+ if (f) throw g({ statusCode: 500, statusMessage: "Could not verify the Firebase integration." });
2445
+ if (!l || l.type !== "FIREBASE")
2446
+ throw g({ statusCode: 400, statusMessage: "The Firebase integration is unavailable for this project." });
2447
+ const m = (await e.initFirebase(a, l.id)).firestore();
2448
+ return { db: m, collection: m.collection(u) };
2449
+ }
2450
+ function r(a, c = {}) {
2451
+ try {
2452
+ const i = e.mailTemplates.render({ ...ze(a), variables: c });
2453
+ if (i.errors.length) throw g({ statusCode: 400, statusMessage: "Fix the MJML validation errors before saving.", data: { errors: i.errors } });
2454
+ return i;
2455
+ } catch (i) {
2456
+ throw i.statusCode ? i : g({ statusCode: 400, statusMessage: "The email contains invalid blocks or styles." });
2457
+ }
2458
+ }
2459
+ function n(a) {
2460
+ const c = Ue(a?.name, "Template name", 120), i = Ue(a?.subject, "Subject", 300), o = Ue(a?.description, "Description", 1e3, !0), d = a.category ?? "notifications", u = a.status ?? "draft";
2461
+ if (!Jt.includes(d) || !Kt.includes(u)) throw g({ statusCode: 400, statusMessage: "Invalid template category or status." });
2462
+ const l = r(a), f = { name: c, subject: i, description: o, category: d, status: u, ...ze(a), html: l.html, mjml: l.mjml };
2463
+ if (new TextEncoder().encode(JSON.stringify(f)).length > 9e5) throw g({ statusCode: 400, statusMessage: "This compiled template exceeds the storage limit. Reduce the content." });
2464
+ return f;
2465
+ }
2466
+ return t.get("/templates", b(async (a) => {
2467
+ const c = we(a);
2468
+ try {
2469
+ const { collection: i } = await s(a, c), o = await i.limit(101).get();
2470
+ if (o.docs.length > 100) throw g({ statusCode: 400, statusMessage: "This collection contains more than 100 templates. Configure a dedicated templates collection." });
2471
+ return o.docs.map((d) => Ve(d, !1)).sort((d, u) => (u.updatedAt || "").localeCompare(d.updatedAt || "") || d.name.localeCompare(u.name));
2472
+ } catch (i) {
2473
+ Se(i);
2474
+ }
2475
+ })), t.get("/templates/:templateId", b(async (a) => {
2476
+ const c = we(a), i = Le(a);
2477
+ try {
2478
+ const { collection: o } = await s(a, c), d = await o.doc(i).get();
2479
+ if (!d.exists) throw g({ statusCode: 404, statusMessage: "Template not found." });
2480
+ return Ve(d);
2481
+ } catch (o) {
2482
+ Se(o);
2483
+ }
2484
+ })), t.post("/templates", b(async (a) => {
2485
+ const c = we(a, "create-template"), i = n(await j(a));
2486
+ try {
2487
+ const { collection: o } = await s(a, c), d = o.doc(), u = (/* @__PURE__ */ new Date()).toISOString(), l = { ...i, createdAt: u, updatedAt: u };
2488
+ return await d.create(l), { id: d.id, ...l };
2489
+ } catch (o) {
2490
+ Se(o);
2491
+ }
2492
+ })), t.patch("/templates/:templateId", b(async (a) => {
2493
+ const c = we(a, "edit-template"), i = Le(a), o = await j(a), d = n(o);
2494
+ try {
2495
+ const { db: u, collection: l } = await s(a, c), f = l.doc(i);
2496
+ return await u.runTransaction(async (p) => {
2497
+ const m = await p.get(f);
2498
+ if (!m.exists) throw g({ statusCode: 404, statusMessage: "Template not found." });
2499
+ const h = Ve(m);
2500
+ if (o.updatedAt !== void 0 && o.updatedAt !== h.updatedAt)
2501
+ throw g({ statusCode: 409, statusMessage: "This template was updated elsewhere. Reload it before saving." });
2502
+ const y = Math.max(Date.now(), (Date.parse(h.updatedAt || "") || 0) + 1), w = { ...d, updatedAt: new Date(y).toISOString() };
2503
+ return p.update(f, w), { ...h, ...w };
2504
+ });
2505
+ } catch (u) {
2506
+ Se(u);
2507
+ }
2508
+ })), t.delete("/templates/:templateId", b(async (a) => {
2509
+ const c = we(a, "delete-template"), i = Le(a);
2510
+ try {
2511
+ const { db: o, collection: d } = await s(a, c), u = d.doc(i);
2512
+ return await o.runTransaction(async (l) => {
2513
+ if (!(await l.get(u)).exists) throw g({ statusCode: 404, statusMessage: "Template not found." });
2514
+ l.delete(u);
2515
+ }), { success: !0 };
2516
+ } catch (o) {
2517
+ Se(o);
2518
+ }
2519
+ })), t.post("/render", b(async (a) => {
2520
+ we(a);
2521
+ const c = await j(a), i = ze(c), o = aa(c);
2522
+ try {
2523
+ return { ...e.mailTemplates.render({ ...i, variables: o }), subject: oa(typeof c.subject == "string" ? c.subject : "", o) };
2524
+ } catch {
2525
+ throw g({ statusCode: 400, statusMessage: "The email contains invalid blocks or styles." });
2526
+ }
2527
+ })), t.handler;
2528
+ }
2529
+ const na = /* @__PURE__ */ new Set(["FIREBASE", "FTP", "SFTP", "S3", "CLOUDFLARE_R2"]);
2530
+ function ra(e) {
2531
+ const t = e?.context?.module;
2532
+ if (!t?.supabase || !t?.instanceId || !t?.projectId || t.moduleType !== "filezone")
2533
+ throw g({ statusCode: 500, statusMessage: "File Zone context is unavailable." });
2534
+ return t;
2535
+ }
2536
+ function He(e, t = !1) {
2537
+ const s = ra(e);
2538
+ if (t ? !s.isAdmin : !s.isAdmin && !s.permissions.includes("view-files"))
2539
+ throw g({ statusCode: 403, statusMessage: t ? "Only Studio administrators can upload files." : "You cannot view files in this module." });
2540
+ return s;
2541
+ }
2542
+ function De(e, t = !1) {
2543
+ if (e == null || e === "") {
2544
+ if (t) return "";
2545
+ throw g({ statusCode: 400, statusMessage: "A file path is required." });
2546
+ }
2547
+ if (typeof e != "string" || e.length > 1024 || e.startsWith("/") || e.endsWith("/") || /[\\\u0000-\u001f\u007f]/.test(e) || e.split("/").some((s) => !s || s === "." || s === ".."))
2548
+ throw g({ statusCode: 400, statusMessage: "Invalid storage path." });
2549
+ return e;
2550
+ }
2551
+ function vt(e) {
2552
+ const t = e.replace(/\\/g, "/").split("/").pop()?.trim() || "";
2553
+ if (!t || t.length > 180 || /[\u0000-\u001f\u007f]/.test(t) || t === "." || t === "..")
2554
+ throw g({ statusCode: 400, statusMessage: "File name is invalid or too long." });
2555
+ return t;
2556
+ }
2557
+ function Ee(...e) {
2558
+ return e.filter(Boolean).join("/");
2559
+ }
2560
+ function _t(e) {
2561
+ return e.replace(/^[a-f0-9]{8}-[a-f0-9]{4}-[1-8][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}-/, "");
2562
+ }
2563
+ function Rt(e) {
2564
+ const t = e.split(".").pop()?.toLowerCase() || "";
2565
+ return { pdf: "application/pdf", jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", gif: "image/gif", webp: "image/webp", txt: "text/plain", csv: "text/csv" }[t] || "application/octet-stream";
2566
+ }
2567
+ function We(e, t) {
2568
+ throw Number.isInteger(e?.statusCode) && e.statusCode >= 400 && e.statusCode < 600 ? e : (console.error("File Zone " + t + " failed:", e), g({ statusCode: 500, statusMessage: "Could not " + t + " file." }));
2569
+ }
2570
+ function xa({ filezone: e }) {
2571
+ const t = J();
2572
+ async function s(r) {
2573
+ const { data: n, error: a } = await r.supabase.from("project_modules").select("type, project_id, config").eq("id", r.instanceId).maybeSingle();
2574
+ if (a || n?.type !== "filezone" || n.project_id !== r.projectId)
2575
+ throw g({ statusCode: 404, statusMessage: "File Zone module is unavailable." });
2576
+ const c = n.config?.storageIntegration;
2577
+ if (typeof c != "string" || !/^[a-f0-9-]{36}$/i.test(c))
2578
+ throw g({ statusCode: 400, statusMessage: "File Zone has no valid storage integration." });
2579
+ const { data: i, error: o } = await r.supabase.from("integrations").select("id, type, config").eq("id", c).eq("project_id", r.projectId).maybeSingle();
2580
+ if (o) throw g({ statusCode: 500, statusMessage: "Could not check storage integration." });
2581
+ if (!i || !na.has(i.type))
2582
+ throw g({ statusCode: 400, statusMessage: "The storage integration is unavailable for this project." });
2583
+ return { provider: i, root: De(n.config?.folderPath, !0) };
2584
+ }
2585
+ return t.get("/files", b(async (r) => {
2586
+ const n = He(r), a = v(r), c = De(a.folder, !0), i = a.cursor === void 0 ? null : typeof a.cursor == "string" && a.cursor.length <= 4096 ? a.cursor : null;
2587
+ if (a.cursor !== void 0 && i === null) throw g({ statusCode: 400, statusMessage: "Invalid file page." });
2588
+ try {
2589
+ const { provider: o, root: d } = await s(n), { objects: u, nextCursor: l } = await e.list(r, o, Ee(d, c), i), f = u.flatMap((p) => {
2590
+ const m = d ? p.key.startsWith(d + "/") ? p.key.slice(d.length + 1) : "" : p.key;
2591
+ if (!m || m.split("/").slice(0, -1).join("/") !== c) return [];
2592
+ try {
2593
+ De(m);
2594
+ } catch {
2595
+ return [];
2596
+ }
2597
+ const h = _t(p.name);
2598
+ return [{
2599
+ path: m,
2600
+ name: h,
2601
+ directory: p.directory,
2602
+ size_bytes: p.size,
2603
+ content_type: p.directory ? null : p.contentType || Rt(h),
2604
+ modified_at: p.modified
2605
+ }];
2606
+ });
2607
+ return se(r, "Cache-Control", "private, no-store"), { files: f, nextCursor: l };
2608
+ } catch (o) {
2609
+ We(o, "list");
2610
+ }
2611
+ })), t.post("/files", b(async (r) => {
2612
+ const n = He(r, !0), a = De(v(r).folder, !0), { provider: c, root: i } = await s(n);
2613
+ let o;
2614
+ try {
2615
+ o = await e.parseUpload(r);
2616
+ const d = vt(o.name);
2617
+ if (!Number.isInteger(o.size) || o.size < 1 || o.size > e.maxBytes)
2618
+ throw g({ statusCode: 413, statusMessage: "File must be between 1 byte and 25 MB." });
2619
+ const u = globalThis.crypto.randomUUID() + "-" + d, l = Ee(i, a, u), f = o.contentType && /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/i.test(o.contentType) ? o.contentType.toLowerCase() : "application/octet-stream";
2620
+ try {
2621
+ await e.upload(r, c, l, o.localPath, f);
2622
+ } catch (p) {
2623
+ throw await e.remove(r, c, l).catch((m) => console.error("File Zone partial upload cleanup failed:", m)), p;
2624
+ }
2625
+ return se(r, "Cache-Control", "private, no-store"), {
2626
+ path: Ee(a, u),
2627
+ name: d,
2628
+ directory: !1,
2629
+ size_bytes: o.size,
2630
+ content_type: f,
2631
+ modified_at: (/* @__PURE__ */ new Date()).toISOString()
2632
+ };
2633
+ } catch (d) {
2634
+ We(d, "upload");
2635
+ } finally {
2636
+ await o?.cleanup();
2637
+ }
2638
+ })), t.get("/files/content", b(async (r) => {
2639
+ const n = He(r), a = v(r), c = De(a.path), i = _t(vt(c.split("/").pop())), { provider: o, root: d } = await s(n);
2640
+ try {
2641
+ const u = await e.read(r, o, Ee(d, c)), l = Rt(i), f = a.view === "1" && /^(application\/pdf|image\/(jpeg|png|gif|webp))$/.test(l), p = i.replace(/[^\x20-\x7e]|["\\]/g, "_");
2642
+ return se(r, "Content-Type", f ? l : "application/octet-stream"), se(r, "Content-Disposition", (f ? "inline" : "attachment") + '; filename="' + p + `"; filename*=UTF-8''` + encodeURIComponent(i)), se(r, "X-Content-Type-Options", "nosniff"), se(r, "Cache-Control", "private, no-store"), se(r, "Content-Security-Policy", "sandbox"), u;
2643
+ } catch (u) {
2644
+ We(u, "read");
2645
+ }
2646
+ })), t.handler;
2647
+ }
2648
+ const ia = "https://graph.facebook.com/v25.0/";
2649
+ class F extends Error {
2650
+ constructor(t, s, r = null) {
2651
+ super(s), this.statusCode = t, this.code = r, this.name = "WhatsAppProviderError";
2652
+ }
2653
+ statusCode;
2654
+ code;
2655
+ }
2656
+ function Qt(e = fetch) {
2657
+ return async (t, s, r = {}) => {
2658
+ if (!/^\d{1,30}(?:\/(?:phone_numbers|message_templates|template_analytics|whatsapp_business_profile))?$/.test(s))
2659
+ throw new F(500, "Invalid WhatsApp API operation.");
2660
+ const n = new URL(s, ia);
2661
+ for (const [i, o] of Object.entries(r.query || {}))
2662
+ o !== void 0 && i !== "access_token" && n.searchParams.set(i, String(o));
2663
+ const a = new AbortController(), c = setTimeout(() => a.abort(), Math.max(1, Math.min(15e3, r.timeoutMs || 15e3)));
2664
+ try {
2665
+ const i = await e(n.toString(), {
2666
+ method: r.method || "GET",
2667
+ headers: { Authorization: `Bearer ${t}`, "Content-Type": "application/json" },
2668
+ ...r.body ? { body: JSON.stringify(r.body) } : {},
2669
+ signal: a.signal,
2670
+ redirect: "error"
2671
+ });
2672
+ if (Number(i.headers.get("content-length")) > 4e6)
2673
+ throw new F(502, "Meta returned too much data. Narrow the request.");
2674
+ const o = i.body?.getReader(), d = [];
2675
+ let u = 0;
2676
+ if (o)
2677
+ for (; ; ) {
2678
+ const m = await o.read();
2679
+ if (m.done) break;
2680
+ if (u += m.value.byteLength, u > 4e6)
2681
+ throw await o.cancel(), new F(502, "Meta returned too much data. Narrow the request.");
2682
+ d.push(m.value);
2683
+ }
2684
+ const l = new Uint8Array(u);
2685
+ let f = 0;
2686
+ for (const m of d)
2687
+ l.set(m, f), f += m.byteLength;
2688
+ let p;
2689
+ try {
2690
+ p = JSON.parse(new TextDecoder().decode(l));
2691
+ } catch {
2692
+ throw new F(502, "Meta returned an unreadable response.");
2693
+ }
2694
+ if (!i.ok || p?.error) {
2695
+ const m = Number.isSafeInteger(p?.error?.code) ? p.error.code : null;
2696
+ throw m === 190 || i.status === 401 ? new F(424, "The WhatsApp access token is invalid or expired. Reconnect it in Studio project integrations.", m) : [10, 200, 294].includes(m) || i.status === 403 ? new F(424, "Meta denied this operation. Check the token permissions and access to this WhatsApp account.", m) : [4, 17, 32, 613, 80007, 130429].includes(m) || i.status === 429 ? new F(429, "Meta is limiting requests. Wait before trying again.", m) : new F(
2697
+ i.status >= 500 ? 502 : 422,
2698
+ `Meta could not complete this request${m === null ? "" : ` (code ${m})`}. Check the account and template requirements.`,
2699
+ m
2700
+ );
2701
+ }
2702
+ if (!p || typeof p != "object" || Array.isArray(p))
2703
+ throw new F(502, "Meta returned an unexpected response.");
2704
+ return p;
2705
+ } catch (i) {
2706
+ throw i instanceof F ? i : new F(
2707
+ a.signal.aborted ? 504 : 502,
2708
+ a.signal.aborted ? "The WhatsApp request timed out. Refresh before retrying a change." : "Could not reach the WhatsApp API."
2709
+ );
2710
+ } finally {
2711
+ clearTimeout(c);
2712
+ }
2713
+ };
2714
+ }
2715
+ function Je(e, t, s) {
2716
+ const r = Date.now() + s;
2717
+ let n = 0;
2718
+ return async (a, c, i = {}) => {
2719
+ const o = r - Date.now();
2720
+ if (++n > t || o <= 0)
2721
+ throw new F(504, "The WhatsApp data request reached its time or page limit. Try a shorter period.");
2722
+ return e(a, c, { ...i, timeoutMs: Math.min(15e3, o) });
2723
+ };
2724
+ }
2725
+ function fe(e) {
2726
+ throw e instanceof F ? g({ statusCode: e.statusCode, statusMessage: e.message }) : g({ statusCode: 502, statusMessage: "Could not complete the WhatsApp request." });
2727
+ }
2728
+ function S(e, t = 2048) {
2729
+ return typeof e == "string" && e.length ? e.slice(0, t) : null;
2730
+ }
2731
+ function Te(e) {
2732
+ const t = e.paging?.cursors?.after;
2733
+ return e.paging?.next && typeof t == "string" && t.length <= 2048 && !/[\r\n]/.test(t) ? t : null;
2734
+ }
2735
+ function ve(e) {
2736
+ if (!Array.isArray(e.data) || e.data.length > 1e4)
2737
+ throw new F(502, "Meta returned an unexpected response.");
2738
+ return e.data.filter((t) => t !== null && typeof t == "object" && !Array.isArray(t));
2739
+ }
2740
+ const st = (e) => !/[{}]/.test(e), Ge = x().trim().min(1).max(25).refine(st, "Button labels cannot contain variables."), ca = rs("type", [
2741
+ O({ type: ke("QUICK_REPLY"), text: Ge }).strict(),
2742
+ O({ type: ke("URL"), text: Ge, url: x().trim().url().max(2e3).refine((e) => /^https:\/\//i.test(e) && st(e), "Use a static HTTPS URL without variables.") }).strict(),
2743
+ O({ type: ke("PHONE_NUMBER"), text: Ge, phoneNumber: x().regex(/^\+[1-9]\d{1,14}$/, "Use an international phone number starting with +.") }).strict()
2744
+ ]), Zt = O({
2745
+ name: x().min(1).max(512).regex(/^[a-z0-9_]+$/, "Template names use lowercase letters, numbers and underscores."),
2746
+ language: x().regex(/^[a-z]{2,3}(?:_[A-Z]{2})?$/, "Use a WhatsApp language code, for example en_US or nl."),
2747
+ category: Ke(["UTILITY", "MARKETING"]),
2748
+ headerText: x().max(60).optional(),
2749
+ headerExample: x().trim().max(1024).optional(),
2750
+ bodyText: x().min(1).max(1024).refine((e) => e.trim().length > 0, "Body text is required."),
2751
+ bodyExamples: it(x().trim().max(1024)).max(20).optional(),
2752
+ footerText: x().max(60).refine(st, "Footer text cannot contain variables.").optional(),
2753
+ buttons: it(ca).max(3).optional()
2754
+ }).strict();
2755
+ function ie(e) {
2756
+ const t = [...e.matchAll(/\{\{([1-9]\d*)\}\}/g)].map((n) => n[1]), s = e.replace(/\{\{[1-9]\d*\}\}/g, "");
2757
+ if (/[{}]/.test(s)) throw new Error("Use numbered variables such as {{1}} and {{2}}.");
2758
+ const r = [...new Set(t)].sort((n, a) => Number(n) - Number(a));
2759
+ if (r.some((n, a) => Number(n) !== a + 1)) throw new Error("Number variables consecutively starting at {{1}}.");
2760
+ return r;
2761
+ }
2762
+ function Xt(e, t) {
2763
+ const s = ie(e.headerText || ""), r = ie(e.bodyText);
2764
+ if (s.length > 1) throw new Error("A text header supports one numbered variable.");
2765
+ if (r.length > 20) throw new Error("This editor supports up to 20 body variables.");
2766
+ if (t && s.length && !e.headerExample?.trim()) throw new Error("Provide an example for the header variable.");
2767
+ if (t && (e.bodyExamples?.length || 0) !== r.length) throw new Error("Provide exactly one example for each body variable.");
2768
+ if (t && e.bodyExamples?.some((c) => !c.trim())) throw new Error("Variable examples cannot be empty.");
2769
+ const n = e.buttons || [], a = n.filter((c) => c.type === "QUICK_REPLY").length;
2770
+ if (a && a !== n.length) throw new Error("Use either quick replies or action buttons in this editor.");
2771
+ if (n.filter((c) => c.type === "URL").length > 1 || n.filter((c) => c.type === "PHONE_NUMBER").length > 1)
2772
+ throw new Error("Use at most one website and one phone button.");
2773
+ }
2774
+ function xt(e) {
2775
+ const t = Zt.safeParse(e);
2776
+ if (!t.success) throw g({ statusCode: 400, statusMessage: t.error.issues[0]?.message || "Invalid template." });
2777
+ try {
2778
+ Xt(t.data, !0);
2779
+ } catch (s) {
2780
+ throw g({ statusCode: 400, statusMessage: s.message });
2781
+ }
2782
+ return t.data;
2783
+ }
2784
+ function Ft(e) {
2785
+ const t = [];
2786
+ return e.headerText && t.push({
2787
+ type: "HEADER",
2788
+ format: "TEXT",
2789
+ text: e.headerText,
2790
+ ...ie(e.headerText).length ? { example: { header_text: [e.headerExample] } } : {}
2791
+ }), t.push({
2792
+ type: "BODY",
2793
+ text: e.bodyText,
2794
+ ...ie(e.bodyText).length ? { example: { body_text: [e.bodyExamples] } } : {}
2795
+ }), e.footerText && t.push({ type: "FOOTER", text: e.footerText }), e.buttons?.length && t.push({ type: "BUTTONS", buttons: e.buttons.map((s) => s.type === "PHONE_NUMBER" ? { type: s.type, text: s.text, phone_number: s.phoneNumber } : { ...s }) }), t;
2796
+ }
2797
+ const Pe = (e, t) => Object.keys(e).every((s) => t.includes(s));
2798
+ function da(e) {
2799
+ if (!["UTILITY", "MARKETING"].includes(e.category) || e.parameter_format && e.parameter_format !== "POSITIONAL" || e.source === "AUTO_GENERATED" || !Array.isArray(e.components)) return null;
2800
+ const t = { name: e.name, language: e.language, category: e.category, bodyText: "" }, s = /* @__PURE__ */ new Set();
2801
+ for (const n of e.components) {
2802
+ if (!n || typeof n != "object" || s.has(n.type) || (s.add(n.type), !Pe(n, ["type", "format", "text", "example", "buttons"]))) return null;
2803
+ if (n.type === "HEADER") {
2804
+ if (n.format !== "TEXT" || typeof n.text != "string" || n.buttons || n.example && !Pe(n.example, ["header_text"])) return null;
2805
+ t.headerText = n.text, t.headerExample = n.example?.header_text?.[0] || "";
2806
+ } else if (n.type === "BODY") {
2807
+ if (typeof n.text != "string" || n.format || n.buttons || n.example && !Pe(n.example, ["body_text"])) return null;
2808
+ t.bodyText = n.text, t.bodyExamples = n.example?.body_text?.[0] || [];
2809
+ } else if (n.type === "FOOTER") {
2810
+ if (typeof n.text != "string" || n.format || n.buttons || n.example) return null;
2811
+ t.footerText = n.text;
2812
+ } else if (n.type === "BUTTONS") {
2813
+ if (!Array.isArray(n.buttons) || n.format || n.text || n.example) return null;
2814
+ t.buttons = [];
2815
+ for (const a of n.buttons) {
2816
+ if (!a || typeof a != "object" || !Pe(a, ["type", "text", "url", "phone_number"])) return null;
2817
+ if (a.type === "QUICK_REPLY" && !a.url && !a.phone_number) t.buttons.push({ type: "QUICK_REPLY", text: a.text });
2818
+ else if (a.type === "URL" && !a.phone_number) t.buttons.push({ type: "URL", text: a.text, url: a.url });
2819
+ else if (a.type === "PHONE_NUMBER" && !a.url) t.buttons.push({ type: "PHONE_NUMBER", text: a.text, phoneNumber: a.phone_number });
2820
+ else return null;
2821
+ }
2822
+ } else return null;
2823
+ }
2824
+ if (!s.has("BODY")) return null;
2825
+ const r = Zt.safeParse(t);
2826
+ if (!r.success) return null;
2827
+ try {
2828
+ Xt(r.data, !1);
2829
+ } catch {
2830
+ return null;
2831
+ }
2832
+ return r.data;
2833
+ }
2834
+ function Nt(e) {
2835
+ const t = da(e), s = ["APPROVED", "REJECTED", "PAUSED"].includes(e.status), r = (Array.isArray(e.components) ? e.components : []).slice(0, 20).map((n) => ({
2836
+ type: S(n?.type, 64) || "UNKNOWN",
2837
+ ...S(n?.format, 64) ? { format: n.format } : {},
2838
+ ...S(n?.text, 32768) ? { text: n.text.slice(0, 32768) } : {},
2839
+ ...Array.isArray(n?.buttons) ? { buttons: n.buttons.slice(0, 20).map((a) => ({
2840
+ type: S(a?.type, 64) || "UNKNOWN",
2841
+ ...S(a?.text, 1024) ? { text: a.text.slice(0, 1024) } : {},
2842
+ ...S(a?.url, 2048) ? { url: a.url.slice(0, 2048) } : {},
2843
+ ...S(a?.phone_number, 64) ? { phoneNumber: a.phone_number.slice(0, 64) } : {}
2844
+ })) } : {}
2845
+ }));
2846
+ return {
2847
+ id: S(e.id, 30) || "",
2848
+ name: S(e.name, 512) || "",
2849
+ language: S(e.language, 20) || "",
2850
+ category: S(e.category, 64) || "UNKNOWN",
2851
+ status: S(e.status, 64) || "UNKNOWN",
2852
+ quality: S(e.quality_score?.score, 64),
2853
+ rejectionReason: S(e.rejected_reason),
2854
+ components: r,
2855
+ editable: t !== null && s,
2856
+ editReason: t ? s ? null : "Meta permits editing only approved, rejected or paused templates." : "This template uses a format this editor cannot safely change. Manage it in WhatsApp Manager.",
2857
+ draft: t
2858
+ };
2859
+ }
2860
+ function ua(e, t) {
2861
+ if (!e.editable || !e.draft) throw g({ statusCode: 409, statusMessage: e.editReason || "This template cannot be edited here." });
2862
+ if (t.name !== e.name || t.language !== e.language || t.category !== e.category)
2863
+ throw g({ statusCode: 400, statusMessage: "Name, language and category must remain unchanged. Create a new template to change them." });
2864
+ const s = e.draft;
2865
+ if (JSON.stringify(ie(s.bodyText)) !== JSON.stringify(ie(t.bodyText)) || JSON.stringify(ie(s.headerText || "")) !== JSON.stringify(ie(t.headerText || "")))
2866
+ throw g({ statusCode: 400, statusMessage: "Create a new template to change variables used by existing automations." });
2867
+ if (JSON.stringify((s.buttons || []).map((r) => r.type)) !== JSON.stringify((t.buttons || []).map((r) => r.type)))
2868
+ throw g({ statusCode: 400, statusMessage: "Create a new template to change button count, types or order used by existing automations." });
2869
+ }
2870
+ const pe = (e) => typeof e == "number" && Number.isFinite(e) && e >= 0 ? e : null, oe = (e) => e.length && e.every((t) => t !== null) ? e.reduce((t, s) => t + s, 0) : null;
2871
+ function la(e) {
2872
+ if (!e.analytics || !Array.isArray(e.analytics.data_points))
2873
+ return { state: "unavailable", reason: "Meta did not provide message analytics for this account and period.", data: null };
2874
+ const t = e.analytics.data_points.filter((s) => Number.isSafeInteger(s?.start) && Number.isSafeInteger(s?.end)).map((s) => ({ start: s.start, end: s.end, sent: pe(s.sent), delivered: pe(s.delivered) }));
2875
+ return t.length !== e.analytics.data_points.length ? { state: "unavailable", reason: "Meta returned incomplete message analytics.", data: null } : {
2876
+ state: t.length ? "available" : "empty",
2877
+ reason: t.length ? null : "Meta returned no message data for this period.",
2878
+ data: { sent: oe(t.map((s) => s.sent)), delivered: oe(t.map((s) => s.delivered)), points: t }
2879
+ };
2880
+ }
2881
+ function ma(e, t, s, r) {
2882
+ if (e.some((o) => !Array.isArray(o.data_points)))
2883
+ return { state: "unavailable", reason: "Meta returned an unsupported template analytics response.", data: null };
2884
+ const n = new Map(t.map((o) => [o.id, o])), a = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
2885
+ for (const o of e)
2886
+ for (const d of o.data_points) {
2887
+ if (!d || !n.has(d.template_id) || !Number.isSafeInteger(d.start) || !Number.isSafeInteger(d.end)) continue;
2888
+ const u = `${d.template_id}:${d.start}:${d.end}`;
2889
+ if (c.has(u)) continue;
2890
+ c.add(u);
2891
+ const l = a.get(d.template_id) || [];
2892
+ l.push(d), a.set(d.template_id, l);
2893
+ }
2894
+ const i = t.map((o) => {
2895
+ const d = a.get(o.id) || [];
2896
+ return {
2897
+ id: o.id,
2898
+ name: S(o.name, 512) || o.id,
2899
+ language: S(o.language, 20) || "",
2900
+ sent: oe(d.map((u) => pe(u.sent))),
2901
+ delivered: oe(d.map((u) => pe(u.delivered))),
2902
+ read: oe(d.map((u) => pe(u.read))),
2903
+ clicked: oe(d.map((u) => Array.isArray(u.clicked) ? u.clicked.length ? oe(u.clicked.map((l) => pe(l?.count))) : 0 : null)),
2904
+ amountSpent: oe(d.map((u) => Array.isArray(u.cost) ? pe(u.cost.find((l) => l?.type === "amount_spent")?.value) : null))
2905
+ };
2906
+ });
2907
+ return {
2908
+ state: c.size ? "available" : "empty",
2909
+ reason: r ? "Only part of the account could be loaded. Metrics shown cover completed template queries only." : c.size ? null : "Meta returned no template metrics for this period. Missing values are not zero.",
2910
+ data: { templates: i, currency: s, truncated: r }
2911
+ };
2912
+ }
2913
+ const Fe = x().regex(/^\d{1,30}$/, "Use the numeric ID from Meta."), es = x().trim().min(10, "Enter a valid access token.").max(16384).regex(/^\S+$/, "The token cannot contain whitespace."), at = O({
2914
+ wabaId: Fe,
2915
+ accessToken: es
2916
+ }).strict(), fa = at.extend({ phoneNumberId: Fe }), pa = at.extend({ phoneNumberId: Fe.optional() }), ts = "id,display_phone_number,verified_name,quality_rating,code_verification_status";
2917
+ function ss(e) {
2918
+ return {
2919
+ id: S(e.id, 30) || "",
2920
+ displayPhoneNumber: S(e.display_phone_number, 64),
2921
+ verifiedName: S(e.verified_name, 256),
2922
+ qualityRating: S(e.quality_rating, 64),
2923
+ verificationStatus: S(e.code_verification_status, 64)
2924
+ };
2925
+ }
2926
+ async function ga(e, t = Qt()) {
2927
+ const s = pa.safeParse(e);
2928
+ if (!s.success) throw new F(400, s.error.issues[0]?.message || "Invalid WhatsApp connection.");
2929
+ const { wabaId: r, accessToken: n, phoneNumberId: a } = s.data, c = 5, i = Je(t, c + 1, 3e4), o = await i(n, r, { query: { fields: "id,name" } });
2930
+ if (o.id !== r) throw new F(422, "Meta did not return the requested WhatsApp Business account.");
2931
+ const d = [];
2932
+ let u = null;
2933
+ const l = /* @__PURE__ */ new Set();
2934
+ for (let f = 0; f < c; f++) {
2935
+ const p = await i(n, `${r}/phone_numbers`, { query: { fields: ts, limit: 100, after: u || void 0 } });
2936
+ for (const m of ve(p))
2937
+ Fe.safeParse(m.id).success && !d.some((h) => h.id === m.id) && d.push(ss(m));
2938
+ if (u = Te(p), !u) break;
2939
+ if (l.has(u)) throw new F(502, "Meta returned a repeated page. Try again later.");
2940
+ l.add(u);
2941
+ }
2942
+ if (a && !d.some((f) => f.id === a))
2943
+ throw new F(400, u ? "The selected number could not be verified within this account. Use a token with access to the correct number." : "The selected phone number does not belong to this WhatsApp Business account.");
2944
+ return { wabaId: r, wabaName: S(o.name, 256), phones: d, truncated: u !== null };
2945
+ }
2946
+ const Fa = {
2947
+ verify: ga,
2948
+ testSchema: at,
2949
+ connectSchema: fa,
2950
+ toHttpError: fe
2951
+ }, Et = "whatsappBusiness", Pt = "id,name,language,category,status,quality_score,rejected_reason,components,parameter_format,source", kt = 20, Ie = Fe, ha = O({
2952
+ wabaId: Ie,
2953
+ phoneNumberId: Ie,
2954
+ displayPhoneNumber: x().max(64).nullish().transform((e) => e || ""),
2955
+ verifiedName: x().max(256).nullish().transform((e) => e || ""),
2956
+ accessToken: x().min(1).max(32768)
2957
+ }), ya = x().min(1).max(2048).refine((e) => !/[\r\n]/.test(e)), Ut = O({
2958
+ search: x().trim().min(1).max(200).optional(),
2959
+ name: x().min(1).max(512).regex(/^[a-z0-9_]+$/).optional(),
2960
+ after: ya.optional(),
2961
+ status: Ke(["APPROVED", "ARCHIVED", "DELETED", "DISABLED", "IN_APPEAL", "LIMIT_EXCEEDED", "PAUSED", "PENDING", "PENDING_DELETION", "REJECTED"]).optional()
2962
+ }).strict(), wa = (e) => g({ statusCode: 400, statusMessage: e });
2963
+ function be(e, t) {
2964
+ const s = e.safeParse(t);
2965
+ if (!s.success) throw wa(s.error.issues[0]?.message || "Invalid request.");
2966
+ return s.data;
2967
+ }
2968
+ function Oe(e) {
2969
+ return {
2970
+ view: e.isAdmin || e.permissions.includes("view-whatsapp"),
2971
+ manageTemplates: e.isAdmin || e.permissions.includes("manage-whatsapp-templates"),
2972
+ manageInsights: e.isAdmin || e.permissions.includes("manage-whatsapp-insights")
2973
+ };
2974
+ }
2975
+ function ba(e, t) {
2976
+ return {
2977
+ connected: t !== null,
2978
+ canManageConnection: e.isAdmin,
2979
+ permissions: Oe(e),
2980
+ wabaId: t?.wabaId || null,
2981
+ phoneNumberId: t?.phoneNumberId || null,
2982
+ displayPhoneNumber: t?.displayPhoneNumber || null,
2983
+ verifiedName: t?.verifiedName || null,
2984
+ updatedAt: null
2985
+ };
2986
+ }
2987
+ function Ce(e) {
2988
+ return { state: "unavailable", reason: e instanceof F ? e.message : "Meta did not make this information available.", data: null };
2989
+ }
2990
+ function Na(e) {
2991
+ const t = e.graphRequest || Qt(), s = J();
2992
+ async function r(i, o = "view") {
2993
+ ns(i, "Cache-Control", "private, no-store");
2994
+ const d = i.context.module;
2995
+ if (!d?.supabase || !d.instanceId || !d.projectId || d.moduleType !== Et || !d.userId || !Array.isArray(d.permissions))
2996
+ throw g({ statusCode: 403, statusMessage: "WhatsApp module access is unavailable." });
2997
+ if (!Oe(d).view || !Oe(d)[o])
2998
+ throw g({ statusCode: 403, statusMessage: "You do not have permission for this WhatsApp action." });
2999
+ const { data: u, error: l } = await d.supabase.from("project_modules").select("id, config").eq("id", d.instanceId).eq("project_id", d.projectId).eq("type", Et).maybeSingle();
3000
+ if (l) throw g({ statusCode: 503, statusMessage: "Could not verify the WhatsApp module." });
3001
+ if (!u) throw g({ statusCode: 404, statusMessage: "WhatsApp module not found in this project." });
3002
+ const f = u.config?.account;
3003
+ if (f && !x().uuid().safeParse(f).success)
3004
+ throw g({ statusCode: 424, statusMessage: "Select a WhatsApp integration from this project in the module settings." });
3005
+ return { ...d, accountId: f || void 0 };
3006
+ }
3007
+ async function n(i) {
3008
+ if (!i.accountId) return null;
3009
+ const { data: o, error: d } = await i.supabase.from("integrations").select("id, config").eq("id", i.accountId).eq("project_id", i.projectId).eq("type", "WHATSAPP").maybeSingle();
3010
+ if (d) throw g({ statusCode: 503, statusMessage: "Could not load the selected WhatsApp integration." });
3011
+ if (!o) throw g({ statusCode: 424, statusMessage: "The selected WhatsApp integration is unavailable in this project. Update the module settings." });
3012
+ const u = ha.safeParse(o.config);
3013
+ if (!u.success) throw g({ statusCode: 424, statusMessage: "The selected WhatsApp integration is incomplete. Reconnect it in project integrations." });
3014
+ return u.data;
3015
+ }
3016
+ async function a(i) {
3017
+ const o = await n(i);
3018
+ if (!o) throw g({ statusCode: 424, statusMessage: "Select a WhatsApp integration in the module settings first." });
3019
+ let d;
3020
+ try {
3021
+ if (d = e.decrypt(o.accessToken), !es.safeParse(d).success) throw new Error("Invalid stored token");
3022
+ } catch {
3023
+ throw g({ statusCode: 503, statusMessage: "The saved WhatsApp credential could not be read. Ask an administrator to reconnect it." });
3024
+ }
3025
+ return { row: o, token: d };
3026
+ }
3027
+ async function c(i, o, d, u) {
3028
+ const l = Je(t, kt, 3e4);
3029
+ let f = null;
3030
+ const p = /* @__PURE__ */ new Set();
3031
+ for (let m = 0; m < kt; m++) {
3032
+ const h = await l(i, `${o}/message_templates`, {
3033
+ query: { fields: Pt, limit: 100, name: u, after: f || void 0 }
3034
+ }), y = ve(h).find((w) => w.id === d);
3035
+ if (y) return Nt(y);
3036
+ if (f = Te(h), !f) throw g({ statusCode: 404, statusMessage: "Template not found in the connected WhatsApp account." });
3037
+ if (p.has(f)) throw new F(502, "Meta returned a repeated page. Try again later.");
3038
+ p.add(f);
3039
+ }
3040
+ throw g({ statusCode: 409, statusMessage: "This account has too many templates to search at once. Open the template from an exact-name search." });
3041
+ }
3042
+ return s.get("/connection", b(async (i) => {
3043
+ const o = await r(i);
3044
+ return ba(o, await n(o));
3045
+ })), s.get("/templates", b(async (i) => {
3046
+ const o = await r(i), { row: d, token: u } = await a(o), l = be(Ut, v(i));
3047
+ try {
3048
+ const f = await t(u, `${d.wabaId}/message_templates`, {
3049
+ query: { fields: Pt, limit: 50, name: l.name, name_or_content: l.search, status: l.status ? JSON.stringify([l.status]) : void 0, after: l.after }
3050
+ });
3051
+ return { templates: ve(f).filter((p) => !l.name || p.name === l.name).map(Nt), nextCursor: Te(f) };
3052
+ } catch (f) {
3053
+ fe(f);
3054
+ }
3055
+ })), s.get("/templates/:id", b(async (i) => {
3056
+ const o = await r(i), { row: d, token: u } = await a(o), l = be(Ie, U(i, "id")), f = be(O({ name: Ut.shape.name }).strict(), v(i));
3057
+ try {
3058
+ return await c(u, d.wabaId, l, f.name);
3059
+ } catch (p) {
3060
+ throw p instanceof F && fe(p), p;
3061
+ }
3062
+ })), s.post("/templates", b(async (i) => {
3063
+ const o = await r(i, "manageTemplates"), { row: d, token: u } = await a(o), l = xt(await j(i));
3064
+ try {
3065
+ const f = await t(u, `${d.wabaId}/message_templates`, { method: "POST", body: {
3066
+ name: l.name,
3067
+ language: l.language,
3068
+ category: l.category,
3069
+ parameter_format: "POSITIONAL",
3070
+ components: Ft(l)
3071
+ } });
3072
+ if (!Ie.safeParse(f.id).success) throw new F(502, "Meta did not confirm the template ID. Refresh the template list before trying again.");
3073
+ return { id: f.id, status: S(f.status, 64), category: S(f.category, 64), success: !0 };
3074
+ } catch (f) {
3075
+ fe(f);
3076
+ }
3077
+ })), s.patch("/templates/:id", b(async (i) => {
3078
+ const o = await r(i, "manageTemplates"), { row: d, token: u } = await a(o), l = be(Ie, U(i, "id")), f = xt(await j(i));
3079
+ let p;
3080
+ try {
3081
+ p = await c(u, d.wabaId, l, f.name);
3082
+ } catch (m) {
3083
+ throw m instanceof F && fe(m), m;
3084
+ }
3085
+ ua(p, f);
3086
+ try {
3087
+ if ((await t(u, l, { method: "POST", body: { components: Ft(f) } })).success !== !0) throw new F(502, "Meta did not confirm the change. Refresh the template before trying again.");
3088
+ return { id: l, status: null, category: p.category, success: !0 };
3089
+ } catch (m) {
3090
+ fe(m);
3091
+ }
3092
+ })), s.get("/overview", b(async (i) => {
3093
+ const o = await r(i), { row: d, token: u } = await a(o), [l, f, p, m] = await Promise.allSettled([
3094
+ t(u, d.wabaId, { query: { fields: "id,name,status,currency,business_verification_status,account_review_status" } }),
3095
+ t(u, d.phoneNumberId, { query: { fields: ts } }),
3096
+ t(u, d.phoneNumberId, { query: { fields: "health_status" } }),
3097
+ t(u, `${d.phoneNumberId}/whatsapp_business_profile`, { query: { fields: "about,address,description,email,vertical,websites" } })
3098
+ ]), h = m.status === "fulfilled" && Array.isArray(m.value.data) ? m.value.data[0] : null;
3099
+ return {
3100
+ account: l.status === "fulfilled" ? { state: "available", reason: null, data: {
3101
+ id: d.wabaId,
3102
+ name: S(l.value.name, 256),
3103
+ status: S(l.value.status, 64),
3104
+ currency: S(l.value.currency, 10),
3105
+ verificationStatus: S(l.value.business_verification_status, 64),
3106
+ reviewStatus: S(l.value.account_review_status, 64)
3107
+ } } : Ce(l.reason),
3108
+ phone: f.status === "fulfilled" ? { state: "available", reason: null, data: ss(f.value) } : Ce(f.reason),
3109
+ health: p.status === "fulfilled" && p.value.health_status ? { state: "available", reason: null, data: {
3110
+ canSendMessage: S(p.value.health_status.can_send_message, 64),
3111
+ entities: (Array.isArray(p.value.health_status.entities) ? p.value.health_status.entities : []).slice(0, 100).map((y) => ({
3112
+ id: S(y.id, 30),
3113
+ type: S(y.entity_type, 64),
3114
+ canSendMessage: S(y.can_send_message, 64)
3115
+ }))
3116
+ } } : Ce(p.status === "rejected" ? p.reason : null),
3117
+ profile: h ? { state: "available", reason: null, data: {
3118
+ about: S(h.about),
3119
+ address: S(h.address),
3120
+ description: S(h.description),
3121
+ email: S(h.email, 254),
3122
+ vertical: S(h.vertical, 64),
3123
+ websites: (Array.isArray(h.websites) ? h.websites : []).filter((y) => typeof y == "string" && /^https?:\/\//i.test(y)).slice(0, 10).map((y) => y.slice(0, 2048))
3124
+ } } : Ce(m.status === "rejected" ? m.reason : null)
3125
+ };
3126
+ })), s.get("/insights", b(async (i) => {
3127
+ const o = Je(t, 18, 2e4), d = await r(i), { row: u, token: l } = await a(d), f = be(O({ days: Ke(["7", "30", "90"]).optional() }).strict(), v(i)), p = Number(f.days || 30), m = e.now?.() || /* @__PURE__ */ new Date(), h = Math.floor(Date.UTC(m.getUTCFullYear(), m.getUTCMonth(), m.getUTCDate()) / 1e3), y = h - p * 86400, w = u.displayPhoneNumber.replace(/\D/g, ""), [C, A] = await Promise.allSettled([
3128
+ o(l, u.wabaId, { query: { fields: "id,is_enabled_for_insights,currency" } }),
3129
+ /^\d{6,15}$/.test(w) ? o(l, u.wabaId, { query: { fields: `analytics.start(${y}).end(${h}).granularity(DAY).phone_numbers(${JSON.stringify([w])})` } }) : Promise.reject(new F(424, "The connected phone number is unavailable. Reconnect it to load message analytics."))
3130
+ ]), I = C.status === "fulfilled" && typeof C.value.is_enabled_for_insights == "boolean" ? C.value.is_enabled_for_insights : null, M = C.status === "fulfilled" ? S(C.value.currency, 10) : null;
3131
+ let D;
3132
+ if (I === !1) D = { state: "unavailable", reason: "Template insights have not been enabled for this WhatsApp account.", data: null };
3133
+ else
3134
+ try {
3135
+ const _ = await o(l, `${u.wabaId}/message_templates`, { query: { fields: "id,name,language", limit: 50 } }), T = ve(_).filter((N) => Ie.safeParse(N.id).success).slice(0, 50), E = [];
3136
+ let V = Te(_) !== null;
3137
+ const P = [], K = Array.from({ length: Math.ceil(T.length / 10) }, (N, de) => T.slice(de * 10, de * 10 + 10)), Q = await Promise.allSettled(K.map(async (N) => {
3138
+ const de = [];
3139
+ let Z = null;
3140
+ const ot = /* @__PURE__ */ new Set();
3141
+ for (let nt = 0; nt < 3; nt++) {
3142
+ const rt = await o(l, `${u.wabaId}/template_analytics`, { query: {
3143
+ start: y,
3144
+ end: h,
3145
+ granularity: "DAILY",
3146
+ metric_types: JSON.stringify(["sent", "delivered", "read", "clicked"]),
3147
+ template_ids: JSON.stringify(N.map((as) => as.id)),
3148
+ use_waba_timezone: !1,
3149
+ limit: 1e3,
3150
+ after: Z || void 0
3151
+ } });
3152
+ if (de.push(...ve(rt)), Z = Te(rt), !Z) break;
3153
+ if (ot.has(Z)) throw new F(502, "Meta returned repeated analytics pages. Try again later.");
3154
+ ot.add(Z);
3155
+ }
3156
+ if (Z) throw new F(504, "Meta returned more analytics pages than this dashboard can load at once.");
3157
+ return { batch: N, batchPoints: de };
3158
+ }));
3159
+ for (const N of Q) {
3160
+ if (N.status === "rejected") {
3161
+ V = !0;
3162
+ continue;
3163
+ }
3164
+ E.push(...N.value.batchPoints), P.push(...N.value.batch);
3165
+ }
3166
+ if (Q.length && !P.length) throw Q.find((N) => N.status === "rejected").reason;
3167
+ D = ma(E, P, M, V);
3168
+ } catch (_) {
3169
+ D = Ce(_);
3170
+ }
3171
+ return {
3172
+ days: p,
3173
+ start: y,
3174
+ end: h,
3175
+ timezone: "UTC",
3176
+ phoneNumber: u.displayPhoneNumber,
3177
+ enabled: I,
3178
+ canEnable: Oe(d).manageInsights && I !== !0,
3179
+ messages: A.status === "fulfilled" ? la(A.value) : Ce(A.reason),
3180
+ templates: D
3181
+ };
3182
+ })), s.post("/insights/enable", b(async (i) => {
3183
+ const o = await r(i, "manageInsights");
3184
+ be(O({ confirm: ke(!0) }).strict(), await j(i));
3185
+ const { row: d, token: u } = await a(o);
3186
+ try {
3187
+ const l = await t(u, d.wabaId, { method: "POST", body: { is_enabled_for_insights: !0 } });
3188
+ if (l.id !== d.wabaId && l.success !== !0) throw new F(502, "Meta did not confirm insights activation. Refresh before trying again.");
3189
+ return { enabled: !0 };
3190
+ } catch (l) {
3191
+ fe(l);
2264
3192
  }
2265
- })), i.handler;
3193
+ })), s.handler;
2266
3194
  }
2267
3195
  export {
2268
- Qt as appointments,
2269
- Kt as contentManager,
2270
- Jt as firebaseAuthManager,
2271
- Xt as formBuilder,
2272
- Yt as googleAnalytics,
2273
- Gt as products
3196
+ Sa as appointments,
3197
+ Ta as contentManager,
3198
+ xa as filezone,
3199
+ va as firebaseAuthManager,
3200
+ _a as formBuilder,
3201
+ Da as googleAnalytics,
3202
+ Ra as mailTemplates,
3203
+ Ma as products,
3204
+ Na as whatsappBusiness,
3205
+ Fa as whatsappBusinessConnection
2274
3206
  };