@oneclick.dev/cms-core-modules 0.0.82 → 0.0.84
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.
- package/dist/{ContentEditor-Dk-iDEjl.mjs → ContentEditor-DPhhOkx3.mjs} +7085 -5936
- package/dist/{ContentEditor-4e80zFyn.js → ContentEditor-DrxtH_Hq.js} +42 -42
- package/dist/{Create-DtFzwxn_.mjs → Create-6uT9HWar.mjs} +35 -35
- package/dist/{Create-CRn2sMHp.js → Create-DuZ5nZrX.js} +1 -1
- package/dist/{DateFormatter-DfIwyrnF.mjs → DateFormatter-2B0R-DY4.mjs} +213 -406
- package/dist/DateFormatter-DbtOLV0L.js +1 -0
- package/dist/{Detail-Bxi7lG9x.js → Detail-BZ-iE9vf.js} +1 -1
- package/dist/{Detail-B4b_FLDa.mjs → Detail-C1Blq61w.mjs} +90 -90
- package/dist/{Detail-BayNaAg9.js → Detail-C8wQiDcv.js} +1 -1
- package/dist/{Detail-BwDnY42G.mjs → Detail-CJVMJDP7.mjs} +17 -17
- package/dist/{Detail-CnK-qbhE.js → Detail-CPqug27l.js} +1 -1
- package/dist/Detail-CjuhjPby.js +1 -0
- package/dist/{Detail-U0mgLKt6.mjs → Detail-CtItxMX4.mjs} +62 -63
- package/dist/{Detail-CVgWHbMC.mjs → Detail-Dnpnmy4-.mjs} +158 -158
- package/dist/{Entries-D7MHylQE.mjs → Entries-BkOPae4R.mjs} +49 -49
- package/dist/Entries-CcEW98F5.js +1 -0
- package/dist/{NewReservationDialog.vue_vue_type_script_setup_true_lang-Ds7z0qeH.mjs → NewReservationDialog.vue_vue_type_script_setup_true_lang-Bc946oSc.mjs} +1 -1
- package/dist/{NewReservationDialog.vue_vue_type_script_setup_true_lang-C5YczjNb.js → NewReservationDialog.vue_vue_type_script_setup_true_lang-CqERfyYb.js} +1 -1
- package/dist/{Overview-CwCAeBnX.js → Overview-CA8wh_BI.js} +1 -1
- package/dist/{Overview-CgViRnNc.mjs → Overview-D4MFwRI_.mjs} +67 -68
- package/dist/{Overview-pCO_47Zt.js → Overview-Da0XexiT.js} +1 -1
- package/dist/Overview-DeQQ0FY3.js +1 -0
- package/dist/{Overview--XpvBbqz.mjs → Overview-DoOASlNz.mjs} +1 -3
- package/dist/{Overview-CuCQgqVp.mjs → Overview-gJSvftdE.mjs} +34 -34
- package/dist/{ReservationDetailDialog.vue_vue_type_script_setup_true_lang-B7ks5mbf.mjs → ReservationDetailDialog.vue_vue_type_script_setup_true_lang-Cohhnd5x.mjs} +0 -1
- package/dist/{ReservationDetailDialog.vue_vue_type_script_setup_true_lang-Vxubki_v.js → ReservationDetailDialog.vue_vue_type_script_setup_true_lang-VWVIxIr6.js} +1 -1
- package/dist/{SeoHealth-CC0rW1AG.mjs → SeoHealth-Bc5chnaa.mjs} +14 -14
- package/dist/{SeoHealth-EZzDmPDM.js → SeoHealth-BkpJ1F2Y.js} +1 -1
- package/dist/TableView-BPWAx--G.mjs +5743 -0
- package/dist/TableView-D63QrVlK.js +4 -0
- package/dist/View-BL70u98U.js +1 -0
- package/dist/{View-DDXN0tKD.mjs → View-BO5N911y.mjs} +5 -5
- package/dist/{agenda-XqvbrU72.mjs → agenda-C5grvzSa.mjs} +166 -169
- package/dist/agenda-DXMwVWpN.js +1 -0
- package/dist/{availability-B-tRp8hB.mjs → availability-C1NqOFsQ.mjs} +81 -81
- package/dist/{availability-BiBbzEIM.js → availability-D_wnfLsH.js} +1 -1
- package/dist/cms-core-modules.css +1 -1
- package/dist/{exceptions-CLgeeUSy.mjs → exceptions-BIwMhYa4.mjs} +1 -1
- package/dist/{exceptions-wEQEVzIs.js → exceptions-Cn7zooEu.js} +1 -1
- package/dist/{index-DTzdHh6g.js → index-C9pSS15N.js} +2 -2
- package/dist/{index-N0NoDEsI.mjs → index-MwjeLHPP.mjs} +3 -3
- package/dist/index.cjs.js +1 -1
- package/dist/index.mjs +50 -36
- package/dist/orders-CG1QUCN8.js +1 -0
- package/dist/orders-CeixEBcU.mjs +396 -0
- package/dist/server-handlers.cjs.js +1 -1
- package/dist/server-handlers.mjs +292 -256
- package/dist/src/contentManager/config.d.ts +28 -0
- package/dist/src/contentManager/index.d.ts +28 -0
- package/dist/src/contentManager/server.d.ts +7 -0
- package/dist/src/server-handlers.d.ts +1 -0
- package/package.json +2 -2
- package/dist/DateFormatter-C9qfmQnP.js +0 -1
- package/dist/Detail-BcboL7NF.js +0 -1
- package/dist/Entries-BPkZ7Jg5.js +0 -1
- package/dist/Overview-B-8TLLjh.js +0 -1
- package/dist/TableView-Ce8H65pL.js +0 -586
- package/dist/TableView-DRQvOW85.mjs +0 -89190
- package/dist/View-DfzaVOzS.js +0 -1
- package/dist/agenda-wNFDKn0G.js +0 -1
- package/dist/floating-ui.dom-BO2Hr6mz.mjs +0 -1292
- package/dist/floating-ui.dom-CAr9LGoC.js +0 -1
- package/dist/index-DYpruS-A-CA2jEOA3.js +0 -88
- package/dist/index-DYpruS-A-D38FBcI3.mjs +0 -4211
- package/dist/index-YMaY4uuk-BgpTtr73.js +0 -1
- package/dist/index-YMaY4uuk-C_xV5K9Z.mjs +0 -1300
- package/dist/orders-Bqa3Z3tH.mjs +0 -356
- package/dist/orders-D5GJOZXN.js +0 -1
package/dist/server-handlers.mjs
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import { createRouter as v, defineEventHandler as y, createError as
|
|
1
|
+
import { createRouter as v, defineEventHandler as y, createError as w, getRouterParam as N, getQuery as D } from "h3";
|
|
2
2
|
import "vue";
|
|
3
|
-
function $(
|
|
4
|
-
const { initFirebase:
|
|
3
|
+
function $(f) {
|
|
4
|
+
const { initFirebase: R, normalizeTimestamps: A } = f, g = v();
|
|
5
5
|
async function m(d) {
|
|
6
|
-
const { supabase: c, instanceId:
|
|
7
|
-
if (
|
|
8
|
-
throw
|
|
6
|
+
const { supabase: c, instanceId: l } = d.context.module, { data: e, error: a } = await c.from("project_modules").select("config").eq("id", l).single();
|
|
7
|
+
if (a || !e?.config)
|
|
8
|
+
throw w({ statusCode: 500, statusMessage: "Failed to load module config." });
|
|
9
9
|
const n = e.config, t = n.project, s = n.productCollection || "products";
|
|
10
10
|
if (!t)
|
|
11
|
-
throw
|
|
12
|
-
return { firebase: await
|
|
11
|
+
throw w({ statusCode: 400, statusMessage: "Products module has no Firebase integration configured." });
|
|
12
|
+
return { firebase: await R(d, t), collection: s };
|
|
13
13
|
}
|
|
14
|
-
return
|
|
14
|
+
return g.get("/products", y(async (d) => {
|
|
15
15
|
try {
|
|
16
|
-
const { firebase: c, collection:
|
|
17
|
-
return (await c.firestore().collection(
|
|
18
|
-
id:
|
|
19
|
-
...
|
|
16
|
+
const { firebase: c, collection: l } = await m(d);
|
|
17
|
+
return (await c.firestore().collection(l).get()).docs.map((a) => A({
|
|
18
|
+
id: a.id,
|
|
19
|
+
...a.data()
|
|
20
20
|
}));
|
|
21
21
|
} catch (c) {
|
|
22
|
-
throw console.error("Products handler — list error:", c),
|
|
22
|
+
throw console.error("Products handler — list error:", c), w({
|
|
23
23
|
statusCode: c.statusCode || 500,
|
|
24
24
|
statusMessage: c.statusMessage || "Failed to list products"
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
-
})),
|
|
28
|
-
const c =
|
|
27
|
+
})), g.get("/products/:productId", y(async (d) => {
|
|
28
|
+
const c = N(d, "productId");
|
|
29
29
|
if (!c)
|
|
30
|
-
throw
|
|
30
|
+
throw w({ statusCode: 400, statusMessage: "Product ID is required." });
|
|
31
31
|
try {
|
|
32
|
-
const { firebase:
|
|
33
|
-
if (!
|
|
34
|
-
throw
|
|
32
|
+
const { firebase: l, collection: e } = await m(d), a = await l.firestore().collection(e).doc(c).get();
|
|
33
|
+
if (!a.exists)
|
|
34
|
+
throw w({ statusCode: 404, statusMessage: "Product not found." });
|
|
35
35
|
return A({
|
|
36
|
-
id:
|
|
37
|
-
...
|
|
36
|
+
id: a.id,
|
|
37
|
+
...a.data()
|
|
38
38
|
});
|
|
39
|
-
} catch (
|
|
40
|
-
throw console.error("Products handler — get error:",
|
|
41
|
-
statusCode:
|
|
42
|
-
statusMessage:
|
|
39
|
+
} catch (l) {
|
|
40
|
+
throw console.error("Products handler — get error:", l), w({
|
|
41
|
+
statusCode: l.statusCode || 500,
|
|
42
|
+
statusMessage: l.statusMessage || "Failed to get product"
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
-
})),
|
|
46
|
-
const
|
|
45
|
+
})), g.get("/empty-stock", y(async (d) => {
|
|
46
|
+
const l = D(d).category;
|
|
47
47
|
try {
|
|
48
|
-
const { firebase: e, collection:
|
|
49
|
-
let n = e.firestore().collection(
|
|
50
|
-
|
|
51
|
-
const s = (await n.get()).docs.map((
|
|
52
|
-
id:
|
|
53
|
-
...
|
|
48
|
+
const { firebase: e, collection: a } = await m(d);
|
|
49
|
+
let n = e.firestore().collection(a).where("stock", "==", 0);
|
|
50
|
+
l && (n = n.where("collections", "array-contains", l));
|
|
51
|
+
const s = (await n.get()).docs.map((o) => A({
|
|
52
|
+
id: o.id,
|
|
53
|
+
...o.data()
|
|
54
54
|
}));
|
|
55
55
|
return {
|
|
56
56
|
count: s.length,
|
|
57
|
-
products: s.map((
|
|
58
|
-
id:
|
|
59
|
-
title:
|
|
60
|
-
slug:
|
|
61
|
-
stock:
|
|
62
|
-
price:
|
|
63
|
-
currency:
|
|
64
|
-
status:
|
|
57
|
+
products: s.map((o) => ({
|
|
58
|
+
id: o.id,
|
|
59
|
+
title: o.title,
|
|
60
|
+
slug: o.slug,
|
|
61
|
+
stock: o.stock,
|
|
62
|
+
price: o.price,
|
|
63
|
+
currency: o.currency,
|
|
64
|
+
status: o.status
|
|
65
65
|
}))
|
|
66
66
|
};
|
|
67
67
|
} catch (e) {
|
|
68
|
-
throw console.error("Products handler — empty-stock error:", e),
|
|
68
|
+
throw console.error("Products handler — empty-stock error:", e), w({
|
|
69
69
|
statusCode: e.statusCode || 500,
|
|
70
70
|
statusMessage: e.statusMessage || "Failed to query empty stock"
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
|
-
})),
|
|
73
|
+
})), g.handler;
|
|
74
74
|
}
|
|
75
|
-
function
|
|
76
|
-
const { initFirebase:
|
|
75
|
+
function x(f) {
|
|
76
|
+
const { initFirebase: R, normalizeTimestamps: A } = f, g = v();
|
|
77
77
|
async function m(c) {
|
|
78
|
-
const { supabase:
|
|
79
|
-
if (n || !
|
|
80
|
-
throw
|
|
81
|
-
const t =
|
|
78
|
+
const { supabase: l, instanceId: e } = c.context.module, { data: a, error: n } = await l.from("project_modules").select("config").eq("id", e).single();
|
|
79
|
+
if (n || !a?.config)
|
|
80
|
+
throw w({ statusCode: 500, statusMessage: "Failed to load module config." });
|
|
81
|
+
const t = a.config, s = t.project, o = t.reservationsCollection || "bookings_orders", r = t.agendaCollection || "agendas";
|
|
82
82
|
if (!s)
|
|
83
|
-
throw
|
|
84
|
-
return { firebase: await
|
|
83
|
+
throw w({ statusCode: 400, statusMessage: "Appointments module has no Firebase integration configured." });
|
|
84
|
+
return { firebase: await R(c, s), reservationsCollection: o, agendaCollection: r };
|
|
85
85
|
}
|
|
86
86
|
function d(c) {
|
|
87
87
|
return (c.reservations || []).map((e) => ({
|
|
@@ -104,98 +104,96 @@ function G(w) {
|
|
|
104
104
|
createdAt: c.createdAt
|
|
105
105
|
}));
|
|
106
106
|
}
|
|
107
|
-
return
|
|
108
|
-
const
|
|
107
|
+
return g.get("/appointments", y(async (c) => {
|
|
108
|
+
const l = D(c), e = Math.min(Number(l.quantity) || 20, 100);
|
|
109
109
|
try {
|
|
110
|
-
const { firebase:
|
|
111
|
-
(
|
|
110
|
+
const { firebase: a, reservationsCollection: n } = await m(c), s = (await a.firestore().collection(n).orderBy("createdAt", "desc").limit(e).get()).docs.flatMap(
|
|
111
|
+
(o) => d(A({ id: o.id, ...o.data() }))
|
|
112
112
|
);
|
|
113
113
|
return {
|
|
114
114
|
count: s.length,
|
|
115
115
|
appointments: s
|
|
116
116
|
};
|
|
117
|
-
} catch (
|
|
118
|
-
throw console.error("Appointments handler — list error:",
|
|
119
|
-
statusCode:
|
|
120
|
-
statusMessage:
|
|
117
|
+
} catch (a) {
|
|
118
|
+
throw console.error("Appointments handler — list error:", a), w({
|
|
119
|
+
statusCode: a.statusCode || 500,
|
|
120
|
+
statusMessage: a.statusMessage || "Failed to list appointments"
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
|
-
})),
|
|
124
|
-
const
|
|
123
|
+
})), g.get("/appointments/find", y(async (c) => {
|
|
124
|
+
const l = D(c), e = (l.name || "").toLowerCase().trim(), a = (l.email || "").toLowerCase().trim(), n = l.date;
|
|
125
125
|
try {
|
|
126
126
|
const { firebase: t, reservationsCollection: s } = await m(c);
|
|
127
|
-
let
|
|
128
|
-
|
|
129
|
-
let i = (await
|
|
127
|
+
let o = t.firestore().collection(s);
|
|
128
|
+
a && (o = o.where("customerInfo.email", "==", a));
|
|
129
|
+
let i = (await o.orderBy("createdAt", "desc").limit(200).get()).docs.flatMap(
|
|
130
130
|
(u) => d(A({ id: u.id, ...u.data() }))
|
|
131
131
|
);
|
|
132
132
|
return n && (i = i.filter((u) => u.date === n)), e && (i = i.filter((u) => {
|
|
133
|
-
const p = (u.customerInfo?.firstName || "").toLowerCase(),
|
|
134
|
-
return p.includes(e) ||
|
|
133
|
+
const p = (u.customerInfo?.firstName || "").toLowerCase(), h = (u.customerInfo?.lastName || "").toLowerCase();
|
|
134
|
+
return p.includes(e) || h.includes(e) || `${p} ${h}`.includes(e);
|
|
135
135
|
})), {
|
|
136
136
|
count: i.length,
|
|
137
137
|
appointments: i
|
|
138
138
|
};
|
|
139
139
|
} catch (t) {
|
|
140
|
-
throw console.error("Appointments handler — find error:", t),
|
|
140
|
+
throw console.error("Appointments handler — find error:", t), w({
|
|
141
141
|
statusCode: t.statusCode || 500,
|
|
142
142
|
statusMessage: t.statusMessage || "Failed to find appointments"
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
-
})),
|
|
146
|
-
const
|
|
147
|
-
if (!
|
|
148
|
-
throw
|
|
145
|
+
})), g.get("/appointments/:appointmentId", y(async (c) => {
|
|
146
|
+
const l = N(c, "appointmentId");
|
|
147
|
+
if (!l)
|
|
148
|
+
throw w({ statusCode: 400, statusMessage: "Appointment ID is required." });
|
|
149
149
|
try {
|
|
150
|
-
const { firebase: e, reservationsCollection:
|
|
151
|
-
console.log("Fetching appointment with ID:", g, o);
|
|
152
|
-
const n = await e.firestore().collection(o).doc(g).get();
|
|
150
|
+
const { firebase: e, reservationsCollection: a } = await m(c), n = await e.firestore().collection(a).doc(l).get();
|
|
153
151
|
if (!n.exists)
|
|
154
|
-
throw
|
|
152
|
+
throw w({ statusCode: 404, statusMessage: "Appointment not found." });
|
|
155
153
|
const t = A({ id: n.id, ...n.data() });
|
|
156
154
|
return {
|
|
157
155
|
...t,
|
|
158
156
|
reservations: d(t)
|
|
159
157
|
};
|
|
160
158
|
} catch (e) {
|
|
161
|
-
throw console.error("Appointments handler — get error:", e),
|
|
159
|
+
throw console.error("Appointments handler — get error:", e), w({
|
|
162
160
|
statusCode: e.statusCode || 500,
|
|
163
161
|
statusMessage: e.statusMessage || "Failed to get appointment"
|
|
164
162
|
});
|
|
165
163
|
}
|
|
166
|
-
})),
|
|
164
|
+
})), g.handler;
|
|
167
165
|
}
|
|
168
166
|
const M = "https://analyticsdata.googleapis.com/v1beta", F = [
|
|
169
167
|
"https://www.googleapis.com/auth/analytics.readonly",
|
|
170
168
|
"https://www.googleapis.com/auth/webmasters.readonly"
|
|
171
|
-
],
|
|
172
|
-
function
|
|
173
|
-
const { decrypt:
|
|
169
|
+
], b = "https://searchconsole.googleapis.com/webmasters/v3";
|
|
170
|
+
function G(f) {
|
|
171
|
+
const { decrypt: R, getGoogleAccessToken: A } = f, g = v();
|
|
174
172
|
async function m(e) {
|
|
175
|
-
const { supabase:
|
|
173
|
+
const { supabase: a, instanceId: n } = e.context.module, { data: t, error: s } = await a.from("project_modules").select("config").eq("id", n).single();
|
|
176
174
|
if (s || !t?.config)
|
|
177
|
-
throw
|
|
178
|
-
const
|
|
175
|
+
throw w({ statusCode: 500, statusMessage: "Failed to load module config." });
|
|
176
|
+
const o = t.config, r = o.propertyId, i = o.serviceAccount, u = o.siteUrl || "";
|
|
179
177
|
if (!i)
|
|
180
|
-
throw
|
|
178
|
+
throw w({ statusCode: 400, statusMessage: "No Google Service Account configured for this module." });
|
|
181
179
|
if (!r)
|
|
182
|
-
throw
|
|
183
|
-
const { data: p, error:
|
|
180
|
+
throw w({ statusCode: 400, statusMessage: "No GA4 Property ID configured for this module." });
|
|
181
|
+
const { data: p, error: h } = await a.from("integrations").select("config").eq("id", i).single();
|
|
184
182
|
let C = p?.config;
|
|
185
|
-
if (
|
|
186
|
-
const { data: q, error:
|
|
187
|
-
if (
|
|
188
|
-
throw
|
|
183
|
+
if (h || !C) {
|
|
184
|
+
const { data: q, error: U } = await a.from("agency_integrations").select("config").eq("id", i).single();
|
|
185
|
+
if (U || !q?.config)
|
|
186
|
+
throw w({ statusCode: 500, statusMessage: "Failed to load Google Service Account credentials." });
|
|
189
187
|
C = q.config;
|
|
190
188
|
}
|
|
191
|
-
const
|
|
189
|
+
const k = R(C.clientEmail), P = R(C.privateKey), S = R(C.projectId);
|
|
192
190
|
return { accessToken: await A(
|
|
193
|
-
{ clientEmail:
|
|
191
|
+
{ clientEmail: k, privateKey: P, projectId: S },
|
|
194
192
|
F
|
|
195
193
|
), propertyId: r, siteUrl: u };
|
|
196
194
|
}
|
|
197
|
-
async function d(e,
|
|
198
|
-
const t = await fetch(`${M}/properties/${
|
|
195
|
+
async function d(e, a, n) {
|
|
196
|
+
const t = await fetch(`${M}/properties/${a}:runReport`, {
|
|
199
197
|
method: "POST",
|
|
200
198
|
headers: {
|
|
201
199
|
Authorization: `Bearer ${e}`,
|
|
@@ -205,17 +203,17 @@ function x(w) {
|
|
|
205
203
|
});
|
|
206
204
|
if (!t.ok) {
|
|
207
205
|
const s = await t.json().catch(() => ({}));
|
|
208
|
-
throw console.error("GA4 runReport failed:", s),
|
|
206
|
+
throw console.error("GA4 runReport failed:", s), w({
|
|
209
207
|
statusCode: t.status,
|
|
210
208
|
statusMessage: s?.error?.message || "GA4 API request failed"
|
|
211
209
|
});
|
|
212
210
|
}
|
|
213
211
|
return t.json();
|
|
214
212
|
}
|
|
215
|
-
|
|
213
|
+
g.get(
|
|
216
214
|
"/report",
|
|
217
215
|
y(async (e) => {
|
|
218
|
-
const { accessToken:
|
|
216
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = s.match(/^(\d+)daysAgo$/), i = r ? parseInt(r[1], 10) : 30, u = `${i * 2}daysAgo`, p = `${i + 1}daysAgo`, h = [
|
|
219
217
|
{ name: "sessions" },
|
|
220
218
|
{ name: "totalUsers" },
|
|
221
219
|
{ name: "screenPageViews" },
|
|
@@ -226,38 +224,38 @@ function x(w) {
|
|
|
226
224
|
{ name: "sessionsPerUser" },
|
|
227
225
|
{ name: "screenPageViewsPerSession" }
|
|
228
226
|
];
|
|
229
|
-
let C,
|
|
227
|
+
let C, k = !0;
|
|
230
228
|
try {
|
|
231
|
-
C = await d(
|
|
229
|
+
C = await d(a, n, {
|
|
232
230
|
dateRanges: [
|
|
233
|
-
{ startDate: s, endDate:
|
|
231
|
+
{ startDate: s, endDate: o, name: "current" },
|
|
234
232
|
{ startDate: u, endDate: p, name: "previous" }
|
|
235
233
|
],
|
|
236
234
|
dimensions: [{ name: "date" }],
|
|
237
|
-
metrics:
|
|
235
|
+
metrics: h,
|
|
238
236
|
metricAggregations: ["TOTAL"],
|
|
239
237
|
orderBys: [{ dimension: { dimensionName: "date" } }]
|
|
240
238
|
});
|
|
241
239
|
} catch {
|
|
242
|
-
|
|
243
|
-
dateRanges: [{ startDate: s, endDate:
|
|
240
|
+
k = !1, C = await d(a, n, {
|
|
241
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
244
242
|
dimensions: [{ name: "date" }],
|
|
245
|
-
metrics:
|
|
243
|
+
metrics: h,
|
|
246
244
|
metricAggregations: ["TOTAL"],
|
|
247
245
|
orderBys: [{ dimension: { dimensionName: "date" } }]
|
|
248
246
|
});
|
|
249
247
|
}
|
|
250
|
-
return V(C,
|
|
248
|
+
return V(C, k);
|
|
251
249
|
})
|
|
252
|
-
),
|
|
250
|
+
), g.get(
|
|
253
251
|
"/realtime",
|
|
254
252
|
y(async (e) => {
|
|
255
|
-
const { accessToken:
|
|
253
|
+
const { accessToken: a, propertyId: n } = await m(e), t = await fetch(
|
|
256
254
|
`${M}/properties/${n}:runRealtimeReport`,
|
|
257
255
|
{
|
|
258
256
|
method: "POST",
|
|
259
257
|
headers: {
|
|
260
|
-
Authorization: `Bearer ${
|
|
258
|
+
Authorization: `Bearer ${a}`,
|
|
261
259
|
"Content-Type": "application/json"
|
|
262
260
|
},
|
|
263
261
|
body: JSON.stringify({
|
|
@@ -270,22 +268,22 @@ function x(w) {
|
|
|
270
268
|
);
|
|
271
269
|
if (!t.ok) {
|
|
272
270
|
const i = await t.json().catch(() => ({}));
|
|
273
|
-
throw
|
|
271
|
+
throw w({ statusCode: t.status, statusMessage: i?.error?.message || "Realtime API failed" });
|
|
274
272
|
}
|
|
275
|
-
const s = await t.json(),
|
|
273
|
+
const s = await t.json(), o = (s?.rows || []).reduce(
|
|
276
274
|
(i, u) => i + parseInt(u.metricValues?.[0]?.value || "0", 10),
|
|
277
275
|
0
|
|
278
276
|
), r = (s?.rows || []).map((i) => ({
|
|
279
277
|
page: i.dimensionValues?.[0]?.value || "(not set)",
|
|
280
278
|
activeUsers: parseInt(i.metricValues?.[0]?.value || "0", 10)
|
|
281
279
|
}));
|
|
282
|
-
return { activeUsers:
|
|
280
|
+
return { activeUsers: o, activePages: r };
|
|
283
281
|
})
|
|
284
|
-
),
|
|
282
|
+
), g.get(
|
|
285
283
|
"/top-pages",
|
|
286
284
|
y(async (e) => {
|
|
287
|
-
const { accessToken:
|
|
288
|
-
dateRanges: [{ startDate: s, endDate:
|
|
285
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = parseInt(t.limit || "10", 10), i = await d(a, n, {
|
|
286
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
289
287
|
dimensions: [{ name: "pagePath" }],
|
|
290
288
|
metrics: [
|
|
291
289
|
{ name: "screenPageViews" },
|
|
@@ -297,21 +295,21 @@ function x(w) {
|
|
|
297
295
|
// fetch extra to account for duplicates before aggregation
|
|
298
296
|
}), u = I(i, "pagePath"), p = /* @__PURE__ */ new Map();
|
|
299
297
|
for (const C of u.rows) {
|
|
300
|
-
const
|
|
298
|
+
const k = C.pagePath.toLowerCase().replace(/\/+$/, ""), P = p.get(k);
|
|
301
299
|
if (P) {
|
|
302
300
|
P.screenPageViews += C.screenPageViews || 0, P.totalUsers += C.totalUsers || 0;
|
|
303
|
-
const
|
|
304
|
-
|
|
301
|
+
const S = P.screenPageViews;
|
|
302
|
+
S > 0 && (P.averageSessionDuration = (P.averageSessionDuration * (S - (C.screenPageViews || 0)) + (C.averageSessionDuration || 0) * (C.screenPageViews || 0)) / S);
|
|
305
303
|
} else
|
|
306
|
-
p.set(
|
|
304
|
+
p.set(k, { ...C });
|
|
307
305
|
}
|
|
308
|
-
return { rows: [...p.values()].sort((C,
|
|
306
|
+
return { rows: [...p.values()].sort((C, k) => (k.screenPageViews || 0) - (C.screenPageViews || 0)).slice(0, r), rowCount: u.rowCount };
|
|
309
307
|
})
|
|
310
|
-
),
|
|
308
|
+
), g.get(
|
|
311
309
|
"/top-sources",
|
|
312
310
|
y(async (e) => {
|
|
313
|
-
const { accessToken:
|
|
314
|
-
dateRanges: [{ startDate: s, endDate:
|
|
311
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
312
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
315
313
|
dimensions: [{ name: "sessionSource" }],
|
|
316
314
|
metrics: [
|
|
317
315
|
{ name: "sessions" },
|
|
@@ -322,11 +320,11 @@ function x(w) {
|
|
|
322
320
|
});
|
|
323
321
|
return I(r, "sessionSource");
|
|
324
322
|
})
|
|
325
|
-
),
|
|
323
|
+
), g.get(
|
|
326
324
|
"/devices",
|
|
327
325
|
y(async (e) => {
|
|
328
|
-
const { accessToken:
|
|
329
|
-
dateRanges: [{ startDate: s, endDate:
|
|
326
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
327
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
330
328
|
dimensions: [{ name: "deviceCategory" }],
|
|
331
329
|
metrics: [
|
|
332
330
|
{ name: "sessions" },
|
|
@@ -336,11 +334,11 @@ function x(w) {
|
|
|
336
334
|
});
|
|
337
335
|
return I(r, "deviceCategory");
|
|
338
336
|
})
|
|
339
|
-
),
|
|
337
|
+
), g.get(
|
|
340
338
|
"/countries",
|
|
341
339
|
y(async (e) => {
|
|
342
|
-
const { accessToken:
|
|
343
|
-
dateRanges: [{ startDate: s, endDate:
|
|
340
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
341
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
344
342
|
dimensions: [{ name: "country" }],
|
|
345
343
|
metrics: [
|
|
346
344
|
{ name: "sessions" },
|
|
@@ -351,11 +349,11 @@ function x(w) {
|
|
|
351
349
|
});
|
|
352
350
|
return I(r, "country");
|
|
353
351
|
})
|
|
354
|
-
),
|
|
352
|
+
), g.get(
|
|
355
353
|
"/acquisition/channels",
|
|
356
354
|
y(async (e) => {
|
|
357
|
-
const { accessToken:
|
|
358
|
-
dateRanges: [{ startDate: s, endDate:
|
|
355
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
356
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
359
357
|
dimensions: [{ name: "sessionDefaultChannelGroup" }],
|
|
360
358
|
metrics: [
|
|
361
359
|
{ name: "sessions" },
|
|
@@ -371,11 +369,11 @@ function x(w) {
|
|
|
371
369
|
});
|
|
372
370
|
return I(r, "sessionDefaultChannelGroup");
|
|
373
371
|
})
|
|
374
|
-
),
|
|
372
|
+
), g.get(
|
|
375
373
|
"/acquisition/source-medium",
|
|
376
374
|
y(async (e) => {
|
|
377
|
-
const { accessToken:
|
|
378
|
-
dateRanges: [{ startDate: s, endDate:
|
|
375
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
376
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
379
377
|
dimensions: [{ name: "sessionSourceMedium" }],
|
|
380
378
|
metrics: [
|
|
381
379
|
{ name: "sessions" },
|
|
@@ -390,11 +388,11 @@ function x(w) {
|
|
|
390
388
|
});
|
|
391
389
|
return I(r, "sessionSourceMedium");
|
|
392
390
|
})
|
|
393
|
-
),
|
|
391
|
+
), g.get(
|
|
394
392
|
"/acquisition/referrals",
|
|
395
393
|
y(async (e) => {
|
|
396
|
-
const { accessToken:
|
|
397
|
-
dateRanges: [{ startDate: s, endDate:
|
|
394
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
395
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
398
396
|
dimensions: [{ name: "sessionSource" }],
|
|
399
397
|
dimensionFilter: {
|
|
400
398
|
filter: {
|
|
@@ -413,11 +411,11 @@ function x(w) {
|
|
|
413
411
|
});
|
|
414
412
|
return I(r, "sessionSource");
|
|
415
413
|
})
|
|
416
|
-
),
|
|
414
|
+
), g.get(
|
|
417
415
|
"/acquisition/campaigns",
|
|
418
416
|
y(async (e) => {
|
|
419
|
-
const { accessToken:
|
|
420
|
-
dateRanges: [{ startDate: s, endDate:
|
|
417
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
418
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
421
419
|
dimensions: [{ name: "sessionCampaignName" }],
|
|
422
420
|
dimensionFilter: {
|
|
423
421
|
notExpression: {
|
|
@@ -438,11 +436,11 @@ function x(w) {
|
|
|
438
436
|
});
|
|
439
437
|
return I(r, "sessionCampaignName");
|
|
440
438
|
})
|
|
441
|
-
),
|
|
439
|
+
), g.get(
|
|
442
440
|
"/content/all-pages",
|
|
443
441
|
y(async (e) => {
|
|
444
|
-
const { accessToken:
|
|
445
|
-
dateRanges: [{ startDate: s, endDate:
|
|
442
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = parseInt(t.limit || "50", 10), i = await d(a, n, {
|
|
443
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
446
444
|
dimensions: [{ name: "pagePath" }],
|
|
447
445
|
metrics: [
|
|
448
446
|
{ name: "screenPageViews" },
|
|
@@ -458,11 +456,11 @@ function x(w) {
|
|
|
458
456
|
});
|
|
459
457
|
return I(i, "pagePath");
|
|
460
458
|
})
|
|
461
|
-
),
|
|
459
|
+
), g.get(
|
|
462
460
|
"/content/landing-pages",
|
|
463
461
|
y(async (e) => {
|
|
464
|
-
const { accessToken:
|
|
465
|
-
dateRanges: [{ startDate: s, endDate:
|
|
462
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
463
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
466
464
|
dimensions: [{ name: "landingPagePlusQueryString" }],
|
|
467
465
|
metrics: [
|
|
468
466
|
{ name: "sessions" },
|
|
@@ -477,11 +475,11 @@ function x(w) {
|
|
|
477
475
|
});
|
|
478
476
|
return I(r, "landingPagePlusQueryString");
|
|
479
477
|
})
|
|
480
|
-
),
|
|
478
|
+
), g.get(
|
|
481
479
|
"/content/exit-pages",
|
|
482
480
|
y(async (e) => {
|
|
483
|
-
const { accessToken:
|
|
484
|
-
dateRanges: [{ startDate: s, endDate:
|
|
481
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
482
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
485
483
|
dimensions: [{ name: "pagePath" }],
|
|
486
484
|
metrics: [
|
|
487
485
|
{ name: "sessions" },
|
|
@@ -497,48 +495,45 @@ function x(w) {
|
|
|
497
495
|
exitRate: u.bounceRate || 0
|
|
498
496
|
})), i;
|
|
499
497
|
})
|
|
500
|
-
),
|
|
498
|
+
), g.get(
|
|
501
499
|
"/content/search-terms",
|
|
502
500
|
y(async (e) => {
|
|
503
|
-
const { accessToken:
|
|
501
|
+
const { accessToken: a, propertyId: n, siteUrl: t } = await m(e), s = D(e), o = s.startDate || "30daysAgo", r = s.endDate || "today";
|
|
504
502
|
if (t)
|
|
505
503
|
try {
|
|
506
|
-
const p = `${
|
|
507
|
-
console.log("[GA Module] Attempting Search Console query for site:", t);
|
|
508
|
-
const D = await fetch(
|
|
504
|
+
const p = `${b}/sites/${encodeURIComponent(t)}/searchAnalytics/query`, h = await fetch(
|
|
509
505
|
p,
|
|
510
506
|
{
|
|
511
507
|
method: "POST",
|
|
512
508
|
headers: {
|
|
513
|
-
Authorization: `Bearer ${
|
|
509
|
+
Authorization: `Bearer ${a}`,
|
|
514
510
|
"Content-Type": "application/json"
|
|
515
511
|
},
|
|
516
512
|
body: JSON.stringify({
|
|
517
|
-
startDate: c(
|
|
513
|
+
startDate: c(o),
|
|
518
514
|
endDate: c(r),
|
|
519
515
|
dimensions: ["query"],
|
|
520
516
|
rowLimit: 30
|
|
521
517
|
})
|
|
522
518
|
}
|
|
523
519
|
);
|
|
524
|
-
if (
|
|
525
|
-
const
|
|
520
|
+
if (h.ok) {
|
|
521
|
+
const k = ((await h.json()).rows || []).map((P) => ({
|
|
526
522
|
query: P.keys[0],
|
|
527
523
|
clicks: P.clicks,
|
|
528
524
|
impressions: P.impressions,
|
|
529
525
|
ctr: P.ctr,
|
|
530
526
|
position: P.position
|
|
531
527
|
}));
|
|
532
|
-
if (
|
|
533
|
-
return
|
|
534
|
-
rows:
|
|
535
|
-
rowCount:
|
|
528
|
+
if (k.length > 0)
|
|
529
|
+
return {
|
|
530
|
+
rows: k,
|
|
531
|
+
rowCount: k.length,
|
|
536
532
|
source: "search_console"
|
|
537
533
|
};
|
|
538
|
-
console.log("[GA Module] Search Console returned 0 rows, falling through");
|
|
539
534
|
} else {
|
|
540
|
-
const C = await
|
|
541
|
-
console.error(`[GA Module] Search Console API error (${
|
|
535
|
+
const C = await h.text().catch(() => "");
|
|
536
|
+
console.error(`[GA Module] Search Console API error (${h.status}):`, C);
|
|
542
537
|
}
|
|
543
538
|
} catch (p) {
|
|
544
539
|
console.error("[GA Module] Search Console request failed:", p?.message || p);
|
|
@@ -546,8 +541,8 @@ function x(w) {
|
|
|
546
541
|
else
|
|
547
542
|
console.log("[GA Module] No siteUrl configured, skipping Search Console");
|
|
548
543
|
try {
|
|
549
|
-
const p = await d(
|
|
550
|
-
dateRanges: [{ startDate:
|
|
544
|
+
const p = await d(a, n, {
|
|
545
|
+
dateRanges: [{ startDate: o, endDate: r }],
|
|
551
546
|
dimensions: [{ name: "sessionGoogleAdsQuery" }],
|
|
552
547
|
metrics: [
|
|
553
548
|
{ name: "sessions" },
|
|
@@ -578,13 +573,13 @@ function x(w) {
|
|
|
578
573
|
},
|
|
579
574
|
orderBys: [{ metric: { metricName: "sessions" }, desc: !0 }],
|
|
580
575
|
limit: 30
|
|
581
|
-
}),
|
|
582
|
-
if (
|
|
583
|
-
return { ...
|
|
576
|
+
}), h = I(p, "sessionGoogleAdsQuery");
|
|
577
|
+
if (h.rows.length > 0)
|
|
578
|
+
return { ...h, source: "google_ads" };
|
|
584
579
|
} catch {
|
|
585
580
|
}
|
|
586
|
-
const i = await d(
|
|
587
|
-
dateRanges: [{ startDate:
|
|
581
|
+
const i = await d(a, n, {
|
|
582
|
+
dateRanges: [{ startDate: o, endDate: r }],
|
|
588
583
|
dimensions: [{ name: "landingPagePlusQueryString" }],
|
|
589
584
|
metrics: [
|
|
590
585
|
{ name: "sessions" },
|
|
@@ -619,11 +614,11 @@ function x(w) {
|
|
|
619
614
|
});
|
|
620
615
|
return { ...I(i, "landingPagePlusQueryString"), source: "organic_landing_pages" };
|
|
621
616
|
})
|
|
622
|
-
),
|
|
617
|
+
), g.get(
|
|
623
618
|
"/audience/overview",
|
|
624
619
|
y(async (e) => {
|
|
625
|
-
const { accessToken:
|
|
626
|
-
dateRanges: [{ startDate: s, endDate:
|
|
620
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
621
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
627
622
|
dimensions: [{ name: "newVsReturning" }],
|
|
628
623
|
metrics: [
|
|
629
624
|
{ name: "totalUsers" },
|
|
@@ -636,11 +631,11 @@ function x(w) {
|
|
|
636
631
|
});
|
|
637
632
|
return I(r, "newVsReturning");
|
|
638
633
|
})
|
|
639
|
-
),
|
|
634
|
+
), g.get(
|
|
640
635
|
"/audience/technology",
|
|
641
636
|
y(async (e) => {
|
|
642
|
-
const { accessToken:
|
|
643
|
-
dateRanges: [{ startDate: s, endDate:
|
|
637
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = t.dimension || "browser", u = ["browser", "operatingSystem", "screenResolution"].includes(r) ? r : "browser", p = await d(a, n, {
|
|
638
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
644
639
|
dimensions: [{ name: u }],
|
|
645
640
|
metrics: [
|
|
646
641
|
{ name: "totalUsers" },
|
|
@@ -652,11 +647,11 @@ function x(w) {
|
|
|
652
647
|
});
|
|
653
648
|
return I(p, u);
|
|
654
649
|
})
|
|
655
|
-
),
|
|
650
|
+
), g.get(
|
|
656
651
|
"/audience/languages",
|
|
657
652
|
y(async (e) => {
|
|
658
|
-
const { accessToken:
|
|
659
|
-
dateRanges: [{ startDate: s, endDate:
|
|
653
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
654
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
660
655
|
dimensions: [{ name: "language" }],
|
|
661
656
|
metrics: [
|
|
662
657
|
{ name: "totalUsers" },
|
|
@@ -667,11 +662,11 @@ function x(w) {
|
|
|
667
662
|
});
|
|
668
663
|
return I(r, "language");
|
|
669
664
|
})
|
|
670
|
-
),
|
|
665
|
+
), g.get(
|
|
671
666
|
"/audience/hours",
|
|
672
667
|
y(async (e) => {
|
|
673
|
-
const { accessToken:
|
|
674
|
-
dateRanges: [{ startDate: s, endDate:
|
|
668
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
669
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
675
670
|
dimensions: [{ name: "dayOfWeekName" }, { name: "hour" }],
|
|
676
671
|
metrics: [{ name: "sessions" }],
|
|
677
672
|
orderBys: [
|
|
@@ -681,13 +676,13 @@ function x(w) {
|
|
|
681
676
|
limit: 168
|
|
682
677
|
// 7 days × 24 hours
|
|
683
678
|
});
|
|
684
|
-
return
|
|
679
|
+
return T(r, ["dayOfWeekName", "hour"]);
|
|
685
680
|
})
|
|
686
|
-
),
|
|
681
|
+
), g.get(
|
|
687
682
|
"/audience/cities",
|
|
688
683
|
y(async (e) => {
|
|
689
|
-
const { accessToken:
|
|
690
|
-
dateRanges: [{ startDate: s, endDate:
|
|
684
|
+
const { accessToken: a, propertyId: n } = await m(e), t = D(e), s = t.startDate || "30daysAgo", o = t.endDate || "today", r = await d(a, n, {
|
|
685
|
+
dateRanges: [{ startDate: s, endDate: o }],
|
|
691
686
|
dimensions: [{ name: "city" }, { name: "country" }],
|
|
692
687
|
metrics: [
|
|
693
688
|
{ name: "totalUsers" },
|
|
@@ -704,14 +699,14 @@ function x(w) {
|
|
|
704
699
|
orderBys: [{ metric: { metricName: "totalUsers" }, desc: !0 }],
|
|
705
700
|
limit: 20
|
|
706
701
|
});
|
|
707
|
-
return
|
|
702
|
+
return T(r, ["city", "country"]);
|
|
708
703
|
})
|
|
709
704
|
);
|
|
710
705
|
function c(e) {
|
|
711
|
-
const
|
|
712
|
-
if (
|
|
706
|
+
const a = e.match(/^(\d+)daysAgo$/);
|
|
707
|
+
if (a) {
|
|
713
708
|
const n = /* @__PURE__ */ new Date();
|
|
714
|
-
return n.setDate(n.getDate() - parseInt(
|
|
709
|
+
return n.setDate(n.getDate() - parseInt(a[1], 10)), n.toISOString().slice(0, 10);
|
|
715
710
|
}
|
|
716
711
|
if (e === "today") return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
717
712
|
if (e === "yesterday") {
|
|
@@ -720,8 +715,8 @@ function x(w) {
|
|
|
720
715
|
}
|
|
721
716
|
return e;
|
|
722
717
|
}
|
|
723
|
-
async function
|
|
724
|
-
const t = `${
|
|
718
|
+
async function l(e, a, n) {
|
|
719
|
+
const t = `${b}/sites/${encodeURIComponent(a)}/searchAnalytics/query`, s = await fetch(t, {
|
|
725
720
|
method: "POST",
|
|
726
721
|
headers: {
|
|
727
722
|
Authorization: `Bearer ${e}`,
|
|
@@ -730,23 +725,23 @@ function x(w) {
|
|
|
730
725
|
body: JSON.stringify(n)
|
|
731
726
|
});
|
|
732
727
|
if (!s.ok) {
|
|
733
|
-
const
|
|
734
|
-
throw
|
|
728
|
+
const o = await s.json().catch(() => ({}));
|
|
729
|
+
throw w({
|
|
735
730
|
statusCode: s.status,
|
|
736
|
-
statusMessage:
|
|
731
|
+
statusMessage: o?.error?.message || "Search Console API request failed"
|
|
737
732
|
});
|
|
738
733
|
}
|
|
739
734
|
return s.json();
|
|
740
735
|
}
|
|
741
|
-
return
|
|
736
|
+
return g.get(
|
|
742
737
|
"/seo/keywords",
|
|
743
738
|
y(async (e) => {
|
|
744
|
-
const { accessToken:
|
|
739
|
+
const { accessToken: a, siteUrl: n } = await m(e);
|
|
745
740
|
if (!n)
|
|
746
|
-
throw
|
|
747
|
-
const t =
|
|
741
|
+
throw w({ statusCode: 400, statusMessage: "Search Console Site URL is not configured. Add it in module settings." });
|
|
742
|
+
const t = D(e), s = c(t.startDate || "30daysAgo"), o = c(t.endDate || "today"), r = Math.min(parseInt(t.limit) || 50, 100), i = await l(a, n, {
|
|
748
743
|
startDate: s,
|
|
749
|
-
endDate:
|
|
744
|
+
endDate: o,
|
|
750
745
|
dimensions: ["query"],
|
|
751
746
|
rowLimit: r
|
|
752
747
|
});
|
|
@@ -761,15 +756,15 @@ function x(w) {
|
|
|
761
756
|
rowCount: i.rows?.length || 0
|
|
762
757
|
};
|
|
763
758
|
})
|
|
764
|
-
),
|
|
759
|
+
), g.get(
|
|
765
760
|
"/seo/pages",
|
|
766
761
|
y(async (e) => {
|
|
767
|
-
const { accessToken:
|
|
762
|
+
const { accessToken: a, siteUrl: n } = await m(e);
|
|
768
763
|
if (!n)
|
|
769
|
-
throw
|
|
770
|
-
const t =
|
|
764
|
+
throw w({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
|
|
765
|
+
const t = D(e), s = c(t.startDate || "30daysAgo"), o = c(t.endDate || "today"), r = Math.min(parseInt(t.limit) || 50, 100), i = await l(a, n, {
|
|
771
766
|
startDate: s,
|
|
772
|
-
endDate:
|
|
767
|
+
endDate: o,
|
|
773
768
|
dimensions: ["page"],
|
|
774
769
|
rowLimit: r
|
|
775
770
|
});
|
|
@@ -784,15 +779,15 @@ function x(w) {
|
|
|
784
779
|
rowCount: i.rows?.length || 0
|
|
785
780
|
};
|
|
786
781
|
})
|
|
787
|
-
),
|
|
782
|
+
), g.get(
|
|
788
783
|
"/seo/trends",
|
|
789
784
|
y(async (e) => {
|
|
790
|
-
const { accessToken:
|
|
785
|
+
const { accessToken: a, siteUrl: n } = await m(e);
|
|
791
786
|
if (!n)
|
|
792
|
-
throw
|
|
793
|
-
const t =
|
|
787
|
+
throw w({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
|
|
788
|
+
const t = D(e), s = c(t.startDate || "30daysAgo"), o = c(t.endDate || "today"), i = ((await l(a, n, {
|
|
794
789
|
startDate: s,
|
|
795
|
-
endDate:
|
|
790
|
+
endDate: o,
|
|
796
791
|
dimensions: ["date"],
|
|
797
792
|
rowLimit: 500
|
|
798
793
|
})).rows || []).map((p) => ({
|
|
@@ -801,24 +796,24 @@ function x(w) {
|
|
|
801
796
|
impressions: p.impressions,
|
|
802
797
|
ctr: p.ctr,
|
|
803
798
|
position: p.position
|
|
804
|
-
})).sort((p,
|
|
805
|
-
(p,
|
|
806
|
-
clicks: p.clicks +
|
|
807
|
-
impressions: p.impressions +
|
|
799
|
+
})).sort((p, h) => p.date.localeCompare(h.date)), u = i.reduce(
|
|
800
|
+
(p, h) => ({
|
|
801
|
+
clicks: p.clicks + h.clicks,
|
|
802
|
+
impressions: p.impressions + h.impressions
|
|
808
803
|
}),
|
|
809
804
|
{ clicks: 0, impressions: 0 }
|
|
810
805
|
);
|
|
811
|
-
return u.ctr = u.impressions > 0 ? u.clicks / u.impressions : 0, u.avgPosition = i.length > 0 ? i.reduce((p,
|
|
806
|
+
return u.ctr = u.impressions > 0 ? u.clicks / u.impressions : 0, u.avgPosition = i.length > 0 ? i.reduce((p, h) => p + h.position, 0) / i.length : 0, { rows: i, totals: u, rowCount: i.length };
|
|
812
807
|
})
|
|
813
|
-
),
|
|
808
|
+
), g.get(
|
|
814
809
|
"/seo/query-pages",
|
|
815
810
|
y(async (e) => {
|
|
816
|
-
const { accessToken:
|
|
811
|
+
const { accessToken: a, siteUrl: n } = await m(e);
|
|
817
812
|
if (!n)
|
|
818
|
-
throw
|
|
819
|
-
const t =
|
|
813
|
+
throw w({ statusCode: 400, statusMessage: "Search Console Site URL is not configured." });
|
|
814
|
+
const t = D(e), s = c(t.startDate || "30daysAgo"), o = c(t.endDate || "today"), r = await l(a, n, {
|
|
820
815
|
startDate: s,
|
|
821
|
-
endDate:
|
|
816
|
+
endDate: o,
|
|
822
817
|
dimensions: ["query", "page"],
|
|
823
818
|
rowLimit: 100
|
|
824
819
|
});
|
|
@@ -834,65 +829,106 @@ function x(w) {
|
|
|
834
829
|
rowCount: r.rows?.length || 0
|
|
835
830
|
};
|
|
836
831
|
})
|
|
837
|
-
),
|
|
832
|
+
), g.handler;
|
|
838
833
|
}
|
|
839
|
-
function V(
|
|
840
|
-
const A = (
|
|
841
|
-
(
|
|
842
|
-
const
|
|
843
|
-
if (!
|
|
844
|
-
const i = { date: `${
|
|
834
|
+
function V(f, R = !0) {
|
|
835
|
+
const A = (f.metricHeaders || []).map((s) => s.name), m = (f.dimensionHeaders || []).map((s) => s.name).indexOf("date"), d = [];
|
|
836
|
+
(f.rows || []).forEach((s) => {
|
|
837
|
+
const o = m >= 0 ? s.dimensionValues[m]?.value : s.dimensionValues[0]?.value;
|
|
838
|
+
if (!o || o.length < 8) return;
|
|
839
|
+
const i = { date: `${o.slice(0, 4)}-${o.slice(4, 6)}-${o.slice(6, 8)}` };
|
|
845
840
|
A.forEach((u, p) => {
|
|
846
841
|
i[u] = parseFloat(s.metricValues[p]?.value || "0");
|
|
847
842
|
}), d.push(i);
|
|
848
843
|
});
|
|
849
|
-
const c = {},
|
|
850
|
-
|
|
851
|
-
c[s] = parseFloat(
|
|
852
|
-
}) :
|
|
853
|
-
c[s] = parseFloat(
|
|
844
|
+
const c = {}, l = {};
|
|
845
|
+
f.totals && f.totals.length >= 2 ? A.forEach((s, o) => {
|
|
846
|
+
c[s] = parseFloat(f.totals[0]?.metricValues?.[o]?.value || "0"), l[s] = parseFloat(f.totals[1]?.metricValues?.[o]?.value || "0");
|
|
847
|
+
}) : f.totals && f.totals.length === 1 && A.forEach((s, o) => {
|
|
848
|
+
c[s] = parseFloat(f.totals[0]?.metricValues?.[o]?.value || "0");
|
|
854
849
|
});
|
|
855
850
|
const e = {};
|
|
856
851
|
A.forEach((s) => {
|
|
857
|
-
const
|
|
858
|
-
r !== void 0 && r !== 0 ? e[s] = (
|
|
852
|
+
const o = c[s] || 0, r = l[s];
|
|
853
|
+
r !== void 0 && r !== 0 ? e[s] = (o - r) / r * 100 : e[s] = null;
|
|
859
854
|
});
|
|
860
|
-
const
|
|
855
|
+
const a = /* @__PURE__ */ new Map();
|
|
861
856
|
for (const s of d)
|
|
862
|
-
|
|
863
|
-
const n = Array.from(
|
|
857
|
+
a.has(s.date) || a.set(s.date, s);
|
|
858
|
+
const n = Array.from(a.values()).sort((s, o) => s.date.localeCompare(o.date)), t = R && f.totals && f.totals.length >= 2 ? n.slice(-Math.ceil(n.length / 2)) : n;
|
|
864
859
|
return {
|
|
865
860
|
rows: t,
|
|
866
861
|
totals: c,
|
|
867
|
-
previousTotals:
|
|
862
|
+
previousTotals: l,
|
|
868
863
|
changes: e,
|
|
869
864
|
rowCount: t.length
|
|
870
865
|
};
|
|
871
866
|
}
|
|
872
|
-
function I(
|
|
873
|
-
const A = (
|
|
867
|
+
function I(f, R) {
|
|
868
|
+
const A = (f.metricHeaders || []).map((m) => m.name), g = (f.rows || []).map((m) => {
|
|
874
869
|
const d = {
|
|
875
|
-
[
|
|
870
|
+
[R]: m.dimensionValues[0].value
|
|
876
871
|
};
|
|
877
|
-
return A.forEach((c,
|
|
878
|
-
d[c] = parseFloat(m.metricValues[
|
|
872
|
+
return A.forEach((c, l) => {
|
|
873
|
+
d[c] = parseFloat(m.metricValues[l].value);
|
|
879
874
|
}), d;
|
|
880
875
|
});
|
|
881
|
-
return { rows:
|
|
876
|
+
return { rows: g, rowCount: f.rowCount || g.length };
|
|
882
877
|
}
|
|
883
|
-
function
|
|
884
|
-
const A = (
|
|
878
|
+
function T(f, R) {
|
|
879
|
+
const A = (f.metricHeaders || []).map((m) => m.name), g = (f.rows || []).map((m) => {
|
|
885
880
|
const d = {};
|
|
886
|
-
return
|
|
887
|
-
d[c] = m.dimensionValues[
|
|
888
|
-
}), A.forEach((c,
|
|
889
|
-
d[c] = parseFloat(m.metricValues[
|
|
881
|
+
return R.forEach((c, l) => {
|
|
882
|
+
d[c] = m.dimensionValues[l]?.value || "";
|
|
883
|
+
}), A.forEach((c, l) => {
|
|
884
|
+
d[c] = parseFloat(m.metricValues[l].value);
|
|
890
885
|
}), d;
|
|
891
886
|
});
|
|
892
|
-
return { rows:
|
|
887
|
+
return { rows: g, rowCount: f.rowCount || g.length };
|
|
888
|
+
}
|
|
889
|
+
function j(f) {
|
|
890
|
+
const { decrypt: R } = f, A = v();
|
|
891
|
+
async function g(m) {
|
|
892
|
+
const { supabase: d, instanceId: c } = m.context.module, { data: l, error: e } = await d.from("project_modules").select("config").eq("id", c).single();
|
|
893
|
+
if (e || !l?.config)
|
|
894
|
+
throw w({ statusCode: 500, statusMessage: "Failed to load module config." });
|
|
895
|
+
const a = l.config, n = a.githubIntegration, t = a.githubRepo, s = a.githubOwner;
|
|
896
|
+
if (!n || !t || !s)
|
|
897
|
+
throw w({ statusCode: 400, statusMessage: "No GitHub integration configured for this module." });
|
|
898
|
+
const { data: o, error: r } = await d.from("integrations").select("config").eq("id", n).single();
|
|
899
|
+
let i = o?.config;
|
|
900
|
+
if (r || !i) {
|
|
901
|
+
const { data: p, error: h } = await d.from("agency_integrations").select("config").eq("id", n).single();
|
|
902
|
+
if (h || !p?.config)
|
|
903
|
+
throw w({ statusCode: 500, statusMessage: "Failed to load Github credentials." });
|
|
904
|
+
i = p.config;
|
|
905
|
+
}
|
|
906
|
+
return { token: R(i.token), repo: t, owner: s };
|
|
907
|
+
}
|
|
908
|
+
return A.post(
|
|
909
|
+
"/github/deploy",
|
|
910
|
+
y(async (m) => {
|
|
911
|
+
try {
|
|
912
|
+
const { token: d, repo: c, owner: l } = await g(m);
|
|
913
|
+
await fetch(`https://api.github.com/repos/${l}/${c}/dispatches`, {
|
|
914
|
+
method: "POST",
|
|
915
|
+
headers: {
|
|
916
|
+
Authorization: `Bearer ${d}`,
|
|
917
|
+
Accept: "application/vnd.github+json"
|
|
918
|
+
},
|
|
919
|
+
body: JSON.stringify({
|
|
920
|
+
event_type: "deploy-site"
|
|
921
|
+
})
|
|
922
|
+
});
|
|
923
|
+
} catch (d) {
|
|
924
|
+
throw console.error("Error triggering GitHub deployment:", d), w({ statusCode: 500, statusMessage: "Failed to trigger deployment." });
|
|
925
|
+
}
|
|
926
|
+
})
|
|
927
|
+
), A.handler;
|
|
893
928
|
}
|
|
894
929
|
export {
|
|
895
|
-
|
|
896
|
-
|
|
930
|
+
x as appointments,
|
|
931
|
+
j as contentManager,
|
|
932
|
+
G as googleAnalytics,
|
|
897
933
|
$ as products
|
|
898
934
|
};
|