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

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 (98) hide show
  1. package/dist/{ContentEditor-C-Wm48ai.js → ContentEditor-BcIUumah.js} +39 -39
  2. package/dist/{ContentEditor-MDGolnIP.mjs → ContentEditor-DX1bTQKs.mjs} +4910 -4793
  3. package/dist/{Detail-Dk8E6_uF.mjs → Detail-B7pe808q.mjs} +15 -14
  4. package/dist/Detail-BESGmY7z.js +1 -0
  5. package/dist/{Detail-Cn9Bk0u0.mjs → Detail-B_Q7Qkuz.mjs} +26 -25
  6. package/dist/Detail-CNiLIEh9.js +1 -0
  7. package/dist/{Detail-B_scnidb.mjs → Detail-DNxAzeCs.mjs} +35 -34
  8. package/dist/Detail-t3tOcy3X.js +1 -0
  9. package/dist/Editor-D4evcdhv.mjs +768 -0
  10. package/dist/Editor-gLLtuJbY.js +1 -0
  11. package/dist/FormStatusBadge.vue_vue_type_script_setup_true_lang-BjKpsqT9.js +1 -0
  12. package/dist/FormStatusBadge.vue_vue_type_script_setup_true_lang-D5v5AhLe.mjs +76 -0
  13. package/dist/Knowledge-B66vxz--.js +1 -0
  14. package/dist/Knowledge-BnMTTuJ7.mjs +742 -0
  15. package/dist/Overview-BE4uYPx0.mjs +745 -0
  16. package/dist/Overview-CQRpFhbJ.mjs +286 -0
  17. package/dist/Overview-CTs7sX4d.js +1 -0
  18. package/dist/Overview-Cj89XXKN.js +1 -0
  19. package/dist/Overview-D_c18mbR.mjs +248 -0
  20. package/dist/Overview-g4Rcj245.js +1 -0
  21. package/dist/TableView-6mdrL3zx.js +4 -0
  22. package/dist/{TableView-C4Zyp8d7.mjs → TableView-Du5nOE6R.mjs} +2 -2
  23. package/dist/Test-CzmOmi53.mjs +447 -0
  24. package/dist/Test-USDtNFY1.js +1 -0
  25. package/dist/UserDetail-DpUL3mhk.mjs +1483 -0
  26. package/dist/UserDetail-KRIfxaYd.js +1 -0
  27. package/dist/cms-core-modules.css +1 -1
  28. package/dist/index-CQuN5rKx.js +1 -0
  29. package/dist/index-CnDGeInm.js +1 -0
  30. package/dist/index-CqDTc5Ig.mjs +20 -0
  31. package/dist/index-CyvvAdt4.js +1 -0
  32. package/dist/index-DIRD7t5_.mjs +20 -0
  33. package/dist/index-OJuBYR60.mjs +57 -0
  34. package/dist/index.cjs.js +1 -1
  35. package/dist/index.mjs +327 -84
  36. package/dist/server-handlers.cjs.js +1 -1
  37. package/dist/server-handlers.mjs +1764 -605
  38. package/dist/src/contentManager/components/content-editor/tiptap-extensions/Container.d.ts +1 -1
  39. package/dist/src/contentManager/components/content-editor/tiptap-extensions/Row.d.ts +7 -0
  40. package/dist/src/contentManager/components/content-editor/tiptap-extensions/Stack.d.ts +7 -0
  41. package/dist/src/contentManager/components/content-editor/tiptap-extensions/helpers/resizeHistory.d.ts +9 -0
  42. package/dist/src/contentManager/components/content-editor/tiptap-menus/ElementEditorMenu.vue.d.ts +3 -1
  43. package/dist/src/firebaseAuthManager/components/DeleteUserDialog.vue.d.ts +25 -0
  44. package/dist/src/firebaseAuthManager/components/ReasonActionDialog.vue.d.ts +23 -0
  45. package/dist/src/firebaseAuthManager/components/UserStatusBadge.vue.d.ts +5 -0
  46. package/dist/src/firebaseAuthManager/config.d.ts +151 -0
  47. package/dist/src/firebaseAuthManager/index.d.ts +163 -0
  48. package/dist/src/firebaseAuthManager/index.vue.d.ts +14 -0
  49. package/dist/src/firebaseAuthManager/metadata.d.ts +2 -0
  50. package/dist/src/firebaseAuthManager/pages/Overview.vue.d.ts +2 -0
  51. package/dist/src/firebaseAuthManager/pages/UserDetail.vue.d.ts +2 -0
  52. package/dist/src/firebaseAuthManager/permissions.d.ts +5 -0
  53. package/dist/src/firebaseAuthManager/routes.d.ts +5 -0
  54. package/dist/src/firebaseAuthManager/server.d.ts +162 -0
  55. package/dist/src/firebaseAuthManager/types.d.ts +84 -0
  56. package/dist/src/formBuilder/components/FormPreviewDialog.vue.d.ts +12 -0
  57. package/dist/src/formBuilder/components/FormStatusBadge.vue.d.ts +9 -0
  58. package/dist/src/formBuilder/config.d.ts +31 -0
  59. package/dist/src/formBuilder/index.d.ts +44 -0
  60. package/dist/src/formBuilder/index.vue.d.ts +14 -0
  61. package/dist/src/formBuilder/lib/forms.d.ts +11 -0
  62. package/dist/src/formBuilder/metadata.d.ts +2 -0
  63. package/dist/src/formBuilder/pages/Editor.vue.d.ts +2 -0
  64. package/dist/src/formBuilder/pages/Overview.vue.d.ts +2 -0
  65. package/dist/src/formBuilder/permissions.d.ts +5 -0
  66. package/dist/src/formBuilder/routes.d.ts +5 -0
  67. package/dist/src/formBuilder/server.d.ts +87 -0
  68. package/dist/src/formBuilder/tools.d.ts +1 -0
  69. package/dist/src/formBuilder/types.d.ts +46 -0
  70. package/dist/src/helpbot/composables/useHelpbotApi.d.ts +18 -0
  71. package/dist/src/helpbot/config.d.ts +17 -0
  72. package/dist/src/helpbot/index.d.ts +29 -0
  73. package/dist/src/helpbot/index.vue.d.ts +2 -0
  74. package/dist/src/helpbot/metadata.d.ts +2 -0
  75. package/dist/src/helpbot/pages/Knowledge.vue.d.ts +4 -0
  76. package/dist/src/helpbot/pages/Overview.vue.d.ts +2 -0
  77. package/dist/src/helpbot/pages/Test.vue.d.ts +4 -0
  78. package/dist/src/helpbot/permissions.d.ts +5 -0
  79. package/dist/src/helpbot/routes.d.ts +5 -0
  80. package/dist/src/helpbot/types.d.ts +42 -0
  81. package/dist/src/index.d.ts +3 -0
  82. package/dist/src/server-handlers.d.ts +2 -0
  83. package/dist/types-9N-DKxNj.mjs +250 -0
  84. package/dist/types-BMraG1kN.js +1 -0
  85. package/dist/types-Cem0vPo_.js +1 -0
  86. package/dist/types-ibC3-e1N.mjs +2630 -0
  87. package/dist/useHelpbotApi-BIIungOh.js +1 -0
  88. package/dist/useHelpbotApi-HC9JSiSn.mjs +229 -0
  89. package/dist/vee-validate-zod-BQElPD0m.js +1 -0
  90. package/dist/vee-validate-zod-CN16K2x9.mjs +1780 -0
  91. package/package.json +2 -2
  92. package/src/formBuilder/tools.ts +1 -0
  93. package/dist/Detail-BCUUNWvp.js +0 -1
  94. package/dist/Detail-DGg_xXZc.js +0 -1
  95. package/dist/Detail-Sc2qZdxj.js +0 -1
  96. package/dist/TableView-BkwoKREo.js +0 -4
  97. package/dist/vee-validate-zod-SjDT8X35.mjs +0 -4404
  98. package/dist/vee-validate-zod-VCmLnrtQ.js +0 -1
@@ -1,400 +1,401 @@
1
- import { createRouter as E, defineEventHandler as h, createError as p, getRouterParam as F, getQuery as I, readBody as O } from "h3";
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";
2
2
  import "vue";
3
- function z(A) {
4
- const { initFirebase: P, normalizeTimestamps: S } = A, f = E();
5
- async function u(l) {
6
- const { supabase: y, instanceId: D } = l.context.module, { data: t, error: c } = await y.from("project_modules").select("config").eq("id", D).single();
7
- if (c || !t?.config)
8
- throw p({ statusCode: 500, statusMessage: "Failed to load module config." });
9
- const i = t.config, s = i.project, a = i.productCollection || "products";
10
- if (!s)
11
- throw p({ statusCode: 400, statusMessage: "Products module has no Firebase integration configured." });
12
- return { firebase: await P(l, s), collection: a };
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";
11
+ if (!l)
12
+ throw y({ statusCode: 400, statusMessage: "Products module has no Firebase integration configured." });
13
+ return { firebase: await t(a, l), collection: f };
13
14
  }
14
- return f.get("/products", h(async (l) => {
15
+ return i.get("/products", A(async (a) => {
15
16
  try {
16
- const { firebase: y, collection: D } = await u(l);
17
- return (await y.firestore().collection(D).get()).docs.map((c) => S({
18
- id: c.id,
19
- ...c.data()
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()
20
21
  }));
21
- } catch (y) {
22
- throw console.error("Products handler — list error:", y), p({
23
- statusCode: y.statusCode || 500,
24
- statusMessage: y.statusMessage || "Failed to list products"
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"
25
26
  });
26
27
  }
27
- })), f.get("/products/:productId", h(async (l) => {
28
- const y = F(l, "productId");
29
- if (!y)
30
- throw p({ statusCode: 400, statusMessage: "Product ID is required." });
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." });
31
32
  try {
32
- const { firebase: D, collection: t } = await u(l), c = await D.firestore().collection(t).doc(y).get();
33
- if (!c.exists)
34
- throw p({ statusCode: 404, statusMessage: "Product not found." });
35
- return S({
36
- id: c.id,
37
- ...c.data()
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." });
36
+ return s({
37
+ id: u.id,
38
+ ...u.data()
38
39
  });
39
- } catch (D) {
40
- throw console.error("Products handler — get error:", D), p({
41
- statusCode: D.statusCode || 500,
42
- statusMessage: D.statusMessage || "Failed to get product"
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"
43
44
  });
44
45
  }
45
- })), f.get("/empty-stock", h(async (l) => {
46
- const D = I(l).category;
46
+ })), i.get("/empty-stock", A(async (a) => {
47
+ const c = R(a).category;
47
48
  try {
48
- const { firebase: t, collection: c } = await u(l);
49
- let i = t.firestore().collection(c).where("stock", "==", 0);
50
- D && (i = i.where("collections", "array-contains", D));
51
- const a = (await i.get()).docs.map((r) => S({
52
- id: r.id,
53
- ...r.data()
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()
54
55
  }));
55
56
  return {
56
- count: a.length,
57
- products: a.map((r) => ({
58
- id: r.id,
59
- title: r.title,
60
- slug: r.slug,
61
- stock: r.stock,
62
- price: r.price,
63
- currency: r.currency,
64
- status: r.status
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
65
66
  }))
66
67
  };
67
- } catch (t) {
68
- throw console.error("Products handler — empty-stock error:", t), p({
69
- statusCode: t.statusCode || 500,
70
- statusMessage: t.statusMessage || "Failed to query empty stock"
68
+ } catch (o) {
69
+ throw console.error("Products handler — empty-stock error:", o), y({
70
+ statusCode: o.statusCode || 500,
71
+ statusMessage: o.statusMessage || "Failed to query empty stock"
71
72
  });
72
73
  }
73
- })), f.handler;
74
- }
75
- function J(A) {
76
- const { initFirebase: P, normalizeTimestamps: S, deleteField: f } = A, u = E(), l = "privateSettings", y = "refundFlow", D = "metadataSchema";
77
- async function t(e) {
78
- const { supabase: n, instanceId: o } = e.context.module, { data: d, error: g } = await n.from("project_modules").select("config").eq("id", o).single();
79
- if (g || !d?.config)
80
- throw p({ statusCode: 500, statusMessage: "Failed to load module config." });
81
- const m = d.config, w = m.project, C = m.reservationsCollection || "bookings_orders", R = m.agendaCollection || "agendas";
82
- if (!w)
83
- throw p({ statusCode: 400, statusMessage: "Appointments module has no Firebase integration configured." });
84
- return { firebase: await P(e, w), reservationsCollection: C, agendaCollection: R };
74
+ })), i.handler;
75
+ }
76
+ function Qt(e) {
77
+ const { initFirebase: t, normalizeTimestamps: s, deleteField: i } = e, r = se(), a = "privateSettings", n = "refundFlow", c = "metadataSchema";
78
+ 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();
80
+ 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 };
85
86
  }
86
- function c(e) {
87
- return (e.reservations || []).map((o) => ({
88
- orderId: e.id,
89
- reservationId: o.id,
90
- customerInfo: e.customerInfo,
91
- date: o.date,
92
- startTime: o.timeslot?.startTime,
93
- endTime: o.timeslot?.endTime,
94
- spots: o.spots,
95
- status: e.status,
96
- reservationStatus: o.status,
97
- resourceId: o.resourceId,
98
- reservationPrice: o.totalPrice,
99
- reservationBasePrice: o.basePrice,
100
- reservationAddOnsPrice: o.addOnsPrice,
101
- pricingOption: o.pricingOption,
102
- amountDue: e.amountDue,
103
- amountPaid: e.amountPaid,
104
- createdAt: e.createdAt,
105
- metadata: e.metadata || {},
106
- reservationMetadata: o.metadata || {}
87
+ function u(m) {
88
+ return (m.reservations || []).map((p) => ({
89
+ orderId: m.id,
90
+ reservationId: p.id,
91
+ customerInfo: m.customerInfo,
92
+ date: p.date,
93
+ startTime: p.timeslot?.startTime,
94
+ endTime: p.timeslot?.endTime,
95
+ spots: p.spots,
96
+ 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,
103
+ amountDue: m.amountDue,
104
+ amountPaid: m.amountPaid,
105
+ createdAt: m.createdAt,
106
+ metadata: m.metadata || {},
107
+ reservationMetadata: p.metadata || {}
107
108
  }));
108
109
  }
109
- function i(e) {
110
+ function d(m) {
110
111
  return {
111
- showAmount: e?.showAmount !== !1,
112
- fields: Array.isArray(e?.fields) ? e.fields : []
112
+ showAmount: m?.showAmount !== !1,
113
+ fields: Array.isArray(m?.fields) ? m.fields : []
113
114
  };
114
115
  }
115
- function s() {
116
- return f ? {
117
- refundFlow: f(),
118
- refundFlowEnabled: f(),
119
- refundDialog: f()
116
+ function l() {
117
+ return i ? {
118
+ refundFlow: i(),
119
+ refundFlowEnabled: i(),
120
+ refundDialog: i()
120
121
  } : {
121
122
  refundFlow: null,
122
123
  refundFlowEnabled: null,
123
124
  refundDialog: null
124
125
  };
125
126
  }
126
- function a(e) {
127
- return Array.isArray(e) ? e : [];
127
+ function f(m) {
128
+ return Array.isArray(m) ? m : [];
128
129
  }
129
- function r() {
130
- return f ? {
131
- metadataSchema: f()
130
+ function g() {
131
+ return i ? {
132
+ metadataSchema: i()
132
133
  } : {
133
134
  metadataSchema: null
134
135
  };
135
136
  }
136
- return u.get("/agendas", h(async (e) => {
137
+ return r.get("/agendas", A(async (m) => {
137
138
  try {
138
- const { firebase: n, agendaCollection: o } = await t(e), g = (await n.firestore().collection(o).get()).docs.map((m) => {
139
- const w = m.data();
139
+ const { firebase: h, agendaCollection: p } = await o(m), C = (await h.firestore().collection(p).get()).docs.map((b) => {
140
+ const D = b.data();
140
141
  return {
141
- id: m.id,
142
- serviceName: w.serviceName || "",
143
- type: w.type || "regular"
142
+ id: b.id,
143
+ serviceName: D.serviceName || "",
144
+ type: D.type || "regular"
144
145
  };
145
146
  });
146
147
  return {
147
- count: g.length,
148
- agendas: g
148
+ count: C.length,
149
+ agendas: C
149
150
  };
150
- } catch (n) {
151
- throw console.error("Appointments handler — list agendas error:", n), p({
152
- statusCode: n.statusCode || 500,
153
- statusMessage: n.statusMessage || "Failed to list agendas"
151
+ } catch (h) {
152
+ throw console.error("Appointments handler — list agendas error:", h), y({
153
+ statusCode: h.statusCode || 500,
154
+ statusMessage: h.statusMessage || "Failed to list agendas"
154
155
  });
155
156
  }
156
- })), u.get("/agendas/:agendaId/opening-hours", h(async (e) => {
157
- const n = F(e, "agendaId"), d = I(e).date;
158
- if (!n)
159
- throw p({ statusCode: 400, statusMessage: "Agenda ID is required." });
160
- if (!d)
161
- throw p({ statusCode: 400, statusMessage: "Date is required (YYYY-MM-DD)." });
157
+ })), r.get("/agendas/:agendaId/opening-hours", A(async (m) => {
158
+ const h = N(m, "agendaId"), w = R(m).date;
159
+ if (!h)
160
+ throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
161
+ if (!w)
162
+ throw y({ statusCode: 400, statusMessage: "Date is required (YYYY-MM-DD)." });
162
163
  try {
163
- const { firebase: g, agendaCollection: m } = await t(e), w = await g.firestore().collection(m).doc(n).get();
164
- if (!w.exists)
165
- throw p({ statusCode: 404, statusMessage: "Agenda not found." });
166
- const C = w.data(), R = (C.resources || []).filter((v) => v.isActive), M = C.exceptions || [], q = (/* @__PURE__ */ new Date(d + "T00:00:00")).getDay(), N = R.map((v) => {
167
- const V = v.openingHours?.[q] || [], U = M.find((T) => {
168
- const G = d >= T.startDate && d <= T.endDate, j = !T.resourceIds || T.resourceIds.length === 0 || T.resourceIds.includes(v.id);
169
- return G && j;
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;
170
171
  });
171
- return U ? {
172
- resourceId: v.id,
173
- resourceName: v.name,
174
- date: d,
175
- dayOfWeek: q,
176
- isClosed: U.isClosed,
177
- hours: U.isClosed ? [] : (U.timeslots || []).map((T) => ({
178
- start: T.startTime,
179
- end: T.endTime
172
+ return de ? {
173
+ resourceId: $.id,
174
+ resourceName: $.name,
175
+ 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
180
181
  })),
181
182
  isException: !0
182
183
  } : {
183
- resourceId: v.id,
184
- resourceName: v.name,
185
- date: d,
186
- dayOfWeek: q,
187
- isClosed: V.length === 0,
188
- hours: V,
184
+ resourceId: $.id,
185
+ resourceName: $.name,
186
+ date: w,
187
+ dayOfWeek: j,
188
+ isClosed: Ae.length === 0,
189
+ hours: Ae,
189
190
  isException: !1
190
191
  };
191
192
  });
192
193
  return {
193
- agendaId: n,
194
- serviceName: C.serviceName || "",
195
- date: d,
196
- resources: N
194
+ agendaId: h,
195
+ serviceName: F.serviceName || "",
196
+ date: w,
197
+ resources: ce
197
198
  };
198
- } catch (g) {
199
- throw console.error("Appointments handler — opening hours error:", g), p({
200
- statusCode: g.statusCode || 500,
201
- statusMessage: g.statusMessage || "Failed to get opening hours"
199
+ } catch (C) {
200
+ throw console.error("Appointments handler — opening hours error:", C), y({
201
+ statusCode: C.statusCode || 500,
202
+ statusMessage: C.statusMessage || "Failed to get opening hours"
202
203
  });
203
204
  }
204
- })), u.get("/agendas/:agendaId/refund-flow", h(async (e) => {
205
- const n = F(e, "agendaId");
206
- if (!n)
207
- throw p({ statusCode: 400, statusMessage: "Agenda ID is required." });
205
+ })), r.get("/agendas/:agendaId/refund-flow", A(async (m) => {
206
+ const h = N(m, "agendaId");
207
+ if (!h)
208
+ throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
208
209
  try {
209
- const { firebase: o, agendaCollection: d } = await t(e), m = o.firestore().collection(d).doc(n), w = m.collection(l).doc(y), [C, R] = await Promise.all([
210
- m.get(),
211
- w.get()
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()
212
213
  ]);
213
- if (!C.exists)
214
- throw p({ statusCode: 404, statusMessage: "Agenda not found." });
215
- const M = R.exists ? R.data() || {} : {};
214
+ if (!F.exists)
215
+ throw y({ statusCode: 404, statusMessage: "Agenda not found." });
216
+ const S = M.exists ? M.data() || {} : {};
216
217
  return {
217
- refundFlow: M.flow || {},
218
- refundFlowEnabled: M.enabled !== !1,
219
- refundDialog: i(M.dialog)
218
+ refundFlow: S.flow || {},
219
+ refundFlowEnabled: S.enabled !== !1,
220
+ refundDialog: d(S.dialog)
220
221
  };
221
- } catch (o) {
222
- throw console.error("Appointments handler — refund flow load error:", o), p({
223
- statusCode: o.statusCode || 500,
224
- statusMessage: o.statusMessage || "Failed to load refund flow"
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"
225
226
  });
226
227
  }
227
- })), u.patch("/agendas/:agendaId/refund-flow", h(async (e) => {
228
- const n = F(e, "agendaId");
229
- if (!n)
230
- throw p({ statusCode: 400, statusMessage: "Agenda ID is required." });
228
+ })), r.patch("/agendas/:agendaId/refund-flow", A(async (m) => {
229
+ const h = N(m, "agendaId");
230
+ if (!h)
231
+ throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
231
232
  try {
232
- const o = await O(e), { firebase: d, agendaCollection: g } = await t(e), m = d.firestore(), w = m.collection(g).doc(n), C = w.collection(l).doc(y), R = i(o?.refundDialog);
233
- if (!(await w.get()).exists)
234
- throw p({ statusCode: 404, statusMessage: "Agenda not found." });
235
- const k = m.batch();
236
- return k.set(C, {
237
- flow: o?.refundFlow || {},
238
- enabled: o?.refundFlowEnabled !== !1,
239
- dialog: R,
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,
240
241
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
241
- }, { merge: !0 }), k.set(w, s(), { merge: !0 }), await k.commit(), { success: !0 };
242
- } catch (o) {
243
- throw console.error("Appointments handler — refund flow save error:", o), p({
244
- statusCode: o.statusCode || 500,
245
- statusMessage: o.statusMessage || "Failed to save refund flow"
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"
246
247
  });
247
248
  }
248
- })), u.get("/agendas/:agendaId/metadata-schema", h(async (e) => {
249
- const n = F(e, "agendaId");
250
- if (!n)
251
- throw p({ statusCode: 400, statusMessage: "Agenda ID is required." });
249
+ })), r.get("/agendas/:agendaId/metadata-schema", A(async (m) => {
250
+ const h = N(m, "agendaId");
251
+ if (!h)
252
+ throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
252
253
  try {
253
- const { firebase: o, agendaCollection: d } = await t(e), m = o.firestore().collection(d).doc(n), w = m.collection(l).doc(D), [C, R] = await Promise.all([
254
- m.get(),
255
- w.get()
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()
256
257
  ]);
257
- if (!C.exists)
258
- throw p({ statusCode: 404, statusMessage: "Agenda not found." });
259
- const M = R.exists ? R.data() || {} : {};
258
+ if (!F.exists)
259
+ throw y({ statusCode: 404, statusMessage: "Agenda not found." });
260
+ const S = M.exists ? M.data() || {} : {};
260
261
  return {
261
- metadataSchema: a(M.schema)
262
+ metadataSchema: f(S.schema)
262
263
  };
263
- } catch (o) {
264
- throw console.error("Appointments handler — metadata schema load error:", o), p({
265
- statusCode: o.statusCode || 500,
266
- statusMessage: o.statusMessage || "Failed to load metadata schema"
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"
267
268
  });
268
269
  }
269
- })), u.patch("/agendas/:agendaId/metadata-schema", h(async (e) => {
270
- const n = F(e, "agendaId");
271
- if (!n)
272
- throw p({ statusCode: 400, statusMessage: "Agenda ID is required." });
270
+ })), r.patch("/agendas/:agendaId/metadata-schema", A(async (m) => {
271
+ const h = N(m, "agendaId");
272
+ if (!h)
273
+ throw y({ statusCode: 400, statusMessage: "Agenda ID is required." });
273
274
  try {
274
- const o = await O(e), { firebase: d, agendaCollection: g } = await t(e), m = d.firestore(), w = m.collection(g).doc(n), C = w.collection(l).doc(D);
275
- if (!(await w.get()).exists)
276
- throw p({ statusCode: 404, statusMessage: "Agenda not found." });
277
- const M = m.batch();
278
- return M.set(C, {
279
- schema: a(o?.metadataSchema),
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),
280
281
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
281
- }, { merge: !0 }), M.set(w, r(), { merge: !0 }), await M.commit(), { success: !0 };
282
- } catch (o) {
283
- throw console.error("Appointments handler — metadata schema save error:", o), p({
284
- statusCode: o.statusCode || 500,
285
- statusMessage: o.statusMessage || "Failed to save metadata schema"
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"
286
287
  });
287
288
  }
288
- })), u.get("/appointments", h(async (e) => {
289
- const n = I(e), o = Math.min(Number(n.quantity) || 20, 100), d = n.status || "confirmed";
289
+ })), r.get("/appointments", A(async (m) => {
290
+ const h = R(m), p = Math.min(Number(h.quantity) || 20, 100), w = h.status || "confirmed";
290
291
  try {
291
- const { firebase: g, reservationsCollection: m } = await t(e), C = (await g.firestore().collection(m).orderBy("createdAt", "desc").where("status", "==", d).limit(o).get()).docs.flatMap(
292
- (R) => c(S({ id: R.id, ...R.data() }))
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() }))
293
294
  );
294
295
  return {
295
- count: C.length,
296
- appointments: C
296
+ count: F.length,
297
+ appointments: F
297
298
  };
298
- } catch (g) {
299
- throw console.error("Appointments handler — list error:", g), p({
300
- statusCode: g.statusCode || 500,
301
- statusMessage: g.statusMessage || "Failed to list appointments"
299
+ } catch (C) {
300
+ throw console.error("Appointments handler — list error:", C), y({
301
+ statusCode: C.statusCode || 500,
302
+ statusMessage: C.statusMessage || "Failed to list appointments"
302
303
  });
303
304
  }
304
- })), u.get("/appointments/find", h(async (e) => {
305
- const n = I(e), o = (n.name || "").toLowerCase().trim(), d = (n.email || "").toLowerCase().trim(), g = n.date;
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;
306
307
  try {
307
- const { firebase: m, reservationsCollection: w } = await t(e);
308
- let C = m.firestore().collection(w);
309
- d && (C = C.where("customerInfo.email", "==", d));
310
- let M = (await C.orderBy("createdAt", "desc").limit(200).get()).docs.flatMap(
311
- (k) => c(S({ id: k.id, ...k.data() }))
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() }))
312
313
  );
313
- return g && (M = M.filter((k) => k.date === g)), o && (M = M.filter((k) => {
314
- const q = (k.customerInfo?.firstName || "").toLowerCase(), N = (k.customerInfo?.lastName || "").toLowerCase();
315
- return q.includes(o) || N.includes(o) || `${q} ${N}`.includes(o);
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);
316
317
  })), {
317
- count: M.length,
318
- appointments: M
318
+ count: S.length,
319
+ appointments: S
319
320
  };
320
- } catch (m) {
321
- throw console.error("Appointments handler — find error:", m), p({
322
- statusCode: m.statusCode || 500,
323
- statusMessage: m.statusMessage || "Failed to find appointments"
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"
324
325
  });
325
326
  }
326
- })), u.get("/appointments/:appointmentId", h(async (e) => {
327
- const n = F(e, "appointmentId");
328
- if (!n)
329
- throw p({ statusCode: 400, statusMessage: "Appointment ID is required." });
327
+ })), r.get("/appointments/:appointmentId", A(async (m) => {
328
+ const h = N(m, "appointmentId");
329
+ if (!h)
330
+ throw y({ statusCode: 400, statusMessage: "Appointment ID is required." });
330
331
  try {
331
- const { firebase: o, reservationsCollection: d } = await t(e), g = await o.firestore().collection(d).doc(n).get();
332
- if (!g.exists)
333
- throw p({ statusCode: 404, statusMessage: "Appointment not found." });
334
- const m = S({ id: g.id, ...g.data() });
332
+ const { firebase: p, reservationsCollection: w } = await o(m), C = await p.firestore().collection(w).doc(h).get();
333
+ if (!C.exists)
334
+ throw y({ statusCode: 404, statusMessage: "Appointment not found." });
335
+ const b = s({ id: C.id, ...C.data() });
335
336
  return {
336
- ...m,
337
- reservations: c(m)
337
+ ...b,
338
+ reservations: u(b)
338
339
  };
339
- } catch (o) {
340
- throw console.error("Appointments handler — get error:", o), p({
341
- statusCode: o.statusCode || 500,
342
- statusMessage: o.statusMessage || "Failed to get appointment"
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"
343
344
  });
344
345
  }
345
- })), u.handler;
346
+ })), r.handler;
346
347
  }
347
- const x = "https://analyticsdata.googleapis.com/v1beta", H = [
348
+ const De = "https://analyticsdata.googleapis.com/v1beta", We = [
348
349
  "https://www.googleapis.com/auth/analytics.readonly",
349
350
  "https://www.googleapis.com/auth/webmasters.readonly"
350
- ], B = "https://searchconsole.googleapis.com/webmasters/v3";
351
- function W(A) {
352
- const { decrypt: P, getGoogleAccessToken: S } = A, f = E();
353
- async function u(t) {
354
- const { supabase: c, instanceId: i } = t.context.module, { data: s, error: a } = await c.from("project_modules").select("config").eq("id", i).single();
355
- if (a || !s?.config)
356
- throw p({ statusCode: 500, statusMessage: "Failed to load module config." });
357
- const r = s.config, e = r.propertyId, n = r.serviceAccount, o = r.siteUrl || "";
358
- if (!n)
359
- throw p({ statusCode: 400, statusMessage: "No Google Service Account configured for this module." });
360
- if (!e)
361
- throw p({ statusCode: 400, statusMessage: "No GA4 Property ID configured for this module." });
362
- const { data: d, error: g } = await c.from("integrations").select("config").eq("id", n).single();
363
- let m = d?.config;
364
- if (g || !m) {
365
- const { data: k, error: q } = await c.from("agency_integrations").select("config").eq("id", n).single();
366
- if (q || !k?.config)
367
- throw p({ statusCode: 500, statusMessage: "Failed to load Google Service Account credentials." });
368
- m = k.config;
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();
356
+ 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 || "";
359
+ if (!h)
360
+ throw y({ statusCode: 400, statusMessage: "No Google Service Account configured for this module." });
361
+ 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;
369
370
  }
370
- const w = P(m.clientEmail), C = P(m.privateKey), R = P(m.projectId);
371
- return { accessToken: await S(
372
- { clientEmail: w, privateKey: C, projectId: R },
373
- H
374
- ), propertyId: e, siteUrl: o };
371
+ const D = t(b.clientEmail), F = t(b.privateKey), M = t(b.projectId);
372
+ return { accessToken: await s(
373
+ { clientEmail: D, privateKey: F, projectId: M },
374
+ We
375
+ ), propertyId: m, siteUrl: p };
375
376
  }
376
- async function l(t, c, i) {
377
- const s = await fetch(`${x}/properties/${c}:runReport`, {
377
+ async function a(o, u, d) {
378
+ const l = await fetch(`${De}/properties/${u}:runReport`, {
378
379
  method: "POST",
379
380
  headers: {
380
- Authorization: `Bearer ${t}`,
381
+ Authorization: `Bearer ${o}`,
381
382
  "Content-Type": "application/json"
382
383
  },
383
- body: JSON.stringify(i)
384
+ body: JSON.stringify(d)
384
385
  });
385
- if (!s.ok) {
386
- const a = await s.json().catch(() => ({}));
387
- throw console.error("GA4 runReport failed:", a), p({
388
- statusCode: s.status,
389
- statusMessage: a?.error?.message || "GA4 API request failed"
386
+ if (!l.ok) {
387
+ const f = await l.json().catch(() => ({}));
388
+ throw console.error("GA4 runReport failed:", f), y({
389
+ statusCode: l.status,
390
+ statusMessage: f?.error?.message || "GA4 API request failed"
390
391
  });
391
392
  }
392
- return s.json();
393
+ return l.json();
393
394
  }
394
- f.get(
395
+ i.get(
395
396
  "/report",
396
- h(async (t) => {
397
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = a.match(/^(\d+)daysAgo$/), n = e ? parseInt(e[1], 10) : 30, o = `${n * 2}daysAgo`, d = `${n + 1}daysAgo`, g = [
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 = [
398
399
  { name: "sessions" },
399
400
  { name: "totalUsers" },
400
401
  { name: "screenPageViews" },
@@ -405,38 +406,38 @@ function W(A) {
405
406
  { name: "sessionsPerUser" },
406
407
  { name: "screenPageViewsPerSession" }
407
408
  ];
408
- let m, w = !0;
409
+ let b, D = !0;
409
410
  try {
410
- m = await l(c, i, {
411
+ b = await a(u, d, {
411
412
  dateRanges: [
412
- { startDate: a, endDate: r, name: "current" },
413
- { startDate: o, endDate: d, name: "previous" }
413
+ { startDate: f, endDate: g, name: "current" },
414
+ { startDate: p, endDate: w, name: "previous" }
414
415
  ],
415
416
  dimensions: [{ name: "date" }],
416
- metrics: g,
417
+ metrics: C,
417
418
  metricAggregations: ["TOTAL"],
418
419
  orderBys: [{ dimension: { dimensionName: "date" } }]
419
420
  });
420
421
  } catch {
421
- w = !1, m = await l(c, i, {
422
- dateRanges: [{ startDate: a, endDate: r }],
422
+ D = !1, b = await a(u, d, {
423
+ dateRanges: [{ startDate: f, endDate: g }],
423
424
  dimensions: [{ name: "date" }],
424
- metrics: g,
425
+ metrics: C,
425
426
  metricAggregations: ["TOTAL"],
426
427
  orderBys: [{ dimension: { dimensionName: "date" } }]
427
428
  });
428
429
  }
429
- return L(m, w);
430
+ return et(b, D);
430
431
  })
431
- ), f.get(
432
+ ), i.get(
432
433
  "/realtime",
433
- h(async (t) => {
434
- const { accessToken: c, propertyId: i } = await u(t), s = await fetch(
435
- `${x}/properties/${i}:runRealtimeReport`,
434
+ A(async (o) => {
435
+ const { accessToken: u, propertyId: d } = await r(o), l = await fetch(
436
+ `${De}/properties/${d}:runRealtimeReport`,
436
437
  {
437
438
  method: "POST",
438
439
  headers: {
439
- Authorization: `Bearer ${c}`,
440
+ Authorization: `Bearer ${u}`,
440
441
  "Content-Type": "application/json"
441
442
  },
442
443
  body: JSON.stringify({
@@ -447,24 +448,24 @@ function W(A) {
447
448
  })
448
449
  }
449
450
  );
450
- if (!s.ok) {
451
- const n = await s.json().catch(() => ({}));
452
- throw p({ statusCode: s.status, statusMessage: n?.error?.message || "Realtime API failed" });
451
+ if (!l.ok) {
452
+ const h = await l.json().catch(() => ({}));
453
+ throw y({ statusCode: l.status, statusMessage: h?.error?.message || "Realtime API failed" });
453
454
  }
454
- const a = await s.json(), r = (a?.rows || []).reduce(
455
- (n, o) => n + parseInt(o.metricValues?.[0]?.value || "0", 10),
455
+ const f = await l.json(), g = (f?.rows || []).reduce(
456
+ (h, p) => h + parseInt(p.metricValues?.[0]?.value || "0", 10),
456
457
  0
457
- ), e = (a?.rows || []).map((n) => ({
458
- page: n.dimensionValues?.[0]?.value || "(not set)",
459
- activeUsers: parseInt(n.metricValues?.[0]?.value || "0", 10)
458
+ ), m = (f?.rows || []).map((h) => ({
459
+ page: h.dimensionValues?.[0]?.value || "(not set)",
460
+ activeUsers: parseInt(h.metricValues?.[0]?.value || "0", 10)
460
461
  }));
461
- return { activeUsers: r, activePages: e };
462
+ return { activeUsers: g, activePages: m };
462
463
  })
463
- ), f.get(
464
+ ), i.get(
464
465
  "/top-pages",
465
- h(async (t) => {
466
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = parseInt(s.limit || "10", 10), n = await l(c, i, {
467
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
468
469
  dimensions: [{ name: "pagePath" }],
469
470
  metrics: [
470
471
  { name: "screenPageViews" },
@@ -472,25 +473,25 @@ function W(A) {
472
473
  { name: "averageSessionDuration" }
473
474
  ],
474
475
  orderBys: [{ metric: { metricName: "screenPageViews" }, desc: !0 }],
475
- limit: e * 2
476
+ limit: m * 2
476
477
  // fetch extra to account for duplicates before aggregation
477
- }), o = b(n, "pagePath"), d = /* @__PURE__ */ new Map();
478
- for (const m of o.rows) {
479
- const w = m.pagePath.toLowerCase().replace(/\/+$/, ""), C = d.get(w);
480
- if (C) {
481
- C.screenPageViews += m.screenPageViews || 0, C.totalUsers += m.totalUsers || 0;
482
- const R = C.screenPageViews;
483
- R > 0 && (C.averageSessionDuration = (C.averageSessionDuration * (R - (m.screenPageViews || 0)) + (m.averageSessionDuration || 0) * (m.screenPageViews || 0)) / R);
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);
484
485
  } else
485
- d.set(w, { ...m });
486
+ w.set(D, { ...b });
486
487
  }
487
- return { rows: [...d.values()].sort((m, w) => (w.screenPageViews || 0) - (m.screenPageViews || 0)).slice(0, e), rowCount: o.rowCount };
488
+ return { rows: [...w.values()].sort((b, D) => (D.screenPageViews || 0) - (b.screenPageViews || 0)).slice(0, m), rowCount: p.rowCount };
488
489
  })
489
- ), f.get(
490
+ ), i.get(
490
491
  "/top-sources",
491
- h(async (t) => {
492
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
493
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
494
495
  dimensions: [{ name: "sessionSource" }],
495
496
  metrics: [
496
497
  { name: "sessions" },
@@ -499,13 +500,13 @@ function W(A) {
499
500
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
500
501
  limit: 10
501
502
  });
502
- return b(e, "sessionSource");
503
+ return P(m, "sessionSource");
503
504
  })
504
- ), f.get(
505
+ ), i.get(
505
506
  "/devices",
506
- h(async (t) => {
507
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
508
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
509
510
  dimensions: [{ name: "deviceCategory" }],
510
511
  metrics: [
511
512
  { name: "sessions" },
@@ -513,13 +514,13 @@ function W(A) {
513
514
  ],
514
515
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }]
515
516
  });
516
- return b(e, "deviceCategory");
517
+ return P(m, "deviceCategory");
517
518
  })
518
- ), f.get(
519
+ ), i.get(
519
520
  "/countries",
520
- h(async (t) => {
521
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
522
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
523
524
  dimensions: [{ name: "country" }],
524
525
  metrics: [
525
526
  { name: "sessions" },
@@ -528,13 +529,13 @@ function W(A) {
528
529
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
529
530
  limit: 10
530
531
  });
531
- return b(e, "country");
532
+ return P(m, "country");
532
533
  })
533
- ), f.get(
534
+ ), i.get(
534
535
  "/acquisition/channels",
535
- h(async (t) => {
536
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
537
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
538
539
  dimensions: [{ name: "sessionDefaultChannelGroup" }],
539
540
  metrics: [
540
541
  { name: "sessions" },
@@ -548,13 +549,13 @@ function W(A) {
548
549
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
549
550
  limit: 15
550
551
  });
551
- return b(e, "sessionDefaultChannelGroup");
552
+ return P(m, "sessionDefaultChannelGroup");
552
553
  })
553
- ), f.get(
554
+ ), i.get(
554
555
  "/acquisition/source-medium",
555
- h(async (t) => {
556
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
557
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
558
559
  dimensions: [{ name: "sessionSourceMedium" }],
559
560
  metrics: [
560
561
  { name: "sessions" },
@@ -567,13 +568,13 @@ function W(A) {
567
568
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
568
569
  limit: 20
569
570
  });
570
- return b(e, "sessionSourceMedium");
571
+ return P(m, "sessionSourceMedium");
571
572
  })
572
- ), f.get(
573
+ ), i.get(
573
574
  "/acquisition/referrals",
574
- h(async (t) => {
575
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
576
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
577
578
  dimensions: [{ name: "sessionSource" }],
578
579
  dimensionFilter: {
579
580
  filter: {
@@ -590,13 +591,13 @@ function W(A) {
590
591
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
591
592
  limit: 20
592
593
  });
593
- return b(e, "sessionSource");
594
+ return P(m, "sessionSource");
594
595
  })
595
- ), f.get(
596
+ ), i.get(
596
597
  "/acquisition/campaigns",
597
- h(async (t) => {
598
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
599
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
600
601
  dimensions: [{ name: "sessionCampaignName" }],
601
602
  dimensionFilter: {
602
603
  notExpression: {
@@ -615,13 +616,13 @@ function W(A) {
615
616
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
616
617
  limit: 20
617
618
  });
618
- return b(e, "sessionCampaignName");
619
+ return P(m, "sessionCampaignName");
619
620
  })
620
- ), f.get(
621
+ ), i.get(
621
622
  "/content/all-pages",
622
- h(async (t) => {
623
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = parseInt(s.limit || "50", 10), n = await l(c, i, {
624
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
625
626
  dimensions: [{ name: "pagePath" }],
626
627
  metrics: [
627
628
  { name: "screenPageViews" },
@@ -633,15 +634,15 @@ function W(A) {
633
634
  { name: "userEngagementDuration" }
634
635
  ],
635
636
  orderBys: [{ metric: { metricName: "screenPageViews" }, desc: !0 }],
636
- limit: e
637
+ limit: m
637
638
  });
638
- return b(n, "pagePath");
639
+ return P(h, "pagePath");
639
640
  })
640
- ), f.get(
641
+ ), i.get(
641
642
  "/content/landing-pages",
642
- h(async (t) => {
643
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
644
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
645
646
  dimensions: [{ name: "landingPagePlusQueryString" }],
646
647
  metrics: [
647
648
  { name: "sessions" },
@@ -654,13 +655,13 @@ function W(A) {
654
655
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
655
656
  limit: 30
656
657
  });
657
- return b(e, "landingPagePlusQueryString");
658
+ return P(m, "landingPagePlusQueryString");
658
659
  })
659
- ), f.get(
660
+ ), i.get(
660
661
  "/content/exit-pages",
661
- h(async (t) => {
662
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
663
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
664
665
  dimensions: [{ name: "pagePath" }],
665
666
  metrics: [
666
667
  { name: "sessions" },
@@ -670,60 +671,60 @@ function W(A) {
670
671
  ],
671
672
  orderBys: [{ metric: { metricName: "screenPageViews" }, desc: !0 }],
672
673
  limit: 20
673
- }), n = b(e, "pagePath");
674
- return n.rows = n.rows.map((o) => ({
675
- ...o,
676
- exitRate: o.bounceRate || 0
677
- })), n;
674
+ }), h = P(m, "pagePath");
675
+ return h.rows = h.rows.map((p) => ({
676
+ ...p,
677
+ exitRate: p.bounceRate || 0
678
+ })), h;
678
679
  })
679
- ), f.get(
680
+ ), i.get(
680
681
  "/content/search-terms",
681
- h(async (t) => {
682
- const { accessToken: c, propertyId: i, siteUrl: s } = await u(t), a = I(t), r = a.startDate || "30daysAgo", e = a.endDate || "today";
683
- if (s)
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";
684
+ if (l)
684
685
  try {
685
- const d = `${B}/sites/${encodeURIComponent(s)}/searchAnalytics/query`, g = await fetch(
686
- d,
686
+ const w = `${Fe}/sites/${encodeURIComponent(l)}/searchAnalytics/query`, C = await fetch(
687
+ w,
687
688
  {
688
689
  method: "POST",
689
690
  headers: {
690
- Authorization: `Bearer ${c}`,
691
+ Authorization: `Bearer ${u}`,
691
692
  "Content-Type": "application/json"
692
693
  },
693
694
  body: JSON.stringify({
694
- startDate: y(r),
695
- endDate: y(e),
695
+ startDate: n(g),
696
+ endDate: n(m),
696
697
  dimensions: ["query"],
697
698
  rowLimit: 30
698
699
  })
699
700
  }
700
701
  );
701
- if (g.ok) {
702
- const w = ((await g.json()).rows || []).map((C) => ({
703
- query: C.keys[0],
704
- clicks: C.clicks,
705
- impressions: C.impressions,
706
- ctr: C.ctr,
707
- position: C.position
702
+ 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
708
709
  }));
709
- if (w.length > 0)
710
+ if (D.length > 0)
710
711
  return {
711
- rows: w,
712
- rowCount: w.length,
712
+ rows: D,
713
+ rowCount: D.length,
713
714
  source: "search_console"
714
715
  };
715
716
  } else {
716
- const m = await g.text().catch(() => "");
717
- console.error(`[GA Module] Search Console API error (${g.status}):`, m);
717
+ const b = await C.text().catch(() => "");
718
+ console.error(`[GA Module] Search Console API error (${C.status}):`, b);
718
719
  }
719
- } catch (d) {
720
- console.error("[GA Module] Search Console request failed:", d?.message || d);
720
+ } catch (w) {
721
+ console.error("[GA Module] Search Console request failed:", w?.message || w);
721
722
  }
722
723
  else
723
724
  console.log("[GA Module] No siteUrl configured, skipping Search Console");
724
725
  try {
725
- const d = await l(c, i, {
726
- dateRanges: [{ startDate: r, endDate: e }],
726
+ const w = await a(u, d, {
727
+ dateRanges: [{ startDate: g, endDate: m }],
727
728
  dimensions: [{ name: "sessionGoogleAdsQuery" }],
728
729
  metrics: [
729
730
  { name: "sessions" },
@@ -754,13 +755,13 @@ function W(A) {
754
755
  },
755
756
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
756
757
  limit: 30
757
- }), g = b(d, "sessionGoogleAdsQuery");
758
- if (g.rows.length > 0)
759
- return { ...g, source: "google_ads" };
758
+ }), C = P(w, "sessionGoogleAdsQuery");
759
+ if (C.rows.length > 0)
760
+ return { ...C, source: "google_ads" };
760
761
  } catch {
761
762
  }
762
- const n = await l(c, i, {
763
- dateRanges: [{ startDate: r, endDate: e }],
763
+ const h = await a(u, d, {
764
+ dateRanges: [{ startDate: g, endDate: m }],
764
765
  dimensions: [{ name: "landingPagePlusQueryString" }],
765
766
  metrics: [
766
767
  { name: "sessions" },
@@ -793,13 +794,13 @@ function W(A) {
793
794
  orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
794
795
  limit: 30
795
796
  });
796
- return { ...b(n, "landingPagePlusQueryString"), source: "organic_landing_pages" };
797
+ return { ...P(h, "landingPagePlusQueryString"), source: "organic_landing_pages" };
797
798
  })
798
- ), f.get(
799
+ ), i.get(
799
800
  "/audience/overview",
800
- h(async (t) => {
801
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
802
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
803
804
  dimensions: [{ name: "newVsReturning" }],
804
805
  metrics: [
805
806
  { name: "totalUsers" },
@@ -810,14 +811,14 @@ function W(A) {
810
811
  ],
811
812
  metricAggregations: ["TOTAL"]
812
813
  });
813
- return b(e, "newVsReturning");
814
+ return P(m, "newVsReturning");
814
815
  })
815
- ), f.get(
816
+ ), i.get(
816
817
  "/audience/technology",
817
- h(async (t) => {
818
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = s.dimension || "browser", o = ["browser", "operatingSystem", "screenResolution"].includes(e) ? e : "browser", d = await l(c, i, {
819
- dateRanges: [{ startDate: a, endDate: r }],
820
- dimensions: [{ name: o }],
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 }],
821
822
  metrics: [
822
823
  { name: "totalUsers" },
823
824
  { name: "sessions" },
@@ -826,13 +827,13 @@ function W(A) {
826
827
  orderBys: [{ metric: { metricName: "totalUsers" }, desc: !0 }],
827
828
  limit: 10
828
829
  });
829
- return b(d, o);
830
+ return P(w, p);
830
831
  })
831
- ), f.get(
832
+ ), i.get(
832
833
  "/audience/languages",
833
- h(async (t) => {
834
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
835
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
836
837
  dimensions: [{ name: "language" }],
837
838
  metrics: [
838
839
  { name: "totalUsers" },
@@ -841,13 +842,13 @@ function W(A) {
841
842
  orderBys: [{ metric: { metricName: "totalUsers" }, desc: !0 }],
842
843
  limit: 15
843
844
  });
844
- return b(e, "language");
845
+ return P(m, "language");
845
846
  })
846
- ), f.get(
847
+ ), i.get(
847
848
  "/audience/hours",
848
- h(async (t) => {
849
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
850
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
851
852
  dimensions: [{ name: "dayOfWeekName" }, { name: "hour" }],
852
853
  metrics: [{ name: "sessions" }],
853
854
  orderBys: [
@@ -857,13 +858,13 @@ function W(A) {
857
858
  limit: 168
858
859
  // 7 days × 24 hours
859
860
  });
860
- return $(e, ["dayOfWeekName", "hour"]);
861
+ return Ie(m, ["dayOfWeekName", "hour"]);
861
862
  })
862
- ), f.get(
863
+ ), i.get(
863
864
  "/audience/cities",
864
- h(async (t) => {
865
- const { accessToken: c, propertyId: i } = await u(t), s = I(t), a = s.startDate || "30daysAgo", r = s.endDate || "today", e = await l(c, i, {
866
- dateRanges: [{ startDate: a, endDate: r }],
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 }],
867
868
  dimensions: [{ name: "city" }, { name: "country" }],
868
869
  metrics: [
869
870
  { name: "totalUsers" },
@@ -880,236 +881,1394 @@ function W(A) {
880
881
  orderBys: [{ metric: { metricName: "totalUsers" }, desc: !0 }],
881
882
  limit: 20
882
883
  });
883
- return $(e, ["city", "country"]);
884
+ return Ie(m, ["city", "country"]);
884
885
  })
885
886
  );
886
- function y(t) {
887
- const c = t.match(/^(\d+)daysAgo$/);
888
- if (c) {
889
- const i = /* @__PURE__ */ new Date();
890
- return i.setDate(i.getDate() - parseInt(c[1], 10)), i.toISOString().slice(0, 10);
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);
891
892
  }
892
- if (t === "today") return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
893
- if (t === "yesterday") {
894
- const i = /* @__PURE__ */ new Date();
895
- return i.setDate(i.getDate() - 1), i.toISOString().slice(0, 10);
893
+ if (o === "today") return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
894
+ if (o === "yesterday") {
895
+ const d = /* @__PURE__ */ new Date();
896
+ return d.setDate(d.getDate() - 1), d.toISOString().slice(0, 10);
896
897
  }
897
- return t;
898
+ return o;
898
899
  }
899
- async function D(t, c, i) {
900
- const s = `${B}/sites/${encodeURIComponent(c)}/searchAnalytics/query`, a = await fetch(s, {
900
+ async function c(o, u, d) {
901
+ const l = `${Fe}/sites/${encodeURIComponent(u)}/searchAnalytics/query`, f = await fetch(l, {
901
902
  method: "POST",
902
903
  headers: {
903
- Authorization: `Bearer ${t}`,
904
+ Authorization: `Bearer ${o}`,
904
905
  "Content-Type": "application/json"
905
906
  },
906
- body: JSON.stringify(i)
907
+ body: JSON.stringify(d)
907
908
  });
908
- if (!a.ok) {
909
- const r = await a.json().catch(() => ({}));
910
- throw p({
911
- statusCode: a.status,
912
- statusMessage: r?.error?.message || "Search Console API request failed"
909
+ if (!f.ok) {
910
+ const g = await f.json().catch(() => ({}));
911
+ throw y({
912
+ statusCode: f.status,
913
+ statusMessage: g?.error?.message || "Search Console API request failed"
913
914
  });
914
915
  }
915
- return a.json();
916
+ return f.json();
916
917
  }
917
- return f.get(
918
+ return i.get(
918
919
  "/seo/keywords",
919
- h(async (t) => {
920
- const { accessToken: c, siteUrl: i } = await u(t);
921
- if (!i)
922
- throw p({ statusCode: 400, statusMessage: "Search Console Site URL is not configured. Add it in module settings." });
923
- const s = I(t), a = y(s.startDate || "30daysAgo"), r = y(s.endDate || "today"), e = Math.min(parseInt(s.limit) || 50, 100), n = await D(c, i, {
924
- startDate: a,
925
- endDate: r,
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, {
925
+ startDate: f,
926
+ endDate: g,
926
927
  dimensions: ["query"],
927
- rowLimit: e
928
+ rowLimit: m
928
929
  });
929
930
  return {
930
- rows: (n.rows || []).map((o) => ({
931
- query: o.keys[0],
932
- clicks: o.clicks,
933
- impressions: o.impressions,
934
- ctr: o.ctr,
935
- position: o.position
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
936
937
  })),
937
- rowCount: n.rows?.length || 0
938
+ rowCount: h.rows?.length || 0
938
939
  };
939
940
  })
940
- ), f.get(
941
+ ), i.get(
941
942
  "/seo/pages",
942
- h(async (t) => {
943
- const { accessToken: c, siteUrl: i } = await u(t);
944
- if (!i)
945
- throw p({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
946
- const s = I(t), a = y(s.startDate || "30daysAgo"), r = y(s.endDate || "today"), e = Math.min(parseInt(s.limit) || 50, 100), n = await D(c, i, {
947
- startDate: a,
948
- endDate: r,
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, {
948
+ startDate: f,
949
+ endDate: g,
949
950
  dimensions: ["page"],
950
- rowLimit: e
951
+ rowLimit: m
951
952
  });
952
953
  return {
953
- rows: (n.rows || []).map((o) => ({
954
- page: o.keys[0],
955
- clicks: o.clicks,
956
- impressions: o.impressions,
957
- ctr: o.ctr,
958
- position: o.position
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
959
960
  })),
960
- rowCount: n.rows?.length || 0
961
+ rowCount: h.rows?.length || 0
961
962
  };
962
963
  })
963
- ), f.get(
964
+ ), i.get(
964
965
  "/seo/trends",
965
- h(async (t) => {
966
- const { accessToken: c, siteUrl: i } = await u(t);
967
- if (!i)
968
- throw p({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
969
- const s = I(t), a = y(s.startDate || "30daysAgo"), r = y(s.endDate || "today"), n = ((await D(c, i, {
970
- startDate: a,
971
- endDate: r,
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, {
971
+ startDate: f,
972
+ endDate: g,
972
973
  dimensions: ["date"],
973
974
  rowLimit: 500
974
- })).rows || []).map((d) => ({
975
- date: d.keys[0],
976
- clicks: d.clicks,
977
- impressions: d.impressions,
978
- ctr: d.ctr,
979
- position: d.position
980
- })).sort((d, g) => d.date.localeCompare(g.date)), o = n.reduce(
981
- (d, g) => ({
982
- clicks: d.clicks + g.clicks,
983
- impressions: d.impressions + g.impressions
975
+ })).rows || []).map((w) => ({
976
+ date: w.keys[0],
977
+ clicks: w.clicks,
978
+ impressions: w.impressions,
979
+ ctr: w.ctr,
980
+ position: w.position
981
+ })).sort((w, C) => w.date.localeCompare(C.date)), p = h.reduce(
982
+ (w, C) => ({
983
+ clicks: w.clicks + C.clicks,
984
+ impressions: w.impressions + C.impressions
984
985
  }),
985
986
  { clicks: 0, impressions: 0 }
986
987
  );
987
- return o.ctr = o.impressions > 0 ? o.clicks / o.impressions : 0, o.avgPosition = n.length > 0 ? n.reduce((d, g) => d + g.position, 0) / n.length : 0, { rows: n, totals: o, rowCount: n.length };
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 };
988
989
  })
989
- ), f.get(
990
+ ), i.get(
990
991
  "/seo/query-pages",
991
- h(async (t) => {
992
- const { accessToken: c, siteUrl: i } = await u(t);
993
- if (!i)
994
- throw p({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
995
- const s = I(t), a = y(s.startDate || "30daysAgo"), r = y(s.endDate || "today"), e = await D(c, i, {
996
- startDate: a,
997
- endDate: r,
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, {
997
+ startDate: f,
998
+ endDate: g,
998
999
  dimensions: ["query", "page"],
999
1000
  rowLimit: 100
1000
1001
  });
1001
1002
  return {
1002
- rows: (e.rows || []).map((n) => ({
1003
- query: n.keys[0],
1004
- page: n.keys[1],
1005
- clicks: n.clicks,
1006
- impressions: n.impressions,
1007
- ctr: n.ctr,
1008
- position: n.position
1003
+ rows: (m.rows || []).map((h) => ({
1004
+ query: h.keys[0],
1005
+ page: h.keys[1],
1006
+ clicks: h.clicks,
1007
+ impressions: h.impressions,
1008
+ ctr: h.ctr,
1009
+ position: h.position
1009
1010
  })),
1010
- rowCount: e.rows?.length || 0
1011
+ rowCount: m.rows?.length || 0
1011
1012
  };
1012
1013
  })
1013
- ), f.handler;
1014
- }
1015
- function L(A, P = !0) {
1016
- const S = (A.metricHeaders || []).map((a) => a.name), u = (A.dimensionHeaders || []).map((a) => a.name).indexOf("date"), l = [];
1017
- (A.rows || []).forEach((a) => {
1018
- const r = u >= 0 ? a.dimensionValues[u]?.value : a.dimensionValues[0]?.value;
1019
- if (!r || r.length < 8) return;
1020
- const n = { date: `${r.slice(0, 4)}-${r.slice(4, 6)}-${r.slice(6, 8)}` };
1021
- S.forEach((o, d) => {
1022
- n[o] = parseFloat(a.metricValues[d]?.value || "0");
1023
- }), l.push(n);
1014
+ ), i.handler;
1015
+ }
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 = [];
1018
+ (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");
1024
+ }), a.push(h);
1024
1025
  });
1025
- const y = {}, D = {};
1026
- A.totals && A.totals.length >= 2 ? S.forEach((a, r) => {
1027
- y[a] = parseFloat(A.totals[0]?.metricValues?.[r]?.value || "0"), D[a] = parseFloat(A.totals[1]?.metricValues?.[r]?.value || "0");
1028
- }) : A.totals && A.totals.length === 1 && S.forEach((a, r) => {
1029
- y[a] = parseFloat(A.totals[0]?.metricValues?.[r]?.value || "0");
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");
1030
1031
  });
1031
- const t = {};
1032
- S.forEach((a) => {
1033
- const r = y[a] || 0, e = D[a];
1034
- e !== void 0 && e !== 0 ? t[a] = (r - e) / e * 100 : t[a] = null;
1032
+ const o = {};
1033
+ 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;
1035
1036
  });
1036
- const c = /* @__PURE__ */ new Map();
1037
- for (const a of l)
1038
- c.has(a.date) || c.set(a.date, a);
1039
- const i = Array.from(c.values()).sort((a, r) => a.date.localeCompare(r.date)), s = P && A.totals && A.totals.length >= 2 ? i.slice(-Math.ceil(i.length / 2)) : i;
1037
+ const u = /* @__PURE__ */ new Map();
1038
+ 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;
1040
1041
  return {
1041
- rows: s,
1042
- totals: y,
1043
- previousTotals: D,
1044
- changes: t,
1045
- rowCount: s.length
1042
+ rows: l,
1043
+ totals: n,
1044
+ previousTotals: c,
1045
+ changes: o,
1046
+ rowCount: l.length
1046
1047
  };
1047
1048
  }
1048
- function b(A, P) {
1049
- const S = (A.metricHeaders || []).map((u) => u.name), f = (A.rows || []).map((u) => {
1050
- const l = {
1051
- [P]: u.dimensionValues[0].value
1049
+ function P(e, t) {
1050
+ const s = (e.metricHeaders || []).map((r) => r.name), i = (e.rows || []).map((r) => {
1051
+ const a = {
1052
+ [t]: r.dimensionValues[0].value
1052
1053
  };
1053
- return S.forEach((y, D) => {
1054
- l[y] = parseFloat(u.metricValues[D].value);
1055
- }), l;
1054
+ return s.forEach((n, c) => {
1055
+ a[n] = parseFloat(r.metricValues[c].value);
1056
+ }), a;
1056
1057
  });
1057
- return { rows: f, rowCount: A.rowCount || f.length };
1058
- }
1059
- function $(A, P) {
1060
- const S = (A.metricHeaders || []).map((u) => u.name), f = (A.rows || []).map((u) => {
1061
- const l = {};
1062
- return P.forEach((y, D) => {
1063
- l[y] = u.dimensionValues[D]?.value || "";
1064
- }), S.forEach((y, D) => {
1065
- l[y] = parseFloat(u.metricValues[D].value);
1066
- }), l;
1058
+ return { rows: i, rowCount: e.rowCount || i.length };
1059
+ }
1060
+ function Ie(e, t) {
1061
+ const s = (e.metricHeaders || []).map((r) => r.name), i = (e.rows || []).map((r) => {
1062
+ 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);
1067
+ }), a;
1067
1068
  });
1068
- return { rows: f, rowCount: A.rowCount || f.length };
1069
- }
1070
- function Y(A) {
1071
- const { decrypt: P } = A, S = E();
1072
- async function f(u) {
1073
- const { supabase: l, instanceId: y } = u.context.module, { data: D, error: t } = await l.from("project_modules").select("config").eq("id", y).single();
1074
- if (t || !D?.config)
1075
- throw p({ statusCode: 500, statusMessage: "Failed to load module config." });
1076
- const c = D.config, i = c.githubIntegration, s = c.githubRepo, a = c.githubOwner;
1077
- if (!i || !s || !a)
1078
- throw p({ statusCode: 400, statusMessage: "No GitHub integration configured for this module." });
1079
- const { data: r, error: e } = await l.from("integrations").select("config").eq("id", i).single();
1080
- let n = r?.config;
1081
- if (e || !n) {
1082
- const { data: d, error: g } = await l.from("agency_integrations").select("config").eq("id", i).single();
1083
- if (g || !d?.config)
1084
- throw p({ statusCode: 500, statusMessage: "Failed to load Github credentials." });
1085
- n = d.config;
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;
1082
+ if (m || !h) {
1083
+ const { data: w, error: C } = await a.from("agency_integrations").select("config").eq("id", d).single();
1084
+ if (C || !w?.config)
1085
+ throw y({ statusCode: 500, statusMessage: "Failed to load Github credentials." });
1086
+ h = w.config;
1086
1087
  }
1087
- return { token: P(n.token), repo: s, owner: a };
1088
+ return { token: t(h.token), repo: l, owner: f };
1088
1089
  }
1089
- return S.post(
1090
+ return s.post(
1090
1091
  "/github/deploy",
1091
- h(async (u) => {
1092
+ A(async (r) => {
1092
1093
  try {
1093
- const { token: l, repo: y, owner: D } = await f(u);
1094
- await fetch(`https://api.github.com/repos/${D}/${y}/dispatches`, {
1094
+ const { token: a, repo: n, owner: c } = await i(r);
1095
+ await fetch(`https://api.github.com/repos/${c}/${n}/dispatches`, {
1095
1096
  method: "POST",
1096
1097
  headers: {
1097
- Authorization: `Bearer ${l}`,
1098
+ Authorization: `Bearer ${a}`,
1098
1099
  Accept: "application/vnd.github+json"
1099
1100
  },
1100
1101
  body: JSON.stringify({
1101
1102
  event_type: "deploy-site"
1102
1103
  })
1103
1104
  });
1104
- } catch (l) {
1105
- throw console.error("Error triggering GitHub deployment:", l), p({ statusCode: 500, statusMessage: "Failed to trigger deployment." });
1105
+ } catch (a) {
1106
+ throw console.error("Error triggering GitHub deployment:", a), y({ statusCode: 500, statusMessage: "Failed to trigger deployment." });
1106
1107
  }
1107
1108
  })
1108
- ), S.handler;
1109
+ ), s.handler;
1110
+ }
1111
+ const Oe = "firebaseAuthManager", v = {
1112
+ viewUsers: "view-auth-users",
1113
+ viewPii: "view-auth-user-pii",
1114
+ createUsers: "create-auth-users",
1115
+ editUsers: "edit-auth-users",
1116
+ manageStatus: "manage-auth-status",
1117
+ manageSessions: "manage-auth-sessions",
1118
+ manageMfa: "manage-auth-mfa",
1119
+ manageRoles: "manage-auth-roles",
1120
+ manageProfiles: "manage-auth-profiles",
1121
+ deleteUsers: "delete-auth-users"
1122
+ }, Be = B().trim().email().max(254), he = B().min(1).max(128), tt = he.refine((e) => e === e.trim(), {
1123
+ 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"), {
1140
+ 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,
1151
+ // Deliberately do not trim this value: destructive confirmation must be an
1152
+ // 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([
1155
+ "acr",
1156
+ "amr",
1157
+ "at_hash",
1158
+ "aud",
1159
+ "auth_time",
1160
+ "azp",
1161
+ "cnf",
1162
+ "c_hash",
1163
+ "email",
1164
+ "email_verified",
1165
+ "exp",
1166
+ "firebase",
1167
+ "iat",
1168
+ "iss",
1169
+ "jti",
1170
+ "name",
1171
+ "nbf",
1172
+ "nonce",
1173
+ "phone_number",
1174
+ "picture",
1175
+ "sub",
1176
+ "user_id"
1177
+ ]), ut = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
1178
+ function Y(e, t) {
1179
+ return Object.prototype.hasOwnProperty.call(e, t);
1180
+ }
1181
+ function K(e) {
1182
+ throw y({ statusCode: 400, statusMessage: e });
1183
+ }
1184
+ function Re(e, t) {
1185
+ return typeof e == "boolean" ? e : e === "true" ? !0 : e === "false" ? !1 : t;
1186
+ }
1187
+ function Ve(e) {
1188
+ const t = typeof e == "number" ? e : Number(e);
1189
+ return Number.isFinite(t) ? Math.min(100, Math.max(10, Math.trunc(t))) : 50;
1190
+ }
1191
+ function lt(e) {
1192
+ 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;
1194
+ }
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;
1198
+ }
1199
+ function mt(e) {
1200
+ 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);
1209
+ }
1210
+ }
1211
+ return s.length > 50 ? K("No more than 50 role options may be configured.") : s;
1212
+ }
1213
+ function ft(e) {
1214
+ 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")
1224
+ };
1225
+ return new Set(Object.values(r)).size !== Object.keys(r).length && K("Each configured Firestore profile field must use a distinct field name."), {
1226
+ project: t,
1227
+ pageSize: Ve(e.pageSize),
1228
+ linkFirestoreProfiles: Re(e.linkFirestoreProfiles, !0),
1229
+ profileCollection: lt(e.profileCollection),
1230
+ ...r,
1231
+ manageRoleClaim: s,
1232
+ roleClaimKey: i,
1233
+ roleOptions: mt(e.roleOptions)
1234
+ };
1235
+ }
1236
+ function Me(e) {
1237
+ const t = Array.isArray(e) ? e[0] : e;
1238
+ return typeof t != "string" ? void 0 : t.trim() || void 0;
1239
+ }
1240
+ function Se(e) {
1241
+ const t = Array.isArray(e) ? e[0] : e;
1242
+ if (!(typeof t != "string" || t.length === 0))
1243
+ return t;
1244
+ }
1245
+ function gt(e, t = 50) {
1246
+ const s = Me(e.limit);
1247
+ let i = Ve(t);
1248
+ if (s !== void 0) {
1249
+ 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." });
1253
+ }
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 } };
1271
+ }
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 } };
1277
+ }
1278
+ const o = he.safeParse(a);
1279
+ if (!o.success)
1280
+ throw y({ statusCode: 422, statusMessage: "UID search is invalid." });
1281
+ return { limit: 1, search: { kind: "uid", value: o.data } };
1282
+ }
1283
+ function pt(e) {
1284
+ const t = new TextEncoder().encode(e);
1285
+ let s = "";
1286
+ for (const i of t) s += String.fromCharCode(i);
1287
+ return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
1288
+ }
1289
+ function ht(e) {
1290
+ if (!/^[A-Za-z0-9_-]{1,1024}$/.test(e))
1291
+ throw y({ statusCode: 400, statusMessage: "Firebase UID token is invalid." });
1292
+ const t = e.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(e.length / 4) * 4, "=");
1293
+ let s;
1294
+ try {
1295
+ const i = atob(t), r = Uint8Array.from(i, (a) => a.charCodeAt(0));
1296
+ s = new TextDecoder("utf-8", { fatal: !0 }).decode(r);
1297
+ } catch {
1298
+ throw y({ statusCode: 400, statusMessage: "Firebase UID token is invalid." });
1299
+ }
1300
+ if (pt(s) !== e || !he.safeParse(s).success)
1301
+ throw y({ statusCode: 400, statusMessage: "Firebase UID token is invalid." });
1302
+ return s;
1303
+ }
1304
+ function ye(e, t) {
1305
+ return e.isAdmin === !0 || Array.isArray(e.permissions) && e.permissions.includes(t);
1306
+ }
1307
+ function yt(e, t) {
1308
+ return t.kind === "uid" || ye(e, v.viewPii);
1309
+ }
1310
+ function wt(e, t) {
1311
+ 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);
1315
+ return s === 0;
1316
+ }
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." });
1320
+ }
1321
+ function ze(e) {
1322
+ if (!e) return null;
1323
+ const t = e.lastIndexOf("@");
1324
+ 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}`;
1327
+ }
1328
+ function bt(e) {
1329
+ return e ? `+••••••${e.replace(/\D/g, "").slice(-2)}` : null;
1330
+ }
1331
+ function Ct(e) {
1332
+ 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
+ /\b(password|passcode|token|secret|api[-_\s]?key|authorization)\b\s*[:=]?\s*\S+/gi,
1334
+ "$1 [redacted]"
1335
+ );
1336
+ }
1337
+ function Le(e) {
1338
+ return e ? `${e.slice(0, 1)}•••` : null;
1339
+ }
1340
+ function U(e) {
1341
+ return typeof e == "string" ? e : null;
1342
+ }
1343
+ function At(e) {
1344
+ const t = [];
1345
+ if (Array.isArray(e?.providerData))
1346
+ for (const s of e.providerData) {
1347
+ const i = U(s?.providerId);
1348
+ i && t.push(i);
1349
+ }
1350
+ return [...new Set(t)].sort();
1351
+ }
1352
+ function He(e) {
1353
+ return Array.isArray(e?.multiFactor?.enrolledFactors) ? e.multiFactor.enrolledFactors.length : 0;
1354
+ }
1355
+ function we(e, t) {
1356
+ return t.manageRoleClaim ? U(e?.customClaims?.[t.roleClaimKey]) : null;
1357
+ }
1358
+ function Dt() {
1359
+ return {
1360
+ enabled: !1,
1361
+ exists: !1,
1362
+ name: null,
1363
+ email: null,
1364
+ role: null,
1365
+ status: null
1366
+ };
1367
+ }
1368
+ function Ft(e, t, s) {
1369
+ const i = e ? U(e[s.profileNameField]) : null, r = e ? U(e[s.profileEmailField]) : null;
1370
+ return {
1371
+ enabled: !0,
1372
+ 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
1377
+ };
1378
+ }
1379
+ function le(e, t) {
1380
+ const s = U(e?.email), i = U(e?.displayName), r = U(e?.phoneNumber);
1381
+ let a;
1382
+ return t.config.linkFirestoreProfiles ? t.profileAvailable === !1 ? a = null : a = Ft(t.profile || null, t.canViewPii, t.config) : a = Dt(), {
1383
+ 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,
1388
+ emailVerified: e?.emailVerified === !0,
1389
+ 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),
1396
+ profile: a
1397
+ };
1398
+ }
1399
+ function Pe(e, t) {
1400
+ if (!e) return null;
1401
+ const s = le(e, {
1402
+ canViewPii: !1,
1403
+ config: t,
1404
+ profileAvailable: !1
1405
+ });
1406
+ return {
1407
+ uid: s.uid,
1408
+ displayName: s.displayName,
1409
+ email: s.email,
1410
+ phoneNumber: s.phoneNumber,
1411
+ emailVerified: s.emailVerified,
1412
+ disabled: s.disabled,
1413
+ providers: s.providers,
1414
+ mfaFactorCount: s.mfaFactorCount,
1415
+ role: s.role
1416
+ };
1417
+ }
1418
+ function It(e, t, s) {
1419
+ const i = { ...e || {} };
1420
+ return s === null ? delete i[t] : i[t] = s, i;
1421
+ }
1422
+ function ke(e, t) {
1423
+ const s = {
1424
+ [t.profileUidField]: String(e.uid),
1425
+ [t.profileStatusField]: e.disabled === !0 ? "disabled" : "active"
1426
+ };
1427
+ 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;
1430
+ }
1431
+ function ie(e) {
1432
+ if (!e || typeof e != "object") return;
1433
+ const t = e;
1434
+ if (typeof t.code == "string") return t.code;
1435
+ if (typeof t.errorInfo?.code == "string") return t.errorInfo.code;
1436
+ }
1437
+ function Rt(e, t = "Firebase Authentication request failed.") {
1438
+ const s = ie(e);
1439
+ return s === "auth/user-not-found" ? { statusCode: 404, statusMessage: "Firebase user not found." } : s && [
1440
+ "auth/email-already-exists",
1441
+ "auth/phone-number-already-exists",
1442
+ "auth/uid-already-exists"
1443
+ ].includes(s) ? { statusCode: 409, statusMessage: "A Firebase user already uses that identifier." } : s && (s.startsWith("auth/invalid-") || s === "auth/weak-password" || s === "auth/claims-too-large" || s === "auth/reserved-claims") ? { statusCode: 422, statusMessage: "Firebase rejected the supplied user data." } : s && [
1444
+ "auth/too-many-requests",
1445
+ "auth/quota-exceeded"
1446
+ ].includes(s) ? { statusCode: 429, statusMessage: "Firebase temporarily rate-limited this request." } : s && [
1447
+ "auth/insufficient-permission",
1448
+ "auth/project-not-found",
1449
+ "auth/configuration-not-found"
1450
+ ].includes(s) ? { statusCode: 424, statusMessage: "The Firebase integration is not authorized for this operation." } : { statusCode: 502, statusMessage: t };
1451
+ }
1452
+ function _(e) {
1453
+ const t = e?.context?.module;
1454
+ 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." });
1456
+ return {
1457
+ ...t,
1458
+ isAdmin: t.isAdmin === !0,
1459
+ permissions: Array.isArray(t.permissions) ? t.permissions : []
1460
+ };
1461
+ }
1462
+ async function z(e, t) {
1463
+ const s = t.safeParse(await Q(e));
1464
+ if (!s.success)
1465
+ throw y({
1466
+ statusCode: 422,
1467
+ statusMessage: s.error.issues[0]?.message || "Request body is invalid."
1468
+ });
1469
+ return s.data;
1470
+ }
1471
+ function L(e) {
1472
+ const t = N(e, "uid");
1473
+ if (typeof t != "string")
1474
+ throw y({ statusCode: 400, statusMessage: "A valid Firebase UID is required." });
1475
+ return ht(t);
1476
+ }
1477
+ function q(e, t) {
1478
+ if (typeof e?.statusCode == "number" && typeof e?.statusMessage == "string")
1479
+ 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);
1482
+ }
1483
+ function Mt(e) {
1484
+ return ie(e) === "auth/user-not-found";
1485
+ }
1486
+ function pe(e) {
1487
+ return ye(e, v.viewPii);
1488
+ }
1489
+ function St(e, t) {
1490
+ const s = [];
1491
+ for (let i = 0; i < e.length; i += t)
1492
+ s.push(e.slice(i, i + t));
1493
+ return s;
1494
+ }
1495
+ function me(e) {
1496
+ return e.length > 0 && e !== "." && e !== ".." && !e.includes("/") && !/^__.*__$/.test(e);
1497
+ }
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());
1505
+ }
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();
1509
+ 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);
1512
+ }
1513
+ }
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() };
1522
+ }
1523
+ const a = (await i.where(s.profileUidField, "==", t).limit(1).get()).docs?.[0];
1524
+ return a ? { id: String(a.id), data: a.data() } : null;
1525
+ }
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." });
1537
+ const o = await t.initFirebase(e, a.project);
1538
+ return {
1539
+ module: s,
1540
+ config: a,
1541
+ integrationId: a.project,
1542
+ firebase: o,
1543
+ auth: o.auth(),
1544
+ firestore: o.firestore()
1545
+ };
1546
+ }
1547
+ async function H(e, t, s) {
1548
+ const i = {
1549
+ project_id: t.module.projectId,
1550
+ module_id: t.module.instanceId,
1551
+ user_id: t.module.userId,
1552
+ message: `Firebase Auth: ${s.action}`,
1553
+ level: "INFO",
1554
+ params: {
1555
+ source: Oe,
1556
+ action: s.action,
1557
+ targetUid: s.targetUid,
1558
+ integrationId: t.integrationId,
1559
+ reason: Ct(s.reason),
1560
+ before: Pe(s.before, t.config),
1561
+ after: Pe(s.after, t.config),
1562
+ ...s.details || {}
1563
+ }
1564
+ };
1565
+ 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";
1570
+ return console.error("Firebase Auth Manager audit insert failed", { code: a }), !1;
1571
+ }
1572
+ }
1573
+ async function kt(e, t) {
1574
+ try {
1575
+ return t.kind === "email" ? [await e.getUserByEmail(t.value)] : t.kind === "phone" ? [await e.getUserByPhoneNumber(t.value)] : [await e.getUser(t.value)];
1576
+ } catch (s) {
1577
+ if (Mt(s)) return [];
1578
+ throw s;
1579
+ }
1580
+ }
1581
+ async function Ue(e, t, s) {
1582
+ try {
1583
+ return await e.getUser(t);
1584
+ } catch (i) {
1585
+ return console.error("Firebase Auth Manager post-mutation refresh failed", {
1586
+ code: ie(i) || "unknown"
1587
+ }), s;
1588
+ }
1589
+ }
1590
+ async function J(e, t) {
1591
+ let s = /* @__PURE__ */ new Map(), i = !0;
1592
+ if (t.config.linkFirestoreProfiles)
1593
+ try {
1594
+ s = await Pt(t.firestore, e, t.config);
1595
+ } catch (r) {
1596
+ i = !1;
1597
+ const a = ie(r);
1598
+ console.error("Firebase Auth Manager profile join failed", { code: a || "unknown" });
1599
+ }
1600
+ return e.map((r) => le(r, {
1601
+ canViewPii: pe(t.module),
1602
+ config: t.config,
1603
+ profile: s.get(String(r.uid)) || null,
1604
+ profileAvailable: i
1605
+ }));
1606
+ }
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);
1612
+ 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({
1616
+ statusCode: 403,
1617
+ statusMessage: "Viewing personal data is required to search by email or phone number."
1618
+ });
1619
+ let n, c = null;
1620
+ if (a.search)
1621
+ n = await kt(r.auth, a.search);
1622
+ 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;
1625
+ }
1626
+ return {
1627
+ users: await J(n, r),
1628
+ nextPageToken: c
1629
+ };
1630
+ } catch (r) {
1631
+ q(r, "Failed to list Firebase users.");
1632
+ }
1633
+ })), t.get("/users/:uid", A(async (s) => {
1634
+ const i = _(s);
1635
+ T(i, v.viewUsers);
1636
+ const r = L(s);
1637
+ try {
1638
+ const a = await O(s, e), n = await a.auth.getUser(r), [c] = await J([n], a);
1639
+ return { user: c };
1640
+ } catch (a) {
1641
+ q(a, "Failed to load the Firebase user.");
1642
+ }
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);
1648
+ 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({
1654
+ statusCode: 409,
1655
+ statusMessage: "A retained Firestore profile already uses this UID. Resolve that profile before reusing the Authentication UID."
1656
+ });
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
1665
+ });
1666
+ let c = null, o = !1, u = null;
1667
+ if (r.createProfile) {
1668
+ c = ke(n, a.config);
1669
+ try {
1670
+ const l = a.firestore.collection(a.config.profileCollection);
1671
+ await (me(n.uid) ? l.doc(n.uid) : l.doc()).create(c), o = !0;
1672
+ } catch {
1673
+ c = null, u = "The Authentication user was created, but its Firestore profile could not be created.";
1674
+ }
1675
+ }
1676
+ const d = await H(s, a, {
1677
+ action: "user.create",
1678
+ targetUid: n.uid,
1679
+ reason: "Created through Firebase Auth Manager.",
1680
+ before: null,
1681
+ after: n,
1682
+ details: {
1683
+ profileRequested: r.createProfile === !0,
1684
+ profileCreated: o
1685
+ }
1686
+ });
1687
+ return Ze(s, 201), {
1688
+ user: le(n, {
1689
+ canViewPii: pe(a.module),
1690
+ config: a.config,
1691
+ profile: c
1692
+ }),
1693
+ profileCreated: o,
1694
+ profileError: u,
1695
+ auditRecorded: d
1696
+ };
1697
+ } catch (a) {
1698
+ q(a, "Failed to create the Firebase user.");
1699
+ }
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);
1704
+ 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, {
1708
+ action: "user.update",
1709
+ targetUid: r,
1710
+ reason: a.reason,
1711
+ before: c,
1712
+ after: u,
1713
+ 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.");
1718
+ }
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);
1723
+ 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, {
1725
+ action: a.disabled ? "user.disable" : "user.enable",
1726
+ targetUid: r,
1727
+ reason: a.reason,
1728
+ before: c,
1729
+ after: u,
1730
+ 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.");
1735
+ }
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);
1740
+ 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, {
1744
+ action: "user.revoke_sessions",
1745
+ targetUid: r,
1746
+ reason: a.reason,
1747
+ before: c,
1748
+ after: c,
1749
+ 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.");
1754
+ }
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);
1759
+ 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, {
1761
+ action: "user.reset_mfa",
1762
+ targetUid: r,
1763
+ reason: a.reason,
1764
+ before: c,
1765
+ after: u,
1766
+ 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.");
1771
+ }
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);
1776
+ 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 };
1787
+ }
1788
+ const l = await H(s, n, {
1789
+ action: "user.set_role",
1790
+ targetUid: r,
1791
+ reason: a.reason,
1792
+ before: c,
1793
+ after: d,
1794
+ details: { changed: u, role: a.role }
1795
+ });
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.");
1801
+ }
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);
1806
+ 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;
1812
+ 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;
1816
+ }
1817
+ const l = await H(s, n, {
1818
+ action: "user.create_profile",
1819
+ targetUid: r,
1820
+ reason: a.reason,
1821
+ before: c,
1822
+ after: c,
1823
+ details: { changed: d }
1824
+ });
1825
+ return {
1826
+ user: le(c, {
1827
+ canViewPii: pe(n.module),
1828
+ config: n.config,
1829
+ profile: u
1830
+ }),
1831
+ profileCreated: d,
1832
+ auditRecorded: l
1833
+ };
1834
+ } catch (n) {
1835
+ q(n, "Failed to create the Firestore profile.");
1836
+ }
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." });
1843
+ 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, {
1847
+ action: "user.delete",
1848
+ targetUid: r,
1849
+ reason: a.reason,
1850
+ before: c,
1851
+ after: null,
1852
+ details: { firestoreProfilePreserved: !0 }
1853
+ });
1854
+ return {
1855
+ uid: r,
1856
+ deleted: !0,
1857
+ firestoreProfilePreserved: !0,
1858
+ auditRecorded: o
1859
+ };
1860
+ } catch (n) {
1861
+ q(n, "Failed to delete the Firebase user.");
1862
+ }
1863
+ })), t.handler;
1864
+ }
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 = {
1866
+ view: "view-forms",
1867
+ create: "create-form",
1868
+ edit: "edit-form",
1869
+ publish: "publish-form",
1870
+ archive: "archive-form"
1871
+ };
1872
+ function I(e) {
1873
+ throw y({ statusCode: 400, statusMessage: e });
1874
+ }
1875
+ function G(e) {
1876
+ throw y({ statusCode: 409, statusMessage: e });
1877
+ }
1878
+ function Ce(e, t) {
1879
+ (!e || typeof e != "object" || Array.isArray(e)) && I(`${t} must be an object.`);
1880
+ const s = Object.getPrototypeOf(e);
1881
+ return s !== Object.prototype && s !== null && I(`${t} must be a plain object.`), e;
1882
+ }
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;
1887
+ }
1888
+ function Tt(e) {
1889
+ if (e == null) return "";
1890
+ typeof e != "string" && I("Form description must be a string.");
1891
+ const t = e.trim();
1892
+ return t.length > Ee && I(`Form description cannot exceed ${Ee} characters.`), t;
1893
+ }
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;
1897
+ }
1898
+ function qt(e) {
1899
+ if (e == null || e === "")
1900
+ return xt;
1901
+ typeof e != "string" && I("The configured forms collection must be a string.");
1902
+ 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.");
1904
+ 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.");
1908
+ return t;
1909
+ }
1910
+ function Ot(e) {
1911
+ (!e || typeof e != "object") && I("Form definition must be an object or array.");
1912
+ const t = /* @__PURE__ */ new Set();
1913
+ 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.");
1918
+ return;
1919
+ }
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);
1924
+ return;
1925
+ }
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);
1931
+ };
1932
+ i(e, 1, !1);
1933
+ let r;
1934
+ try {
1935
+ r = JSON.stringify(e);
1936
+ } catch {
1937
+ I("Form definition must be valid JSON.");
1938
+ }
1939
+ new TextEncoder().encode(r).byteLength > Ne && I(`Form definition cannot exceed ${Ne} bytes.`);
1940
+ }
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),
1947
+ definition: s
1948
+ };
1949
+ }
1950
+ function Bt(e) {
1951
+ return Ye(e);
1952
+ }
1953
+ function Ke(e) {
1954
+ return (!Number.isInteger(e) || e < 1) && I("expectedRevision must be a positive integer."), e;
1955
+ }
1956
+ function jt(e) {
1957
+ const t = Ce(e, "Request body");
1958
+ return {
1959
+ ...Ye(t),
1960
+ expectedRevision: Ke(t.expectedRevision)
1961
+ };
1962
+ }
1963
+ function ge(e) {
1964
+ const t = Ce(e, "Request body");
1965
+ return { expectedRevision: Ke(t.expectedRevision) };
1966
+ }
1967
+ function $t(e) {
1968
+ return {
1969
+ id: e.revisionId,
1970
+ formId: e.formId,
1971
+ key: e.form.key,
1972
+ name: e.form.name,
1973
+ description: e.form.description || "",
1974
+ definition: e.form.draftDefinition,
1975
+ schemaVersion: e.form.schemaVersion || be,
1976
+ revision: e.revision,
1977
+ draftRevision: e.form.draftRevision,
1978
+ previousRevisionId: e.form.publishedRevisionId || null,
1979
+ publishedAt: e.publishedAt,
1980
+ publishedBy: e.publishedBy
1981
+ };
1982
+ }
1983
+ function ee(e) {
1984
+ typeof e != "string" && I("Form ID is required.");
1985
+ 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;
1987
+ }
1988
+ function oe(e) {
1989
+ const s = e?.context?.module?.userId || e?.context?.user?.id || null;
1990
+ return typeof s == "string" && s.trim() ? s : null;
1991
+ }
1992
+ function E(e, t) {
1993
+ const s = e?.context?.module;
1994
+ if (!s)
1995
+ throw y({ statusCode: 500, statusMessage: "Module context is unavailable." });
1996
+ if (!s.userId)
1997
+ throw y({ statusCode: 401, statusMessage: "Unauthorized" });
1998
+ if (s.isAdmin === !0) return;
1999
+ if (!(Array.isArray(s.permissions) ? s.permissions : []).includes(t))
2000
+ throw y({ statusCode: 403, statusMessage: `Missing module permission: ${t}.` });
2001
+ }
2002
+ function te(e) {
2003
+ if (!e || typeof e != "object" || Array.isArray(e))
2004
+ throw y({ statusCode: 500, statusMessage: "Stored form data is invalid." });
2005
+ 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." });
2008
+ return t;
2009
+ }
2010
+ function ue(e, t) {
2011
+ e.revision !== t && G(`Form has changed. Expected revision ${t}, current revision is ${e.revision}.`);
2012
+ }
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.");
2015
+ }
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;
2018
+ 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,
2027
+ 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
2039
+ };
2040
+ }
2041
+ function _e(e, t) {
2042
+ if (!(e == null || e === ""))
2043
+ return (Array.isArray(e) || typeof e != "string") && I(`${t} must be a single string.`), e.trim();
2044
+ }
2045
+ function qe(e) {
2046
+ if (typeof e == "string") {
2047
+ const t = Date.parse(e);
2048
+ return Number.isNaN(t) ? 0 : t;
2049
+ }
2050
+ return e instanceof Date ? e.getTime() : e && typeof e.toMillis == "function" ? e.toMillis() : 0;
2051
+ }
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 }));
2054
+ }
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();
2062
+ 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;
2069
+ if (typeof m != "string" || !m.trim())
2070
+ throw y({
2071
+ statusCode: 400,
2072
+ statusMessage: "Form Builder has no Firebase integration configured."
2073
+ });
2074
+ 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({
2079
+ statusCode: 400,
2080
+ statusMessage: "Configured Firebase integration is unavailable for this project."
2081
+ });
2082
+ const C = qt(g.formsCollection), b = ee(o), F = (await t(a, m)).firestore();
2083
+ return {
2084
+ firestore: F,
2085
+ // Access is granted per module instance in Studio, so storage must be
2086
+ // isolated at the same boundary even when multiple instances retain the
2087
+ // default root collection.
2088
+ forms: F.collection(C).doc(b).collection("forms")
2089
+ };
2090
+ }
2091
+ return i.get("/forms", A(async (a) => {
2092
+ E(a, x.view);
2093
+ 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(
2098
+ f.id,
2099
+ te(f.data()),
2100
+ s,
2101
+ !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.");
2105
+ }
2106
+ })), i.get("/forms/:formId", A(async (a) => {
2107
+ E(a, x.view);
2108
+ const n = ee(N(a, "formId"));
2109
+ try {
2110
+ const { forms: c } = await r(a), o = await c.doc(n).get();
2111
+ 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.");
2116
+ }
2117
+ })), i.post("/forms", A(async (a) => {
2118
+ E(a, x.view), E(a, x.create);
2119
+ 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,
2124
+ status: "draft",
2125
+ draftDefinition: n.definition,
2126
+ schemaVersion: be,
2127
+ revision: 1,
2128
+ draftRevision: 1,
2129
+ publishedRevision: null,
2130
+ publishedRevisionId: null,
2131
+ publishedDraftRevision: null,
2132
+ createdAt: o,
2133
+ createdBy: c,
2134
+ updatedAt: o,
2135
+ updatedBy: c,
2136
+ draftUpdatedAt: o,
2137
+ draftUpdatedBy: c,
2138
+ publishedAt: null,
2139
+ publishedBy: null,
2140
+ archivedAt: null,
2141
+ archivedBy: null,
2142
+ statusBeforeArchive: null
2143
+ };
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.");
2149
+ }
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"));
2153
+ 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);
2157
+ 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,
2166
+ revision: h.revision + 1,
2167
+ draftRevision: h.draftRevision + 1,
2168
+ updatedAt: u,
2169
+ updatedBy: o,
2170
+ draftUpdatedAt: u,
2171
+ draftUpdatedBy: o
2172
+ };
2173
+ return g.update(f, p), X(n, { ...h, ...p }, s);
2174
+ });
2175
+ } catch (c) {
2176
+ Z("update draft", c, "Failed to update form draft.");
2177
+ }
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"));
2181
+ 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) => {
2184
+ const h = await m.get(f);
2185
+ 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,
2192
+ revision: w,
2193
+ revisionId: g.id,
2194
+ publishedAt: u,
2195
+ publishedBy: o
2196
+ }), b = {
2197
+ status: "published",
2198
+ revision: w,
2199
+ publishedRevision: w,
2200
+ publishedRevisionId: g.id,
2201
+ publishedDraftRevision: p.draftRevision,
2202
+ publishedAt: u,
2203
+ publishedBy: o,
2204
+ updatedAt: u,
2205
+ updatedBy: o,
2206
+ archivedAt: null,
2207
+ archivedBy: null,
2208
+ statusBeforeArchive: null
2209
+ };
2210
+ return m.create(g, C), m.update(f, b), X(n, { ...p, ...b }, s);
2211
+ });
2212
+ } catch (c) {
2213
+ Z("publish", c, "Failed to publish form.");
2214
+ }
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"));
2218
+ 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);
2222
+ 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 = {
2227
+ status: "archived",
2228
+ statusBeforeArchive: h.status,
2229
+ revision: h.revision + 1,
2230
+ archivedAt: u,
2231
+ archivedBy: o,
2232
+ updatedAt: u,
2233
+ updatedBy: o
2234
+ };
2235
+ return g.update(f, p), X(n, { ...h, ...p }, s);
2236
+ });
2237
+ } catch (c) {
2238
+ Z("archive", c, "Failed to archive form.");
2239
+ }
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"));
2243
+ 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);
2247
+ 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.");
2251
+ const w = {
2252
+ status: h.publishedRevisionId ? "published" : "draft",
2253
+ statusBeforeArchive: null,
2254
+ revision: h.revision + 1,
2255
+ archivedAt: null,
2256
+ archivedBy: null,
2257
+ updatedAt: u,
2258
+ updatedBy: o
2259
+ };
2260
+ return g.update(f, w), X(n, { ...h, ...w }, s);
2261
+ });
2262
+ } catch (c) {
2263
+ Z("restore", c, "Failed to restore form.");
2264
+ }
2265
+ })), i.handler;
1109
2266
  }
1110
2267
  export {
1111
- J as appointments,
1112
- Y as contentManager,
1113
- W as googleAnalytics,
1114
- z as products
2268
+ Qt as appointments,
2269
+ Kt as contentManager,
2270
+ Jt as firebaseAuthManager,
2271
+ Xt as formBuilder,
2272
+ Yt as googleAnalytics,
2273
+ Gt as products
1115
2274
  };