@gscdump/cloudflare 0.26.9 → 0.27.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.
@@ -1,24 +1,13 @@
1
- import { ArchetypeQuery, ArchetypeResult, ArchetypeResultRow } from "@gscdump/sdk";
1
+ import { ArchetypeQuery, ArchetypeResult, ArchetypeResultRow } from "@gscdump/contracts/archetypes";
2
2
  import { Result } from "gscdump/result";
3
- import { IcebergTableName } from "@gscdump/engine/iceberg";
4
3
  import { ServerTailDirective } from "@gscdump/contracts";
5
- /** Placeholder substituted for the engine-specific table reference. */
6
4
  declare const TABLE_PLACEHOLDER = "{{TABLE}}";
7
- /** A dialect-neutral SQL plan. */
5
+ type ArchetypeFactTable = 'pages' | 'queries' | 'countries' | 'page_queries' | 'dates';
8
6
  interface ArchetypeSqlPlan {
9
- /** SQL with `{{TABLE}}` standing in for the table reference. */
10
7
  sql: string;
11
- /** Bound parameters, in `?`-order. */
12
8
  params: unknown[];
13
- /** The Iceberg fact table this query reads. */
14
- table: IcebergTableName;
9
+ table: ArchetypeFactTable;
15
10
  }
16
- /**
17
- * Translate an archetype query to a dialect-neutral SQL plan.
18
- *
19
- * Throws for `arbitrary-sql` (caller-supplied SQL, handled by the DuckDB
20
- * executor directly) and `aux-cloud-only` (not an Iceberg query).
21
- */
22
11
  declare function buildArchetypeSql(query: ArchetypeQuery): ArchetypeSqlPlan;
23
12
  /** Row returned by the DuckDB sibling. */
24
13
  type DuckDbIcebergRow = Record<string, string | number | null>;
@@ -1,5 +1,5 @@
1
- import { bindLiterals, inferTable } from "@gscdump/engine";
2
- import { ARCHETYPE_EXECUTION_CLASS } from "@gscdump/sdk";
1
+ import { bindLiterals } from "@gscdump/engine";
2
+ import { ARCHETYPE_EXECUTION_CLASS } from "@gscdump/contracts/archetypes";
3
3
  import { err, ok, unwrapResult } from "gscdump/result";
4
4
  const TABLE_PLACEHOLDER = "{{TABLE}}";
5
5
  function dimColumn(dim) {
@@ -7,6 +7,14 @@ function dimColumn(dim) {
7
7
  if (dim === "queryCanonical") return "query_canonical";
8
8
  return dim;
9
9
  }
10
+ function tableForDimensions(dims) {
11
+ const set = new Set(dims.filter((d) => d !== "date"));
12
+ if (set.has("page") && (set.has("query") || set.has("queryCanonical"))) return "page_queries";
13
+ if (set.has("query") || set.has("queryCanonical")) return "queries";
14
+ if (set.has("country")) return "countries";
15
+ if (set.has("device")) return "dates";
16
+ return "pages";
17
+ }
10
18
  function metricExpr(metric) {
11
19
  switch (metric) {
12
20
  case "clicks": return "SUM(clicks) AS clicks";
@@ -128,7 +136,7 @@ function buildSiteDailyTimeseries(q) {
128
136
  };
129
137
  }
130
138
  function buildEntityDailyTimeseries(q) {
131
- const table = inferTable([q.entity.dimension]);
139
+ const table = tableForDimensions([q.entity.dimension]);
132
140
  const w = partitionWhere(q);
133
141
  const col = dimColumn(q.entity.dimension);
134
142
  const metrics = q.metrics.map(metricExpr).join(", ");
@@ -139,10 +147,10 @@ function buildEntityDailyTimeseries(q) {
139
147
  };
140
148
  }
141
149
  function buildEntityDailySparkline(q) {
142
- const table = inferTable([q.dimension]);
150
+ const table = tableForDimensions([q.dimension]);
143
151
  const w = partitionWhere(q);
144
152
  const col = dimColumn(q.dimension);
145
- if (q.entities.length === 0) throw new Error("entity-daily-sparkline: empty entities resolver must pre-resolve the top-N list");
153
+ if (q.entities.length === 0) throw new Error("entity-daily-sparkline: empty entities - resolver must pre-resolve the top-N list");
146
154
  const inList = q.entities.map(sqlStringLiteral).join(", ");
147
155
  return {
148
156
  table,
@@ -151,7 +159,7 @@ function buildEntityDailySparkline(q) {
151
159
  };
152
160
  }
153
161
  function buildTopNBreakdown(q) {
154
- const table = inferTable([q.dimension]);
162
+ const table = tableForDimensions([q.dimension]);
155
163
  const w = partitionWhere(q);
156
164
  const order = `${q.orderBy.metric} ${q.orderBy.dir.toUpperCase()}`;
157
165
  const limit = `LIMIT ${Math.max(0, Math.floor(q.limit))}`;
@@ -226,7 +234,7 @@ function buildTopNBreakdown(q) {
226
234
  }
227
235
  function buildSingleRowLookup(q) {
228
236
  const dims = Object.keys(q.match);
229
- const table = inferTable(dims);
237
+ const table = tableForDimensions(dims);
230
238
  const w = partitionWhere(q);
231
239
  const params = [...w.params];
232
240
  let clause = w.clause;
@@ -243,7 +251,7 @@ function buildSingleRowLookup(q) {
243
251
  };
244
252
  }
245
253
  function buildMultiSeriesStackedDaily(q) {
246
- const table = inferTable([q.seriesDimension]);
254
+ const table = tableForDimensions([q.seriesDimension]);
247
255
  const w = partitionWhere(q);
248
256
  if (q.seriesDimension === "device") {
249
257
  const selects = DEVICE_SUFFIXES.map((suffix) => {
@@ -296,7 +304,7 @@ function buildArchetypeSql(query) {
296
304
  case "single-row-lookup": return buildSingleRowLookup(query);
297
305
  case "multi-series-stacked-daily": return buildMultiSeriesStackedDaily(query);
298
306
  case "two-dimension-detail": return buildTwoDimensionDetail(query);
299
- case "arbitrary-sql": throw new Error("buildArchetypeSql: arbitrary-sql carries caller SQL the DuckDB executor runs it verbatim");
307
+ case "arbitrary-sql": throw new Error("buildArchetypeSql: arbitrary-sql carries caller SQL - the DuckDB executor runs it verbatim");
300
308
  case "aux-cloud-only": throw new Error("buildArchetypeSql: aux-cloud-only is not an Iceberg query");
301
309
  }
302
310
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/cloudflare",
3
3
  "type": "module",
4
- "version": "0.26.9",
4
+ "version": "0.27.0",
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,15 +46,14 @@
46
46
  "dependencies": {
47
47
  "@uwdata/flechette": "^2.5.0",
48
48
  "aws4fetch": "^1.0.20",
49
- "@gscdump/engine-sqlite": "0.26.9",
50
- "@gscdump/sdk": "0.26.9",
51
- "@gscdump/contracts": "0.26.9",
52
- "@gscdump/engine": "0.26.9",
53
- "gscdump": "0.26.9"
49
+ "@gscdump/contracts": "0.27.0",
50
+ "@gscdump/engine": "0.27.0",
51
+ "@gscdump/engine-sqlite": "0.27.0",
52
+ "gscdump": "0.27.0"
54
53
  },
55
54
  "devDependencies": {
56
55
  "@cloudflare/vitest-pool-workers": "^0.16.15",
57
- "@cloudflare/workers-types": "^4.20260613.1",
56
+ "@cloudflare/workers-types": "^4.20260616.1",
58
57
  "h3": "^1.15.11",
59
58
  "typescript": "^6.0.3",
60
59
  "wrangler": "^4.100.0"