@gscdump/analysis 0.6.3 → 0.7.5

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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/@gscdump/analysis?color=yellow)](https://npm.chart.dev/@gscdump/analysis)
5
5
  [![license](https://img.shields.io/github/license/harlan-zw/gscdump?color=yellow)](https://github.com/harlan-zw/gscdump/blob/main/LICENSE)
6
6
 
7
- > SEO analyzers + typed query primitives for Google Search Console data. Row-based, DuckDB-native, D1-ready.
7
+ > SEO analyzers for Google Search Console data. Row-based, DuckDB-native, D1-ready.
8
8
 
9
9
  ## Install
10
10
 
@@ -16,15 +16,16 @@ npm install @gscdump/analysis
16
16
 
17
17
  | Subpath | Use when |
18
18
  |---|---|
19
- | `@gscdump/analysis` | You have arrays of rows (GSC API responses, D1 query results). Pure functions, no DB. |
20
- | `@gscdump/analysis/analyzer` | Analyzer contracts (`Analyzer`, `Plan`, `FileSet`), `ROW_ANALYZERS`, registry, dispatcher. |
21
- | `@gscdump/engine-duckdb-node` | You have a Node DuckDB handle over parquet. Ships `SQL_ANALYZERS` + `analyzeInBrowser` for attached-table parquet. |
22
- | `@gscdump/engine-wasm` | Nuxt / React / vanilla app running DuckDB-WASM client-side against R2 parquets. |
23
- | `@gscdump/engine-sqlite` | Cloudflare Workers / anywhere routing through sqlite-proxy (D1). |
24
- | `@gscdump/engine/resolver` | Dialect-neutral SQL composition kit: `ResolverAdapter`, `pgResolverAdapter`, `compilePg`/`compileSqlite`, `resolveToSQL`, source contracts. |
25
- | `@gscdump/analysis/source` | Portable query sources + source-backed analyzers shared across GSC API, sqlite, DuckDB, and tests. |
19
+ | `@gscdump/analysis` | Top-level barrel: row analyzers, source-backed analyzers, `SQL_ANALYZERS`, `analyzeInBrowser`, `defaultAnalyzerRegistry`, contract types re-exported from engine. |
20
+ | `@gscdump/analysis/analyzer` | `ROW_ANALYZERS` array + `paginate*` / `adapt-rows` helpers used by analyzer authors. |
21
+ | `@gscdump/analysis/registry` | Pre-built `defaultAnalyzerRegistry` (rows + sql). Convenience for callers who don't care about bundle size. |
22
+ | `@gscdump/analysis/source` | Portable query sources (`createInMemoryQuerySource`, `createCompositeSource`) + source-backed analyzers. |
26
23
  | `@gscdump/analysis/semantic` | Browser-only semantic analyzers such as content-gap; optional `@huggingface/transformers` peer. |
27
24
  | `@gscdump/analysis/query` | `buildDataQueryPlan` / `buildDataDetailPlan` for the generic query analyzers. |
25
+ | `@gscdump/analysis/routing` | Phase-aware D1 ↔ R2 routing helpers. |
26
+ | `@gscdump/analysis/rollups` | Pre-baked rollup definitions + rebuild orchestration. |
27
+
28
+ The contract layer (`Analyzer`, `Plan`, `Capability`, `AnalysisParams`, `AnalysisResult`, `AnalysisQuerySource`, `runAnalyzerFromSource`, `createAnalyzerRegistry`, `defineAnalyzer`, period helpers, `createEngineQuerySource`) lives in `@gscdump/engine` under the `/analyzer`, `/analysis-types`, `/period`, `/source`, and `/resolver` subpaths. Most are re-exported from `@gscdump/analysis` for convenience.
28
29
 
29
30
  ## Row-based analyzers
30
31
 
@@ -61,11 +62,8 @@ const prioritized = await analyzeActionPriority({
61
62
  Source adapters compose a GSC client + analyzer in one call:
62
63
 
63
64
  ```ts
64
- import {
65
- analyzeMoversFromSource,
66
- analyzeStrikingDistanceFromSource,
67
- createGscApiQuerySource,
68
- } from '@gscdump/analysis'
65
+ import { analyzeMoversFromSource, analyzeStrikingDistanceFromSource } from '@gscdump/analysis'
66
+ import { createGscApiQuerySource } from '@gscdump/engine-gsc-api'
69
67
 
70
68
  const source = createGscApiQuerySource({ client, siteUrl })
71
69
  const movers = await analyzeMoversFromSource(source, { current, previous })
@@ -76,92 +74,39 @@ const movers = await analyzeMoversFromSource(source, { current, previous })
76
74
  SQL-native path. `SQL_ANALYZERS` dispatch through `runAnalyzerFromSource` against an engine-backed source.
77
75
 
78
76
  ```ts
79
- import { createAnalyzerRegistry, ROW_ANALYZERS, runAnalyzerFromSource } from '@gscdump/analysis/analyzer'
80
- import { createEngine, SQL_ANALYZERS } from '@gscdump/engine-duckdb-node'
77
+ import { ROW_ANALYZERS, SQL_ANALYZERS } from '@gscdump/analysis'
78
+ import { createAnalyzerRegistry, runAnalyzerFromSource } from '@gscdump/engine/analyzer'
79
+ import { createEngineQuerySource } from '@gscdump/engine/source'
81
80
 
82
- const source = createEngine({ engine, ctx })
81
+ const source = createEngineQuerySource({ engine, ctx })
83
82
  const registry = createAnalyzerRegistry({ rows: ROW_ANALYZERS, sql: SQL_ANALYZERS })
84
83
  const result = await runAnalyzerFromSource(source, { type: 'striking-distance', minImpressions: 100 }, registry)
85
84
  ```
86
85
 
87
- `attachParquetIndex` and `attachSnapshotIndex` wire parquet files (per-day, per-month, or pre-baked `.duckdb` snapshots) into a DuckDB session for `analyzeInBrowser` (attached-table path).
86
+ `attachParquetIndex` and `attachSnapshotIndex` from `@gscdump/engine-duckdb-node` wire parquet files (per-day, per-month, or pre-baked `.duckdb` snapshots) into a DuckDB session. Pair with `analyzeInBrowser` from `@gscdump/analysis` for the attached-table dispatch path.
88
87
 
89
88
  ## Browser (DuckDB-WASM)
90
89
 
91
- Three primitives for client-side analytics:
92
-
93
90
  ```ts
94
- import {
95
- createInsightRunner,
96
- resolveWindow,
97
- scopeFor,
98
- strikingMomentum,
99
- } from '@gscdump/engine-wasm'
91
+ import { analyzeInBrowser } from '@gscdump/analysis'
92
+ import { createEngine } from '@gscdump/engine-duckdb-wasm'
100
93
 
101
- const runner = createInsightRunner({ db, conn }) // AsyncDuckDB + connection
102
- const window = resolveWindow({ preset: 'last-30d', comparison: 'prev-period' })
103
- const scope = scopeFor('pages', { siteId, window })
104
-
105
- const rows = await strikingMomentum(runner, { ...scope, limit: 50 })
94
+ const result = await analyzeInBrowser(runner, { schema: 'gsc' }, { type: 'striking-distance' })
106
95
  ```
107
96
 
108
- - `createInsightRunner({ db, conn })` drizzle-orm handle over DuckDB-WASM. Typed `.select()` / window functions, or drop to `sql\`...\`` raw.
109
- - `bootDuckDBWasm()` / `attachParquetUrlTables()` / `attachParquetTables()` / `createBrowserAnalysisRuntime()` — reusable browser runtime primitives for booting DuckDB-WASM, attaching parquet-backed views, and exposing `query()` / `analyze()` helpers without rewriting the same glue in every app.
110
- - `resolveWindow({ preset, comparison, anchor })` — canonical date windows, no DB.
111
- - `scopeFor(table, { siteId, window })` + `mergeScope()` — boundary predicates for multi-tenant queries.
112
- - `schema`, `pages`, `keywords`, `page_keywords`, `countries`, `devices` — drizzle schema mirroring `gscdump/analytics` `SCHEMAS`. Drift fails loudly at load.
113
-
114
- Vendors a stripped-down drizzle-orm DuckDB-WASM adapter (~240 LoC, adapted from `@proj-airi/drizzle-duckdb-wasm`, MIT). Transactions throw — analytics workload is read-only.
97
+ `analyzeInBrowser` wraps any runner with `query(sql, params, signal?)` in an `AnalysisQuerySource` with the `attachedTables` capability and dispatches via `runAnalyzerFromSource`.
115
98
 
116
- `@duckdb/duckdb-wasm` is an optional peer dep. Bundle: **10.3 kB / 2.72 kB gzipped**.
99
+ For typed drizzle-style access, `@gscdump/engine-duckdb-wasm` exports `createEngine` (a `SqlQuerySource`) plus `bootDuckDBWasm`, `attachParquetUrlTables`, `createBrowserAnalysisRuntime`, and `resolveWindow` (re-export from `@gscdump/engine/period`).
117
100
 
118
101
  ## SQLite (D1 / Cloudflare Workers)
119
102
 
120
- Mirror of `/browser`, dialect-targeted at sqlite-core.
121
-
122
- ```ts
123
- import {
124
- aggClicks,
125
- aggCtr,
126
- aggImpressions,
127
- aggPosition,
128
- compileSqlite,
129
- createSqliteInsightRunner,
130
- gsc_keywords,
131
- sql,
132
- } from '@gscdump/engine-sqlite'
133
-
134
- const queryExpr = sql`
135
- SELECT ${gsc_keywords.query} as keyword,
136
- SUM(${gsc_keywords.clicks}) as clicks,
137
- ${aggCtr(gsc_keywords)} as ctr
138
- FROM ${gsc_keywords}
139
- WHERE ${gsc_keywords.site_id} = ${siteId}
140
- GROUP BY ${gsc_keywords.query}
141
- `
142
- const { sql: compiledSql, params } = compileSqlite(queryExpr)
143
- const rows = await executor(compiledSql, params) // queryUserD1, etc.
144
- ```
145
-
146
- - `createSqliteInsightRunner({ executor })` — sqlite-proxy drizzle adapter.
147
- - `compileSqlite(sql)` — compile to `{ sql, params }` for any HTTP executor.
148
- - `aggClicks` / `aggImpressions` / `aggCtr` / `aggPosition` — aggregate helpers replacing hand-rolled `METRICS_SQL`.
149
- - Runtime builder exports (`colRef`, `dimColumn`, `metricSql`, `havingPredicates`, …) for dimension/metric driven query builders.
150
-
151
- Always import `sql` from `@gscdump/engine-sqlite` — not `drizzle-orm` directly — so consumers bind to the package's drizzle-orm instance and avoid cross-install `SQL<unknown>` mismatches.
152
-
153
- Bundle: **5.3 kB / 1.4 kB gzipped**.
103
+ Mirror of the DuckDB path, dialect-targeted at sqlite-core. `@gscdump/engine-sqlite` exports `createEngine` (a `SqlQuerySource` over `executor + siteId`), `compileSqlite`, drizzle helpers (`gsc_keywords`, etc.), and `resolveWindow` (re-export from `@gscdump/engine/period`).
154
104
 
155
105
  ## Query composers (dialect-neutral)
156
106
 
157
107
  ```ts
158
108
  import { sqliteResolverAdapter } from '@gscdump/engine-sqlite'
159
- import {
160
- buildTotalsSql,
161
- pgResolverAdapter,
162
- resolveToSQL,
163
- resolveToSQLOptimized,
164
- } from '@gscdump/engine/resolver'
109
+ import { pgResolverAdapter, resolveToSQL } from '@gscdump/engine/resolver'
165
110
 
166
111
  const resolved = resolveToSQL(builderState, { adapter: sqliteResolverAdapter, siteId })
167
112
  ```
@@ -173,16 +118,10 @@ Pass `sqliteResolverAdapter` from `@gscdump/engine-sqlite` (D1, `site_id`-scoped
173
118
  `/source` is the cross-implementation seam:
174
119
 
175
120
  ```ts
176
- import {
177
- analyzeMoversFromSource,
178
- createEngineQuerySource,
179
- queryRows,
180
- } from '@gscdump/analysis/source'
181
-
182
- const source = createEngineQuerySource({
183
- engine,
184
- ctx: { userId, siteId },
185
- })
121
+ import { analyzeMoversFromSource } from '@gscdump/analysis'
122
+ import { createEngineQuerySource, queryRows } from '@gscdump/engine/source'
123
+
124
+ const source = createEngineQuerySource({ engine, ctx: { userId, siteId } })
186
125
 
187
126
  const rows = await queryRows(source, builderState)
188
127
  const movers = await analyzeMoversFromSource(source, periods)
@@ -190,11 +129,12 @@ const movers = await analyzeMoversFromSource(source, periods)
190
129
 
191
130
  Available source factories:
192
131
 
193
- - `createGscApiQuerySource({ client, siteUrl })`
194
- - `createBrowserQuerySource({ query(sql, params) })`
195
- - `createSqliteQuerySource({ executor, siteId })`
196
- - `createEngineQuerySource({ engine, ctx })`
197
- - `createInMemoryQuerySource({ queryRows })`
132
+ - `createGscApiQuerySource({ client, siteUrl })` — `@gscdump/engine-gsc-api`
133
+ - `createLiveGscSource({ accessToken, siteUrl })` — `@gscdump/engine-gsc-api`
134
+ - `createCompositeSource({ engine, gsc })` — `@gscdump/analysis/source`; engine first, GSC fallback
135
+ - `createInMemoryQuerySource({ queryRows })` — `@gscdump/analysis/source`
136
+ - `createEngineQuerySource({ engine, ctx })` — `@gscdump/engine/source`
137
+ - `createEngine({ ... })` — `@gscdump/engine-duckdb-wasm`, `@gscdump/engine-sqlite`, `@gscdump/engine-duckdb-node`
198
138
 
199
139
  Portable analyzers currently cover the row-based tools:
200
140
  `striking-distance`, `opportunity`, `brand`, `clustering`, `concentration`,
@@ -202,9 +142,6 @@ Portable analyzers currently cover the row-based tools:
202
142
 
203
143
  ## Semantic (browser-only)
204
144
 
205
- `/semantic` holds browser-only analysis that depends on client runtime
206
- capabilities rather than SQL backends alone.
207
-
208
145
  ```ts
209
146
  import { analyzeContentGap } from '@gscdump/analysis/semantic'
210
147
 
@@ -214,14 +151,12 @@ const result = await analyzeContentGap(runner, {
214
151
  })
215
152
  ```
216
153
 
217
- `analyzeContentGap()` loads a MiniLM/BGE embedding model via
218
- `@huggingface/transformers`, caches vectors in IndexedDB, and compares top
219
- queries to candidate URLs derived from `page_keywords`.
154
+ Loads a MiniLM/BGE embedding model via `@huggingface/transformers`, caches vectors in IndexedDB, and compares top queries to candidate URLs derived from `page_keywords`.
220
155
 
221
156
  ## Window resolution
222
157
 
223
158
  ```ts
224
- import { resolveWindow } from '@gscdump/engine-wasm'
159
+ import { resolveWindow } from '@gscdump/analysis'
225
160
 
226
161
  const w = resolveWindow({ preset: 'last-30d', comparison: 'yoy' })
227
162
  // { start: '...', end: '...', days: 30, comparison: { start, end } }
@@ -234,19 +169,19 @@ Presets: `last-7d`, `last-28d`, `last-30d`, `last-90d`, `last-180d`, `last-365d`
234
169
  | Surface | Stability |
235
170
  |---|---|
236
171
  | Row analyzers (`analyzeStrikingDistance`, `analyzeMovers`, ...) | Public |
237
- | Source factories (`create*QuerySource`) + `analyzeFromSource` | Public |
238
- | Engine factories (`@gscdump/analysis/engine/<name>`'s `createEngine`) | Public |
239
- | `Analyzer<P, R>` contract + `analyzerRegistry` | Public |
240
- | `/period`, `/query`, `/source`, `/semantic` subpaths | Public |
241
- | Internals reached through `@gscdump/analysis/engine/<name>/<file>` not listed above | Private |
172
+ | Source factories + `analyzeFromSource` | Public |
173
+ | `Analyzer<P, R>` contract + `createAnalyzerRegistry` (re-exported from `@gscdump/engine/analyzer`) | Public |
174
+ | `/source`, `/semantic`, `/query`, `/routing`, `/rollups` subpaths | Public |
175
+ | Per-analyzer modules under `analysis/src/analyzers/<name>` | Private |
242
176
 
243
177
  ## Related
244
178
 
245
179
  - [`gscdump`](../gscdump) — REST client + query builder (edge-safe).
246
- - [`@gscdump/engine`](../engine) — Parquet/DuckDB storage engine.
247
- - [`@gscdump/engine-duckdb-node`](../engine-duckdb-node) — Node DuckDB analyzer dispatch.
248
- - [`@gscdump/engine-wasm`](../engine-wasm) — DuckDB-WASM browser runtime.
180
+ - [`@gscdump/engine`](../engine) — Parquet/DuckDB storage engine + analyzer/source/period contracts.
181
+ - [`@gscdump/engine-duckdb-node`](../engine-duckdb-node) — Node DuckDB engine factory + parquet/snapshot attach helpers.
182
+ - [`@gscdump/engine-duckdb-wasm`](../engine-duckdb-wasm) — DuckDB-WASM browser runtime + drizzle adapter.
249
183
  - [`@gscdump/engine-sqlite`](../engine-sqlite) — SQLite / D1 dialect adapter.
184
+ - [`@gscdump/engine-gsc-api`](../engine-gsc-api) — GSC live-API engine adapter.
250
185
  - [`@gscdump/cli`](../cli) — CLI wrapping `gscdump` + `@gscdump/engine` + `@gscdump/analysis`.
251
186
 
252
187
  ## License
@@ -1,6 +1,7 @@
1
+ import * as _$_gscdump_engine_analyzer0 from "@gscdump/engine/analyzer";
2
+ import { Analyzer } from "@gscdump/engine/analyzer";
3
+ import { AnalysisPeriod } from "@gscdump/engine/period";
1
4
  import { BuilderState } from "gscdump/query";
2
- import { AnalysisQuerySource, FileSet, FileSet as FileSet$1 } from "@gscdump/engine/resolver";
3
- import { AnalysisParams, AnalysisResult } from "gscdump/contracts";
4
5
  import { Row } from "@gscdump/engine/contracts";
5
6
  /**
6
7
  * `bayesian-ctr` — Empirical-Bayes CTR shrinkage. SQL-only colocation.
@@ -27,7 +28,7 @@ interface BayesianCtrResult {
27
28
  significance: number;
28
29
  classification: 'overperforming' | 'underperforming' | 'expected';
29
30
  }
30
- declare const bayesianCtrAnalyzer: DefinedAnalyzer;
31
+ declare const bayesianCtrAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
31
32
  /**
32
33
  * bipartite-pagerank
33
34
  *
@@ -53,7 +54,12 @@ interface BipartitePagerankNode {
53
54
  impressions: number;
54
55
  }
55
56
  type BipartitePagerankResult = BipartitePagerankNode;
56
- declare const bipartitePagerankAnalyzer: DefinedAnalyzer;
57
+ declare const bipartitePagerankAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
58
+ /**
59
+ * Domain row shapes + analysis utilities. Analyzer-call contracts
60
+ * (`AnalysisParams`, `AnalysisResult`, `AnalysisTool`, `num`) live in
61
+ * `@gscdump/engine/analysis-types`.
62
+ */
57
63
  type SortOrder = 'asc' | 'desc';
58
64
  /** Base search metrics */
59
65
  interface BaseMetrics {
@@ -98,7 +104,7 @@ interface BrandResultRow {
98
104
  position: number;
99
105
  segment: 'brand' | 'non-brand';
100
106
  }
101
- declare const brandAnalyzer: DefinedAnalyzer;
107
+ declare const brandAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
102
108
  type CannibalizationSortMetric = 'clicks' | 'impressions' | 'positionSpread' | 'pageCount';
103
109
  interface CannibalizationOptions {
104
110
  /** Minimum impressions for a query to be considered. Default: 10 */
@@ -149,7 +155,7 @@ interface CannibalizationEvent {
149
155
  severity: number;
150
156
  competitors: CannibalizationCompetitor[];
151
157
  }
152
- declare const cannibalizationAnalyzer: DefinedAnalyzer;
158
+ declare const cannibalizationAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
153
159
  /**
154
160
  * `change-point` — per-(query, url) timeseries change-point detection. SQL-only.
155
161
  *
@@ -174,7 +180,7 @@ interface ChangePointResult {
174
180
  direction: 'improved' | 'worsened';
175
181
  series: ChangePointSeriesPoint[];
176
182
  }
177
- declare const changePointAnalyzer: DefinedAnalyzer;
183
+ declare const changePointAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
178
184
  type ClusterType = 'prefix' | 'intent' | 'both';
179
185
  interface ClusteringOptions {
180
186
  /** Minimum keywords for a cluster to be reported. Default: 2 */
@@ -197,7 +203,7 @@ interface ClusteringResult {
197
203
  clusters: KeywordCluster[];
198
204
  unclustered: KeywordRow[];
199
205
  }
200
- declare const clusteringAnalyzer: DefinedAnalyzer;
206
+ declare const clusteringAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
201
207
  type ConcentrationRiskLevel = 'low' | 'medium' | 'high';
202
208
  interface ConcentrationOptions {
203
209
  /** Number of top items to report. Default: 10 */
@@ -225,7 +231,7 @@ interface ConcentrationResult {
225
231
  /** Risk level derived from HHI: <1500 low, 1500-2500 medium, >2500 high */
226
232
  riskLevel: ConcentrationRiskLevel;
227
233
  }
228
- declare const concentrationAnalyzer: DefinedAnalyzer;
234
+ declare const concentrationAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
229
235
  /**
230
236
  * `content-velocity` — weekly new-keyword cadence. SQL-only colocation.
231
237
  *
@@ -236,7 +242,7 @@ interface ContentVelocityWeek {
236
242
  newKeywords: number;
237
243
  totalKeywords: number;
238
244
  }
239
- declare const contentVelocityAnalyzer: DefinedAnalyzer;
245
+ declare const contentVelocityAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
240
246
  /**
241
247
  * `ctr-anomaly` — rolling CTR envelope per (query, page). SQL-only colocation.
242
248
  *
@@ -266,7 +272,7 @@ interface CtrAnomalyResult {
266
272
  totalClicks: number;
267
273
  series: CtrAnomalySeriesPoint[];
268
274
  }
269
- declare const ctrAnomalyAnalyzer: DefinedAnalyzer;
275
+ declare const ctrAnomalyAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
270
276
  /**
271
277
  * `ctr-curve` — CTR by position bucket plus over/under-performing outliers.
272
278
  * SQL-only colocation.
@@ -290,7 +296,7 @@ interface CtrCurveOutlier {
290
296
  expectedCtr: number;
291
297
  ctrDiff: number;
292
298
  }
293
- declare const ctrCurveAnalyzer: DefinedAnalyzer;
299
+ declare const ctrCurveAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
294
300
  /**
295
301
  * dark-traffic — gap between page-level clicks and sum-of-keyword clicks.
296
302
  *
@@ -305,11 +311,11 @@ interface DarkTrafficResult {
305
311
  darkPercent: number;
306
312
  keywordCount: number;
307
313
  }
308
- declare const darkTrafficAnalyzer: DefinedAnalyzer;
314
+ declare const darkTrafficAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
309
315
  type DataDetailResult = Row;
310
- declare const dataDetailAnalyzer: DefinedAnalyzer;
316
+ declare const dataDetailAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
311
317
  type DataQueryResult = Row;
312
- declare const dataQueryAnalyzer: DefinedAnalyzer;
318
+ declare const dataQueryAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
313
319
  type DecaySortMetric = 'lostClicks' | 'declinePercent' | 'currentClicks';
314
320
  interface DecayOptions {
315
321
  /** Minimum clicks in previous period to consider. Default: 50 */
@@ -339,7 +345,7 @@ interface DecayResult {
339
345
  positionDrop: number;
340
346
  series?: DecaySeriesPoint[];
341
347
  }
342
- declare const decayAnalyzer: DefinedAnalyzer;
348
+ declare const decayAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
343
349
  /**
344
350
  * device-gap — desktop vs mobile CTR/position delta over time.
345
351
  */
@@ -358,7 +364,7 @@ interface DeviceGapResult {
358
364
  positionGap: number;
359
365
  };
360
366
  }
361
- declare const deviceGapAnalyzer: DefinedAnalyzer;
367
+ declare const deviceGapAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
362
368
  /**
363
369
  * intent-atlas
364
370
  *
@@ -381,7 +387,7 @@ interface IntentAtlasResult {
381
387
  position: number;
382
388
  }>;
383
389
  }
384
- declare const intentAtlasAnalyzer: DefinedAnalyzer;
390
+ declare const intentAtlasAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
385
391
  /**
386
392
  * keyword-breadth — keyword-count histogram across pages + fragile/authority
387
393
  * classification.
@@ -390,7 +396,7 @@ interface KeywordBreadthResult {
390
396
  bucket: string;
391
397
  pageCount: number;
392
398
  }
393
- declare const keywordBreadthAnalyzer: DefinedAnalyzer;
399
+ declare const keywordBreadthAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
394
400
  /**
395
401
  * long-tail
396
402
  *
@@ -415,7 +421,7 @@ interface LongTailResult {
415
421
  query: string;
416
422
  }>;
417
423
  }
418
- declare const longTailAnalyzer: DefinedAnalyzer;
424
+ declare const longTailAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
419
425
  type MoversSortMetric = 'clicks' | 'impressions' | 'clicksChange' | 'impressionsChange' | 'positionChange';
420
426
  interface MoversOptions {
421
427
  /** Minimum change threshold to flag. Default: 0.2 (20%) */
@@ -459,7 +465,7 @@ interface MoversResultRow extends MoverData {
459
465
  direction: 'rising' | 'declining' | 'stable';
460
466
  series?: MoversSeriesPoint[];
461
467
  }
462
- declare const moversAnalyzer: DefinedAnalyzer;
468
+ declare const moversAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
463
469
  interface OpportunityFactors {
464
470
  positionScore: number;
465
471
  impressionScore: number;
@@ -476,7 +482,7 @@ interface OpportunityResult {
476
482
  potentialClicks: number;
477
483
  factors: OpportunityFactors;
478
484
  }
479
- declare const opportunityAnalyzer: DefinedAnalyzer;
485
+ declare const opportunityAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
480
486
  /**
481
487
  * position-distribution — daily count of keywords per position bucket.
482
488
  * Matches `/api/sites/[siteId]/position-distribution.get.ts`.
@@ -489,7 +495,7 @@ interface PositionDistributionResult {
489
495
  pos_20_plus: number;
490
496
  total: number;
491
497
  }
492
- declare const positionDistributionAnalyzer: DefinedAnalyzer;
498
+ declare const positionDistributionAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
493
499
  /**
494
500
  * position-volatility
495
501
  *
@@ -517,7 +523,7 @@ interface PositionVolatilityResult {
517
523
  totalImpressions: number;
518
524
  days: PositionVolatilityDay[];
519
525
  }
520
- declare const positionVolatilityAnalyzer: DefinedAnalyzer;
526
+ declare const positionVolatilityAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
521
527
  /**
522
528
  * query-migration
523
529
  *
@@ -545,7 +551,7 @@ interface QueryMigrationResult {
545
551
  fuzzyCount: number;
546
552
  examples: QueryMigrationExample[];
547
553
  }
548
- declare const queryMigrationAnalyzer: DefinedAnalyzer;
554
+ declare const queryMigrationAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
549
555
  type SeasonalityMetric = 'clicks' | 'impressions';
550
556
  interface SeasonalityOptions {
551
557
  /** Metric to analyze for seasonality. Default: clicks */
@@ -567,7 +573,7 @@ interface SeasonalityResult {
567
573
  monthlyBreakdown: MonthlyData[];
568
574
  insufficientData: boolean;
569
575
  }
570
- declare const seasonalityAnalyzer: DefinedAnalyzer;
576
+ declare const seasonalityAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
571
577
  /**
572
578
  * stl-decompose
573
579
  *
@@ -597,7 +603,7 @@ interface StlDecomposeResult {
597
603
  trendSlope: number;
598
604
  series: StlDecomposeSeriesPoint[];
599
605
  }
600
- declare const stlDecomposeAnalyzer: DefinedAnalyzer;
606
+ declare const stlDecomposeAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
601
607
  /**
602
608
  * Unified `striking-distance` analyzer. Spike for the `defineAnalyzer`
603
609
  * pattern: one file owns the SQL plan, the row plan, the typed `InputRow`
@@ -632,7 +638,7 @@ interface StrikingDistanceResult {
632
638
  /** Estimated clicks at ~15% CTR (the average for positions 1–3). */
633
639
  potentialClicks: number;
634
640
  }
635
- declare const strikingDistanceAnalyzer: DefinedAnalyzer;
641
+ declare const strikingDistanceAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
636
642
  /**
637
643
  * survival (Kaplan-Meier)
638
644
  *
@@ -660,7 +666,7 @@ interface SurvivalResult {
660
666
  medianTenure: number;
661
667
  curve: SurvivalCurvePoint[];
662
668
  }
663
- declare const survivalAnalyzer: DefinedAnalyzer;
669
+ declare const survivalAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
664
670
  /**
665
671
  * trends — weekly trajectory over a rolling window (default 28 weeks)
666
672
  */
@@ -682,7 +688,7 @@ interface TrendsResult {
682
688
  trend: TrendCategory;
683
689
  series: TrendSeriesPoint[];
684
690
  }
685
- declare const trendsAnalyzer: DefinedAnalyzer;
691
+ declare const trendsAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
686
692
  /**
687
693
  * `zero-click` — high impressions, low CTR, good ranking. SQL groups by
688
694
  * (query, url) and applies HAVING/WHERE pushdown; row reducer dedupes to the
@@ -697,157 +703,10 @@ interface ZeroClickResult {
697
703
  ctr: number;
698
704
  position: number;
699
705
  }
700
- declare const zeroClickAnalyzer: DefinedAnalyzer;
701
- interface AnalysisPeriod {
702
- startDate: string;
703
- endDate: string;
704
- }
706
+ declare const zeroClickAnalyzer: _$_gscdump_engine_analyzer0.DefinedAnalyzer;
705
707
  declare function keywordsQueryState(period: AnalysisPeriod, limit?: number): BuilderState;
706
708
  declare function pagesQueryState(period: AnalysisPeriod, limit?: number): BuilderState;
707
709
  declare function datesQueryState(period: AnalysisPeriod, limit?: number): BuilderState;
708
- /**
709
- * Capabilities a Plan may require of its host. A dispatcher matches these
710
- * against a source's declared capabilities and rejects mismatches.
711
- */
712
- type Capability = 'executeSql' | 'partitionedParquet' | 'attachedTables' | 'regex' | 'windowTotals' | 'comparisonJoin';
713
- interface SqlExtraQuery {
714
- name: string;
715
- sql: string;
716
- params: unknown[];
717
- }
718
- /**
719
- * SQL-native plan: SQL string + placeholders, with optional extra file sets
720
- * and follow-up queries. Mirrors the existing `AnalyzerSpec` shape but
721
- * renamed for clarity under the unified contract.
722
- */
723
- interface SqlPlan {
724
- kind: 'sql';
725
- sql: string;
726
- params: unknown[];
727
- current: FileSet$1;
728
- previous?: FileSet$1;
729
- extraFiles?: Record<string, FileSet$1>;
730
- extraQueries?: SqlExtraQuery[];
731
- /** Emits direct table refs (browser-only). Dispatcher rejects for manifest path. */
732
- requiresAttachedTables?: boolean;
733
- }
734
- interface TypedRowQuery<T extends Row = Row> {
735
- state: BuilderState;
736
- /** Optional type tag for downstream narrowing. */
737
- rowType?: (row: Row) => T;
738
- }
739
- /**
740
- * Row-queries plan: a named set of typed `BuilderState` queries. A portable
741
- * dispatcher runs each against a source's `queryRows` and hands the row
742
- * collection to `reduce`.
743
- */
744
- interface RowQueriesPlan {
745
- kind: 'rows';
746
- queries: Record<string, TypedRowQuery>;
747
- }
748
- type Plan = SqlPlan | RowQueriesPlan;
749
- interface ReduceContext<TRow extends Row = Row> {
750
- params: AnalysisParams;
751
- /** Extra SQL-query results keyed by `SqlExtraQuery.name`. */
752
- extras?: Record<string, TRow[]>;
753
- }
754
- /**
755
- * Unified analyzer contract. `TRow` lets authors narrow from the default
756
- * `Row = Record<string, unknown>` to a typed row shape (e.g. `KeywordRow`)
757
- * when their reducer assumes specific columns exist — catches drift between
758
- * `build` (SELECT list) and `reduce` (column access) at compile time.
759
- */
760
- interface Analyzer<P extends AnalysisParams = AnalysisParams, R = unknown, TRow extends Row = Row> {
761
- /** Stable tool id (e.g. `striking-distance`, `opportunity`). */
762
- id: string;
763
- /** Capabilities a host source must provide. */
764
- requires: readonly Capability[];
765
- /** Pure: params → plan. Snapshot-testable. */
766
- build: (params: P) => Plan;
767
- /** Pure: rows + context → typed result + meta. */
768
- reduce: (rows: TRow[] | Record<string, TRow[]>, ctx: ReduceContext<TRow>) => {
769
- results: R;
770
- meta?: Record<string, unknown>;
771
- };
772
- }
773
- interface SqlPlanSpec {
774
- sql: string;
775
- params: unknown[];
776
- current: FileSet$1;
777
- previous?: FileSet$1;
778
- extraFiles?: Record<string, FileSet$1>;
779
- extraQueries?: SqlExtraQuery[];
780
- requiresAttachedTables?: boolean;
781
- }
782
- interface ReduceCtx<InputRow> {
783
- /** Extra SQL-query results keyed by `SqlExtraQuery.name` (SQL path only). */
784
- extras?: Record<string, InputRow[]>;
785
- }
786
- type Reducer<Params, InputRow, Result> = (rows: InputRow[] | Record<string, InputRow[]>, params: Params, ctx: ReduceCtx<InputRow>) => {
787
- results: Result;
788
- meta?: Record<string, unknown>;
789
- };
790
- interface DefineAnalyzerOptions<Params extends AnalysisParams, InputRow, Result> {
791
- id: string;
792
- /**
793
- * Shared reducer used by both SQL and row paths. Use this when the
794
- * post-aggregation row count is small and filter/sort/derive can live in
795
- * one place. Mutually exclusive with `reduceSql` / `reduceRows`.
796
- */
797
- reduce?: Reducer<Params, InputRow, Result>;
798
- /** SQL-only reducer. Required when `buildSql` is set without `reduce`. */
799
- reduceSql?: Reducer<Params, InputRow, Result>;
800
- /** Row-only reducer. Required when `buildRows` is set without `reduce`. */
801
- reduceRows?: Reducer<Params, InputRow, Result>;
802
- /** SQL plan builder. Omit if the analyzer has no SQL path. */
803
- buildSql?: (params: Params) => SqlPlanSpec;
804
- /** Row plan builder. Omit if the analyzer has no row path. */
805
- buildRows?: (params: Params) => Record<string, BuilderState>;
806
- /** Capabilities required by the SQL plan. Defaults to `['executeSql', 'partitionedParquet']`. */
807
- sqlRequires?: readonly Capability[];
808
- /** Capabilities required by the row plan. Defaults to `[]`. */
809
- rowsRequires?: readonly Capability[];
810
- }
811
- interface DefinedAnalyzer {
812
- id: string;
813
- sql?: Analyzer;
814
- rows?: Analyzer;
815
- }
816
- declare function defineAnalyzer<Params extends AnalysisParams, InputRow, Result>(opts: DefineAnalyzerOptions<Params, InputRow, Result>): DefinedAnalyzer;
817
- interface AnalyzerVariants {
818
- sql?: Analyzer;
819
- rows?: Analyzer;
820
- }
821
- interface AnalyzerRegistryInit {
822
- rows?: readonly Analyzer[];
823
- sql?: readonly Analyzer[];
824
- }
825
- interface AnalyzerRegistry {
826
- listAnalyzerIds: () => readonly string[];
827
- getAnalyzerVariants: (id: string) => AnalyzerVariants | undefined;
828
- resolveAnalyzer: (id: string, sourceSupportsSql: boolean) => Analyzer | undefined;
829
- listAnalyzersFor: (sourceSupportsSql: boolean) => readonly Analyzer[];
830
- listAnalyzerIdsFor: (source: {
831
- executeSql?: unknown;
832
- }) => readonly string[];
833
- }
834
- /**
835
- * Build an immutable registry from collections of row / SQL analyzers.
836
- * No global state; call this once per logical use (typically at startup
837
- * or per-request in a worker).
838
- */
839
- declare function createAnalyzerRegistry(init?: AnalyzerRegistryInit): AnalyzerRegistry;
840
- declare class AnalyzerCapabilityError extends Error {
841
- readonly tool: string;
842
- readonly missing: readonly Capability[];
843
- constructor(tool: string, missing: readonly Capability[]);
844
- }
845
- /**
846
- * Run an analyzer against a generic `AnalysisQuerySource`. The registry is
847
- * an explicit parameter — callers build one via `createAnalyzerRegistry` (or
848
- * reuse `defaultAnalyzerRegistry` from the main barrel).
849
- */
850
- declare function runAnalyzerFromSource(source: AnalysisQuerySource, params: AnalysisParams, registry: AnalyzerRegistry): Promise<AnalysisResult>;
851
710
  /**
852
711
  * Pagination helpers shared across analyzers. SQL builders compose
853
712
  * `paginateClause` into their tail; row reducers use `paginateInMemory`
@@ -890,4 +749,4 @@ declare function resolveSort<K extends string>(input: {
890
749
  sortDir: 'asc' | 'desc';
891
750
  };
892
751
  declare const ROW_ANALYZERS: readonly Analyzer[];
893
- export { type Analyzer, AnalyzerCapabilityError, type AnalyzerRegistry, type AnalyzerRegistryInit, type AnalyzerVariants, type BayesianCtrResult, type BipartitePagerankNode, type BipartitePagerankResult, type BrandResultRow, type BrandSegmentationOptions, type BrandSegmentationResult, type BrandSummary, type CannibalizationCompetitor, type CannibalizationEvent, type CannibalizationOptions, type CannibalizationPage, type CannibalizationResult, type CannibalizationSortMetric, type Capability, type ChangePointResult, type ChangePointSeriesPoint, type ClusterType, type ClusteringOptions, type ClusteringResult, type ConcentrationInput, type ConcentrationItem, type ConcentrationOptions, type ConcentrationResult, type ConcentrationRiskLevel, type ContentVelocityWeek, type CtrAnomalyResult, type CtrAnomalySeriesPoint, type CtrCurveBucket, type CtrCurveOutlier, type DarkTrafficResult, type DataDetailResult, type DataQueryResult, type DecayInput, type DecayOptions, type DecayResult, type DecaySeriesPoint, type DecaySortMetric, type DefineAnalyzerOptions, type DefinedAnalyzer, type DeviceGapResult, type FileSet, type IntentAtlasResult, type KeywordBreadthResult, type KeywordCluster, type LongTailResult, type MonthlyData, type MoverData, type MoversInput, type MoversOptions, type MoversResult, type MoversResultRow, type MoversSeriesPoint, type MoversSortMetric, type OpportunityResult, type PaginateInput, type Plan, type PositionDistributionResult, type PositionVolatilityDay, type PositionVolatilityResult, type QueryMigrationExample, type QueryMigrationResult, ROW_ANALYZERS, type ReduceContext, type RowQueriesPlan, type SeasonalityMetric, type SeasonalityOptions, type SeasonalityResult, type SqlExtraQuery, type SqlPlan, type SqlPlanSpec, type StlDecomposeResult, type StlDecomposeSeriesPoint, type StrikingDistanceInputRow, type StrikingDistanceResult, type SurvivalCurvePoint, type SurvivalResult, type TrendCategory, type TrendSeriesPoint, type TrendsResult, type TypedRowQuery, type ZeroClickResult, bayesianCtrAnalyzer, bipartitePagerankAnalyzer, brandAnalyzer, cannibalizationAnalyzer, changePointAnalyzer, clampLimit, clampOffset, clusteringAnalyzer, concentrationAnalyzer, contentVelocityAnalyzer, createAnalyzerRegistry, ctrAnomalyAnalyzer, ctrCurveAnalyzer, darkTrafficAnalyzer, dataDetailAnalyzer, dataQueryAnalyzer, datesQueryState, decayAnalyzer, defineAnalyzer, deviceGapAnalyzer, intentAtlasAnalyzer, keywordBreadthAnalyzer, keywordsQueryState, longTailAnalyzer, moversAnalyzer, opportunityAnalyzer, pagesQueryState, paginateClause, paginateInMemory, positionDistributionAnalyzer, positionVolatilityAnalyzer, queryMigrationAnalyzer, resolveSort, runAnalyzerFromSource, seasonalityAnalyzer, stlDecomposeAnalyzer, strikingDistanceAnalyzer, survivalAnalyzer, trendsAnalyzer, zeroClickAnalyzer };
752
+ export { type BayesianCtrResult, type BipartitePagerankNode, type BipartitePagerankResult, type BrandResultRow, type BrandSegmentationOptions, type BrandSegmentationResult, type BrandSummary, type CannibalizationCompetitor, type CannibalizationEvent, type CannibalizationOptions, type CannibalizationPage, type CannibalizationResult, type CannibalizationSortMetric, type ChangePointResult, type ChangePointSeriesPoint, type ClusterType, type ClusteringOptions, type ClusteringResult, type ConcentrationInput, type ConcentrationItem, type ConcentrationOptions, type ConcentrationResult, type ConcentrationRiskLevel, type ContentVelocityWeek, type CtrAnomalyResult, type CtrAnomalySeriesPoint, type CtrCurveBucket, type CtrCurveOutlier, type DarkTrafficResult, type DataDetailResult, type DataQueryResult, type DecayInput, type DecayOptions, type DecayResult, type DecaySeriesPoint, type DecaySortMetric, type DeviceGapResult, type IntentAtlasResult, type KeywordBreadthResult, type KeywordCluster, type LongTailResult, type MonthlyData, type MoverData, type MoversInput, type MoversOptions, type MoversResult, type MoversResultRow, type MoversSeriesPoint, type MoversSortMetric, type OpportunityResult, type PaginateInput, type PositionDistributionResult, type PositionVolatilityDay, type PositionVolatilityResult, type QueryMigrationExample, type QueryMigrationResult, ROW_ANALYZERS, type SeasonalityMetric, type SeasonalityOptions, type SeasonalityResult, type StlDecomposeResult, type StlDecomposeSeriesPoint, type StrikingDistanceInputRow, type StrikingDistanceResult, type SurvivalCurvePoint, type SurvivalResult, type TrendCategory, type TrendSeriesPoint, type TrendsResult, type ZeroClickResult, bayesianCtrAnalyzer, bipartitePagerankAnalyzer, brandAnalyzer, cannibalizationAnalyzer, changePointAnalyzer, clampLimit, clampOffset, clusteringAnalyzer, concentrationAnalyzer, contentVelocityAnalyzer, ctrAnomalyAnalyzer, ctrCurveAnalyzer, darkTrafficAnalyzer, dataDetailAnalyzer, dataQueryAnalyzer, datesQueryState, decayAnalyzer, deviceGapAnalyzer, intentAtlasAnalyzer, keywordBreadthAnalyzer, keywordsQueryState, longTailAnalyzer, moversAnalyzer, opportunityAnalyzer, pagesQueryState, paginateClause, paginateInMemory, positionDistributionAnalyzer, positionVolatilityAnalyzer, queryMigrationAnalyzer, resolveSort, seasonalityAnalyzer, stlDecomposeAnalyzer, strikingDistanceAnalyzer, survivalAnalyzer, trendsAnalyzer, zeroClickAnalyzer };