@gscdump/cloudflare 5.6.0 → 5.7.0

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.
@@ -153,36 +153,59 @@ function facetPredicate(query) {
153
153
  params
154
154
  };
155
155
  }
156
+ const DAILY_FACET_COLUMNS = /* @__PURE__ */ new Set([
157
+ "page",
158
+ "query",
159
+ "queryCanonical",
160
+ "country"
161
+ ]);
162
+ function dailyTable(query, seriesDimension, unfaceted) {
163
+ const facets = query.facets ?? [];
164
+ if (!facets.length) return unfaceted;
165
+ const dims = [...seriesDimension ? [seriesDimension] : [], ...facets.map((facet) => facet.column)];
166
+ const unsupported = dims.find((dim) => !DAILY_FACET_COLUMNS.has(dim));
167
+ if (unsupported) throw new Error(`[archetype-sql] ${query.archetype}: a daily read cannot combine a facet with the ${unsupported} dimension`);
168
+ if (dims.includes("country") && dims.some((dim) => dim !== "country")) throw new Error(`[archetype-sql] ${query.archetype}: no fact table stores country with page or query, so a daily read cannot apply this facet`);
169
+ return tableForDimensions(dims);
170
+ }
156
171
  function buildSiteDailyTimeseries(q, pruned, mode) {
172
+ const table = dailyTable(q, void 0, "dates");
157
173
  const w = partitionWhere(q, pruned, mode);
174
+ const facet = facetPredicate(q);
158
175
  const metrics = q.metrics.map(metricExpr).join(", ");
159
176
  return {
160
- table: "dates",
161
- params: w.params,
162
- sql: `SELECT date, ${metrics} FROM ${factTableRef()} WHERE ${w.clause} GROUP BY date ORDER BY date ASC`
177
+ table,
178
+ params: [...w.params, ...facet.params],
179
+ sql: `SELECT date, ${metrics} FROM ${factTableRef()} WHERE ${w.clause}${facet.sql} GROUP BY date ORDER BY date ASC`
163
180
  };
164
181
  }
165
182
  function buildEntityDailyTimeseries(q, pruned, mode) {
166
- const table = tableForDimensions([q.entity.dimension]);
183
+ const table = dailyTable(q, q.entity.dimension, tableForDimensions([q.entity.dimension]));
167
184
  const w = partitionWhere(q, pruned, mode);
185
+ const facet = facetPredicate(q);
168
186
  const col = dimColumn(q.entity.dimension);
169
187
  const metrics = q.metrics.map(metricExpr).join(", ");
170
188
  return {
171
189
  table,
172
- params: [...w.params, q.entity.value],
173
- sql: `SELECT date, ${metrics} FROM ${factTableRef()} WHERE ${w.clause} AND ${col} = ? GROUP BY date ORDER BY date ASC`
190
+ params: [
191
+ ...w.params,
192
+ ...facet.params,
193
+ q.entity.value
194
+ ],
195
+ sql: `SELECT date, ${metrics} FROM ${factTableRef()} WHERE ${w.clause}${facet.sql} AND ${col} = ? GROUP BY date ORDER BY date ASC`
174
196
  };
175
197
  }
176
198
  function buildEntityDailySparkline(q, pruned, mode) {
177
- const table = tableForDimensions([q.dimension]);
199
+ const table = dailyTable(q, q.dimension, tableForDimensions([q.dimension]));
178
200
  const w = partitionWhere(q, pruned, mode);
201
+ const facet = facetPredicate(q);
179
202
  const col = dimColumn(q.dimension);
180
203
  if (q.entities.length === 0) throw new Error("entity-daily-sparkline: empty entities - resolver must pre-resolve the top-N list");
181
204
  const inList = q.entities.map(sqlStringLiteral).join(", ");
182
205
  return {
183
206
  table,
184
- params: w.params,
185
- sql: `SELECT date, ${col} AS entity, ${metricExpr(q.metric)} FROM ${factTableRef()} WHERE ${w.clause} AND ${col} IN (${inList}) GROUP BY date, ${col} ORDER BY date ASC`
207
+ params: [...w.params, ...facet.params],
208
+ sql: `SELECT date, ${col} AS entity, ${metricExpr(q.metric)} FROM ${factTableRef()} WHERE ${w.clause}${facet.sql} AND ${col} IN (${inList}) GROUP BY date, ${col} ORDER BY date ASC`
186
209
  };
187
210
  }
188
211
  function buildTopNBreakdown(q, pruned, mode, separateComparisonTable = false) {
@@ -285,7 +308,7 @@ function buildSingleRowLookup(q, pruned, mode) {
285
308
  };
286
309
  }
287
310
  function buildMultiSeriesStackedDaily(q, pruned, mode) {
288
- const table = tableForDimensions([q.seriesDimension]);
311
+ const table = dailyTable(q, q.seriesDimension, tableForDimensions([q.seriesDimension]));
289
312
  const w = partitionWhere(q, pruned, mode);
290
313
  if (q.seriesDimension === "device") {
291
314
  const selects = DEVICE_SUFFIXES.map((suffix) => {
@@ -299,10 +322,11 @@ function buildMultiSeriesStackedDaily(q, pruned, mode) {
299
322
  };
300
323
  }
301
324
  const col = dimColumn(q.seriesDimension);
325
+ const facet = facetPredicate(q);
302
326
  return {
303
327
  table,
304
- params: w.params,
305
- sql: `SELECT date, ${dimSelect(q.seriesDimension)}, ${metricExpr(q.metric)} FROM ${factTableRef()} WHERE ${w.clause} GROUP BY date, ${col} ORDER BY date ASC`
328
+ params: [...w.params, ...facet.params],
329
+ sql: `SELECT date, ${dimSelect(q.seriesDimension)}, ${metricExpr(q.metric)} FROM ${factTableRef()} WHERE ${w.clause}${facet.sql} GROUP BY date, ${col} ORDER BY date ASC`
306
330
  };
307
331
  }
308
332
  function buildTwoDimensionDetail(q, pruned, mode) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/cloudflare",
3
3
  "type": "module",
4
- "version": "5.6.0",
4
+ "version": "5.7.0",
5
5
  "description": "Cloudflare Workers helpers for server-tail queries and in-flight request deduplication.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -39,9 +39,9 @@
39
39
  "node": ">=22.13.0"
40
40
  },
41
41
  "dependencies": {
42
- "@gscdump/contracts": "^5.6.0",
43
- "@gscdump/engine": "^5.6.0",
44
- "gscdump": "^5.6.0"
42
+ "@gscdump/contracts": "^5.7.0",
43
+ "@gscdump/engine": "^5.7.0",
44
+ "gscdump": "^5.7.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@cloudflare/vitest-pool-workers": "^0.22.0",