@gscdump/cloudflare 0.36.1 → 0.36.3
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/server-tail/index.mjs +26 -13
- package/package.json +5 -5
|
@@ -3,9 +3,13 @@ import { ARCHETYPE_EXECUTION_CLASS } from "@gscdump/contracts/archetypes";
|
|
|
3
3
|
import { err, ok, unwrapResult } from "gscdump/result";
|
|
4
4
|
import { SEARCH_TYPE_INT } from "@gscdump/engine/iceberg";
|
|
5
5
|
const TABLE_PLACEHOLDER = "{{TABLE}}";
|
|
6
|
+
const FACT_ALIAS = "fact";
|
|
7
|
+
function factTableRef() {
|
|
8
|
+
return `${TABLE_PLACEHOLDER} AS ${FACT_ALIAS}`;
|
|
9
|
+
}
|
|
6
10
|
function dimColumn(dim) {
|
|
7
11
|
if (dim === "page") return "url";
|
|
8
|
-
if (dim === "queryCanonical") return
|
|
12
|
+
if (dim === "queryCanonical") return `COALESCE((SELECT qd.query_canonical FROM query_dim qd WHERE qd.query = ${FACT_ALIAS}.query LIMIT 1), ${FACT_ALIAS}.query)`;
|
|
9
13
|
return dim;
|
|
10
14
|
}
|
|
11
15
|
function dimSelect(dim) {
|
|
@@ -20,6 +24,15 @@ function tableForDimensions(dims) {
|
|
|
20
24
|
if (set.has("device")) return "dates";
|
|
21
25
|
return "pages";
|
|
22
26
|
}
|
|
27
|
+
function tableForTopNBreakdown(q) {
|
|
28
|
+
const dims = [q.dimension];
|
|
29
|
+
for (const facet of q.facets ?? []) {
|
|
30
|
+
const hasPage = q.dimension === "page" || facet.column === "page";
|
|
31
|
+
const hasQuery = q.dimension === "query" || q.dimension === "queryCanonical" || facet.column === "query" || facet.column === "queryCanonical";
|
|
32
|
+
if (hasPage && hasQuery) dims.push(facet.column);
|
|
33
|
+
}
|
|
34
|
+
return tableForDimensions(dims);
|
|
35
|
+
}
|
|
23
36
|
function metricExpr(metric) {
|
|
24
37
|
switch (metric) {
|
|
25
38
|
case "clicks": return "SUM(clicks) AS clicks";
|
|
@@ -149,7 +162,7 @@ function buildSiteDailyTimeseries(q, pruned, mode) {
|
|
|
149
162
|
return {
|
|
150
163
|
table: "dates",
|
|
151
164
|
params: w.params,
|
|
152
|
-
sql: `SELECT date, ${metrics} FROM ${
|
|
165
|
+
sql: `SELECT date, ${metrics} FROM ${factTableRef()} WHERE ${w.clause} GROUP BY date ORDER BY date ASC`
|
|
153
166
|
};
|
|
154
167
|
}
|
|
155
168
|
function buildEntityDailyTimeseries(q, pruned, mode) {
|
|
@@ -160,7 +173,7 @@ function buildEntityDailyTimeseries(q, pruned, mode) {
|
|
|
160
173
|
return {
|
|
161
174
|
table,
|
|
162
175
|
params: [...w.params, q.entity.value],
|
|
163
|
-
sql: `SELECT date, ${metrics} FROM ${
|
|
176
|
+
sql: `SELECT date, ${metrics} FROM ${factTableRef()} WHERE ${w.clause} AND ${col} = ? GROUP BY date ORDER BY date ASC`
|
|
164
177
|
};
|
|
165
178
|
}
|
|
166
179
|
function buildEntityDailySparkline(q, pruned, mode) {
|
|
@@ -172,11 +185,11 @@ function buildEntityDailySparkline(q, pruned, mode) {
|
|
|
172
185
|
return {
|
|
173
186
|
table,
|
|
174
187
|
params: w.params,
|
|
175
|
-
sql: `SELECT date, ${dimSelect(q.dimension)}, ${metricExpr(q.metric)} FROM ${
|
|
188
|
+
sql: `SELECT date, ${dimSelect(q.dimension)}, ${metricExpr(q.metric)} FROM ${factTableRef()} WHERE ${w.clause} AND ${col} IN (${inList}) GROUP BY date, ${col} ORDER BY date ASC`
|
|
176
189
|
};
|
|
177
190
|
}
|
|
178
191
|
function buildTopNBreakdown(q, pruned, mode) {
|
|
179
|
-
const table =
|
|
192
|
+
const table = tableForTopNBreakdown(q);
|
|
180
193
|
const w = partitionWhere(q, pruned, mode);
|
|
181
194
|
if (!q.orderBy || !q.orderBy.metric || !q.orderBy.dir) throw new Error(`[archetype-sql] top-n-breakdown requires orderBy.{metric,dir}, got: ${JSON.stringify(q.orderBy)}`);
|
|
182
195
|
const order = `${metricAlias(q.orderBy.metric)} ${q.orderBy.dir.toUpperCase()}`;
|
|
@@ -198,7 +211,7 @@ function buildTopNBreakdown(q, pruned, mode) {
|
|
|
198
211
|
const deviceSelects = (clause, ml) => DEVICE_SUFFIXES.map((suffix) => {
|
|
199
212
|
const source = deviceSource(suffix);
|
|
200
213
|
const metrics = ml.map((m) => metricExprForSource(m, source)).join(", ");
|
|
201
|
-
return `SELECT '${suffix.toUpperCase()}' AS device, ${metrics} FROM ${
|
|
214
|
+
return `SELECT '${suffix.toUpperCase()}' AS device, ${metrics} FROM ${factTableRef()} WHERE ${clause}`;
|
|
202
215
|
}).join(" UNION ALL ");
|
|
203
216
|
const inner = `SELECT COALESCE(c.device, p.device) AS device, ${metricList.map((m) => coalesceMetric(m, "c", m)).join(", ")}, ${STD_METRICS.map((m) => coalesceMetric(m, "p", prevAlias(m))).join(", ")} FROM cur c FULL OUTER JOIN prev p ON c.device = p.device`;
|
|
204
217
|
const sql = `WITH cur AS (${deviceSelects(w.clause, metricList)}), prev AS (${deviceSelects(wPrev.clause, STD_METRICS)}) SELECT * FROM (${inner}) t ORDER BY ${order} ${limit}${offset}`;
|
|
@@ -211,7 +224,7 @@ function buildTopNBreakdown(q, pruned, mode) {
|
|
|
211
224
|
const sql = `${DEVICE_SUFFIXES.map((suffix) => {
|
|
212
225
|
const source = deviceSource(suffix);
|
|
213
226
|
const metrics = metricList.map((m) => metricExprForSource(m, source)).join(", ");
|
|
214
|
-
return `SELECT '${suffix.toUpperCase()}' AS device, ${metrics} FROM ${
|
|
227
|
+
return `SELECT '${suffix.toUpperCase()}' AS device, ${metrics} FROM ${factTableRef()} WHERE ${w.clause}`;
|
|
215
228
|
}).join(" UNION ALL ")} ORDER BY ${order} ${limit}${offset}`;
|
|
216
229
|
return {
|
|
217
230
|
table,
|
|
@@ -235,7 +248,7 @@ function buildTopNBreakdown(q, pruned, mode) {
|
|
|
235
248
|
const moverWhere = q.movers ? `WHERE ${moverClause(q.movers).where} ` : "";
|
|
236
249
|
const outerOrder = q.movers ? moverOrderByAlias(q.movers) : order;
|
|
237
250
|
const inner = `SELECT COALESCE(c.k, p.k) AS ${q.dimension}, ${curCols}, ${prevCols}${variantOut}${totalCol} FROM cur c FULL OUTER JOIN prev p ON c.k = p.k ${moverWhere}`;
|
|
238
|
-
const sql = `WITH cur AS (SELECT ${col} AS k, ${curMetrics}${variantSel} FROM ${
|
|
251
|
+
const sql = `WITH cur AS (SELECT ${col} AS k, ${curMetrics}${variantSel} FROM ${factTableRef()} WHERE ${w.clause}${facet.sql} GROUP BY ${col}), prev AS (SELECT ${col} AS k, ${prevMetrics} FROM ${factTableRef()} WHERE ${wPrev.clause}${facet.sql} GROUP BY ${col}) SELECT * FROM (${inner}) t ORDER BY ${outerOrder} ${limit}${offset}`;
|
|
239
252
|
return {
|
|
240
253
|
table,
|
|
241
254
|
params: [
|
|
@@ -248,7 +261,7 @@ function buildTopNBreakdown(q, pruned, mode) {
|
|
|
248
261
|
};
|
|
249
262
|
}
|
|
250
263
|
const metrics = metricList.map(metricExpr).join(", ");
|
|
251
|
-
const sql = `SELECT ${dimSelect(q.dimension)}, ${metrics}${variantSel}${totalCol} FROM ${
|
|
264
|
+
const sql = `SELECT ${dimSelect(q.dimension)}, ${metrics}${variantSel}${totalCol} FROM ${factTableRef()} WHERE ${w.clause}${facet.sql} GROUP BY ${col} ORDER BY ${order} ${limit}${offset}`;
|
|
252
265
|
return {
|
|
253
266
|
table,
|
|
254
267
|
params: [...w.params, ...facet.params],
|
|
@@ -270,7 +283,7 @@ function buildSingleRowLookup(q, pruned, mode) {
|
|
|
270
283
|
return {
|
|
271
284
|
table,
|
|
272
285
|
params,
|
|
273
|
-
sql: `SELECT ${dims.length > 0 ? `${dims.map(dimSelect).join(", ")}, ${metrics}` : metrics} FROM ${
|
|
286
|
+
sql: `SELECT ${dims.length > 0 ? `${dims.map(dimSelect).join(", ")}, ${metrics}` : metrics} FROM ${factTableRef()} WHERE ${clause}${groupBy}`
|
|
274
287
|
};
|
|
275
288
|
}
|
|
276
289
|
function buildMultiSeriesStackedDaily(q, pruned, mode) {
|
|
@@ -279,7 +292,7 @@ function buildMultiSeriesStackedDaily(q, pruned, mode) {
|
|
|
279
292
|
if (q.seriesDimension === "device") {
|
|
280
293
|
const selects = DEVICE_SUFFIXES.map((suffix) => {
|
|
281
294
|
const source = deviceSource(suffix);
|
|
282
|
-
return `SELECT date, '${suffix.toUpperCase()}' AS device, ${metricExprForSource(q.metric, source)} FROM ${
|
|
295
|
+
return `SELECT date, '${suffix.toUpperCase()}' AS device, ${metricExprForSource(q.metric, source)} FROM ${factTableRef()} WHERE ${w.clause} GROUP BY date`;
|
|
283
296
|
});
|
|
284
297
|
return {
|
|
285
298
|
table,
|
|
@@ -291,7 +304,7 @@ function buildMultiSeriesStackedDaily(q, pruned, mode) {
|
|
|
291
304
|
return {
|
|
292
305
|
table,
|
|
293
306
|
params: w.params,
|
|
294
|
-
sql: `SELECT date, ${dimSelect(q.seriesDimension)}, ${metricExpr(q.metric)} FROM ${
|
|
307
|
+
sql: `SELECT date, ${dimSelect(q.seriesDimension)}, ${metricExpr(q.metric)} FROM ${factTableRef()} WHERE ${w.clause} GROUP BY date, ${col} ORDER BY date ASC`
|
|
295
308
|
};
|
|
296
309
|
}
|
|
297
310
|
function buildTwoDimensionDetail(q, pruned, mode) {
|
|
@@ -309,7 +322,7 @@ function buildTwoDimensionDetail(q, pruned, mode) {
|
|
|
309
322
|
const facet = facetPredicate(q);
|
|
310
323
|
clause += facet.sql;
|
|
311
324
|
params.push(...facet.params);
|
|
312
|
-
let sql = `SELECT url, query, ${(q.orderBy && !q.metrics.includes(q.orderBy.metric) ? [...q.metrics, q.orderBy.metric] : q.metrics).map(metricExpr).join(", ")} FROM ${
|
|
325
|
+
let sql = `SELECT url, query, ${(q.orderBy && !q.metrics.includes(q.orderBy.metric) ? [...q.metrics, q.orderBy.metric] : q.metrics).map(metricExpr).join(", ")} FROM ${factTableRef()} WHERE ${clause} GROUP BY url, query`;
|
|
313
326
|
if (q.orderBy) sql += ` ORDER BY ${metricAlias(q.orderBy.metric)} ${q.orderBy.dir.toUpperCase()}`;
|
|
314
327
|
if (q.limit && q.limit > 0) sql += ` LIMIT ${Math.floor(q.limit)}`;
|
|
315
328
|
return {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/cloudflare",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.36.
|
|
4
|
+
"version": "0.36.3",
|
|
5
5
|
"description": "Cloudflare-Workers-flavored helpers for the gscdump analytics stack: AnalyticsEnv binding contract, R2 SigV4 presigner, size-hint HMAC, DuckDB Workers shims, engine factory.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@uwdata/flechette": "^2.5.0",
|
|
48
48
|
"aws4fetch": "^1.0.20",
|
|
49
|
-
"@gscdump/contracts": "0.36.
|
|
50
|
-
"@gscdump/engine": "0.36.
|
|
51
|
-
"@gscdump/engine-sqlite": "0.36.
|
|
52
|
-
"gscdump": "0.36.
|
|
49
|
+
"@gscdump/contracts": "0.36.3",
|
|
50
|
+
"@gscdump/engine": "0.36.3",
|
|
51
|
+
"@gscdump/engine-sqlite": "0.36.3",
|
|
52
|
+
"gscdump": "0.36.3"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@cloudflare/vitest-pool-workers": "^0.18.0",
|