@gscdump/engine-duckdb-wasm 0.40.2 → 1.0.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.
package/README.md CHANGED
@@ -23,19 +23,14 @@ import {
23
23
  attachParquetUrlTables,
24
24
  bootDuckDBWasm,
25
25
  createInsightRunner,
26
- resolveWindow,
27
- scopeFor,
28
- strikingMomentum,
29
26
  } from '@gscdump/engine-duckdb-wasm'
30
27
 
31
28
  const { db, conn } = await bootDuckDBWasm()
32
29
  await attachParquetUrlTables(conn, { tables: [{ name: 'queries', url: '/r2/queries.parquet' }] })
33
30
 
34
- const runner = createInsightRunner({ db, conn })
35
- const window = resolveWindow({ preset: 'last-30d', comparison: 'prev-period' })
36
- const scope = scopeFor('queries', { siteId, window })
37
-
38
- const rows = await strikingMomentum(runner, { ...scope, limit: 50 })
31
+ const runner = await createInsightRunner({ db, conn })
32
+ const client = await runner.client
33
+ const rows = await client.query('SELECT query, clicks, impressions FROM queries LIMIT 50')
39
34
  ```
40
35
 
41
36
  ## Browser Parquet Attachment Strategy
@@ -73,7 +68,6 @@ instead.
73
68
  - `createInsightRunner({ db, conn })` — drizzle-orm handle for typed `.select()` / window functions, with `sql\`...\`` raw escape hatch.
74
69
  - `bootDuckDBWasm()` / `attachParquetTables()` / `attachParquetUrlTables()` / `attachSingleTable()` / `createBrowserAnalysisRuntime()` / `createDuckDBBundlesFromBase()` / `listAttachedTables()` — browser runtime primitives.
75
70
  - `attachOpfsParquetTables()` / `readOpfsSnapshotFile()` / `estimateOpfsStorage()` / `requestPersistentStorage()` / `clearOpfsSnapshotCache()` — OPFS-backed parquet cache.
76
- - `strikingMomentum(runner, options)` — first-class browser insight.
77
71
  - `scopeFor(table, { siteId, window })` / `mergeScope()` — tenant scope predicates.
78
72
  - `pages` / `queries` / `page_queries` / `countries` / `dates` / `hourly_pages` / `schema` — drizzle schema mirroring `gscdump/analytics` `SCHEMAS`. Drift fails loudly at module load.
79
73
  - `compileArchetypeSql()` / `tableForArchetype()` — archetype query compilation.
@@ -83,7 +77,7 @@ instead.
83
77
  ## Related
84
78
 
85
79
  - [`@gscdump/engine`](../engine) — Storage contracts + dialect-neutral resolver.
86
- - [`@gscdump/analysis`](../analysis) — Analyzer registry + `analyzeContentGap` (browser semantic).
80
+ - [`@gscdump/analysis`](../analysis) — Portable analyzer registry and browser dispatch.
87
81
  - [`@gscdump/engine-sqlite`](../engine-sqlite) — SQLite / D1 counterpart.
88
82
 
89
83
  ## License
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Assume, DrizzleConfig, entityKind } from "drizzle-orm";
2
2
  import { PgAsyncDatabase, PgAsyncPreparedQuery, PgAsyncSession, PgDialect, PgQueryResultHKT } from "drizzle-orm/pg-core";
3
3
  import { AnyRelations, EmptyRelations, ExtractTablesWithRelations, Schema as Schema$1 } from "drizzle-orm/relations";
4
- import { DrizzleSchema as Schema, countries, dates, drizzleSchema as schema, hourly_pages, page_queries, pages, queries } from "@gscdump/engine/schema";
5
4
  import { ScopedRunnerOptions, TableScope } from "@gscdump/engine/scope";
5
+ import { DrizzleSchema as Schema, countries, dates, drizzleSchema as schema, hourly_pages, page_queries, pages, queries } from "@gscdump/engine/schema";
6
6
  import { AnalyzerRegistry } from "@gscdump/engine/analyzer";
7
7
  import { Result } from "gscdump/result";
8
8
  import { ComparisonMode, ResolveWindowOptions, ResolvedWindow, WindowPreset, resolveWindow } from "@gscdump/engine/period";
@@ -41,49 +41,6 @@ interface DuckDBWasmDrizzleDatabase<TSchema extends Schema$1 = Record<string, ne
41
41
  $client: Promise<DuckDBWasmClient>;
42
42
  }
43
43
  declare function drizzle<TSchema extends Schema$1 = Record<string, never>, TRelations extends AnyRelations = SchemaRelations<TSchema>>(client: Promise<DuckDBWasmClient> | DuckDBWasmClient, config?: DrizzleConfig<TSchema, TRelations>): DuckDBWasmDrizzleDatabase<TSchema, TRelations>;
44
- interface InsightRunnerOptions {
45
- db: AsyncDuckDB;
46
- conn: AsyncDuckDBConnection;
47
- logger?: boolean;
48
- }
49
- interface InsightRunner {
50
- db: DuckDBWasmDrizzleDatabase<Schema>;
51
- client: Promise<DuckDBWasmClient>;
52
- close: () => Promise<void>;
53
- }
54
- declare function createInsightRunner(opts: InsightRunnerOptions): Promise<InsightRunner>;
55
- /**
56
- * Build a per-table predicate set from {siteId, window}. The returned
57
- * `wherePredicates` composes with user-level filters via `mergeScope`.
58
- *
59
- * Note: the current SCHEMAS don't include `site_id` on any table (snapshots
60
- * are already per-site), so `siteId` is a no-op for now — kept in the API
61
- * so consumers can add the predicate without an interface change when
62
- * multi-site snapshots land.
63
- */
64
- declare const scopeFor: (table: "pages" | "queries" | "countries" | "page_queries" | "dates" | "search_appearance" | "search_appearance_pages" | "search_appearance_queries" | "search_appearance_page_queries" | "hourly_pages", opts: ScopedRunnerOptions) => TableScope, mergeScope: typeof import("@gscdump/engine/scope").mergeScope;
65
- interface StrikingMomentumOptions {
66
- /** Anchor date (YYYY-MM-DD). Defaults to today. */
67
- anchor?: string;
68
- /** Width of each window in days. Default 90. */
69
- windowDays?: number;
70
- /** Minimum impressions in the prior window for a row to qualify. Default 10. */
71
- minPriorImpressions?: number;
72
- /** Minimum impressions in the recent window. Default 50. */
73
- minRecentImpressions?: number;
74
- /** Result limit. Default 20. */
75
- limit?: number;
76
- }
77
- interface StrikingMomentumRow {
78
- query: string;
79
- url: string;
80
- recent_impr: number;
81
- recent_pos: number;
82
- prior_impr: number;
83
- prior_pos: number;
84
- momentum_score: number;
85
- }
86
- declare function strikingMomentum(runner: InsightRunner, opts?: StrikingMomentumOptions): Promise<StrikingMomentumRow[]>;
87
44
  /** A parquet data file to materialise into OPFS. */
88
45
  interface OpfsParquetFile {
89
46
  /** Same-origin URL carrying a signed size hint + short-lived access token. */
@@ -309,6 +266,27 @@ declare function overlayViewBody(args: {
309
266
  overlaySelect: string | null;
310
267
  materializeLake?: boolean;
311
268
  }): string | null;
269
+ interface InsightRunnerOptions {
270
+ db: AsyncDuckDB;
271
+ conn: AsyncDuckDBConnection;
272
+ logger?: boolean;
273
+ }
274
+ interface InsightRunner {
275
+ db: DuckDBWasmDrizzleDatabase<Schema>;
276
+ client: Promise<DuckDBWasmClient>;
277
+ close: () => Promise<void>;
278
+ }
279
+ declare function createInsightRunner(opts: InsightRunnerOptions): Promise<InsightRunner>;
280
+ /**
281
+ * Build a per-table predicate set from {siteId, window}. The returned
282
+ * `wherePredicates` composes with user-level filters via `mergeScope`.
283
+ *
284
+ * Note: the current SCHEMAS don't include `site_id` on any table (snapshots
285
+ * are already per-site), so `siteId` is a no-op for now — kept in the API
286
+ * so consumers can add the predicate without an interface change when
287
+ * multi-site snapshots land.
288
+ */
289
+ declare const scopeFor: (table: "pages" | "queries" | "countries" | "page_queries" | "dates" | "search_appearance" | "search_appearance_pages" | "search_appearance_queries" | "search_appearance_page_queries" | "hourly_pages", opts: ScopedRunnerOptions) => TableScope, mergeScope: typeof import("@gscdump/engine/scope").mergeScope;
312
290
  interface QueryResult {
313
291
  rows: Record<string, unknown>[];
314
292
  queryMs: number;
@@ -514,4 +492,4 @@ declare function createBrowserAnalysisRuntime(boot: DuckDBWasmBootResult, option
514
492
  version?: number | string;
515
493
  attachedTables?: readonly string[];
516
494
  }): BrowserAnalysisRuntime;
517
- export { type AnalyzeResult, type AttachOpfsTablesOptions, type AttachParquetTablesOptions, type AttachParquetUrlTablesOptions, type AttachedTablesHandle, type BootDuckDBWasmOptions, type BrowserAnalysisRuntime, BrowserAttachBudgetExceededError, type BrowserAttachError, type BrowserParquetFile, type BrowserParquetTable, type BrowserParquetUrlTable, type ComparisonMode, type CompiledArchetypeSql, type DuckDBWasmBootResult, type DuckDBWasmClient, DuckDBWasmDatabase, type DuckDBWasmDrizzleDatabase, type InsightRunner, type InsightRunnerOptions, type OpfsAttachTiming, type OpfsAttachTimingStage, type OpfsAttachedHandle, type OpfsFileProgress, type OpfsParquetFile, type OpfsParquetTable, OpfsQuotaExceededError, type QueryResult, type ResolveWindowOptions, type ResolvedWindow, type Schema, type ScopedRunnerOptions, type StrikingMomentumOptions, type StrikingMomentumRow, type TableScope, type WindowPreset, attachOpfsParquetTables, attachParquetTables, attachParquetUrlTables, attachParquetUrlTablesResult, bootDuckDBWasm, browserAttachErrors, clearOpfsSnapshotCache, compileArchetypeSql, countries, createBrowserAnalysisRuntime, createClient, createInsightRunner, dates, drizzle, estimateOpfsStorage, hourly_pages, isBrowserAttachError, mergeScope, overlayViewBody, page_queries, pages, queries, readOpfsSnapshotFile, requestPersistentStorage, resolveWindow, schema, scopeFor, strikingMomentum, tableForArchetype };
495
+ export { type AnalyzeResult, type AttachOpfsTablesOptions, type AttachParquetTablesOptions, type AttachParquetUrlTablesOptions, type AttachedTablesHandle, type BootDuckDBWasmOptions, type BrowserAnalysisRuntime, BrowserAttachBudgetExceededError, type BrowserAttachError, type BrowserParquetFile, type BrowserParquetTable, type BrowserParquetUrlTable, type ComparisonMode, type CompiledArchetypeSql, type DuckDBWasmBootResult, type DuckDBWasmClient, DuckDBWasmDatabase, type DuckDBWasmDrizzleDatabase, type InsightRunner, type InsightRunnerOptions, type OpfsAttachTiming, type OpfsAttachTimingStage, type OpfsAttachedHandle, type OpfsFileProgress, type OpfsParquetFile, type OpfsParquetTable, OpfsQuotaExceededError, type QueryResult, type ResolveWindowOptions, type ResolvedWindow, type Schema, type ScopedRunnerOptions, type TableScope, type WindowPreset, attachOpfsParquetTables, attachParquetTables, attachParquetUrlTables, attachParquetUrlTablesResult, bootDuckDBWasm, browserAttachErrors, clearOpfsSnapshotCache, compileArchetypeSql, countries, createBrowserAnalysisRuntime, createClient, createInsightRunner, dates, drizzle, estimateOpfsStorage, hourly_pages, isBrowserAttachError, mergeScope, overlayViewBody, page_queries, pages, queries, readOpfsSnapshotFile, requestPersistentStorage, resolveWindow, schema, scopeFor, tableForArchetype };
package/dist/index.mjs CHANGED
@@ -1,10 +1,9 @@
1
1
  import { arrowToRows } from "@gscdump/engine/arrow";
2
- import { DefaultLogger, NoopLogger, entityKind, sql } from "drizzle-orm";
2
+ import { DefaultLogger, NoopLogger, entityKind } from "drizzle-orm";
3
3
  import { PgAsyncDatabase, PgAsyncPreparedQuery, PgAsyncSession, PgDialect } from "drizzle-orm/pg-core";
4
4
  import { buildRelations } from "drizzle-orm/relations";
5
- import { toIsoDate } from "gscdump/dates";
6
- import { countries, dates, drizzleSchema as schema, hourly_pages, page_queries, pages, queries } from "@gscdump/engine/schema";
7
5
  import { createScopedHelpers } from "@gscdump/engine/scope";
6
+ import { countries, dates, drizzleSchema as schema, hourly_pages, page_queries, pages, queries } from "@gscdump/engine/schema";
8
7
  import { runAnalyzerFromSource } from "@gscdump/engine/analyzer";
9
8
  import { pgResolverAdapter } from "@gscdump/engine/resolver";
10
9
  import { createAttachedTableSource } from "@gscdump/engine/source";
@@ -442,67 +441,6 @@ function drizzle(client, config = {}) {
442
441
  db.$client = clientPromise;
443
442
  return db;
444
443
  }
445
- async function strikingMomentum(runner, opts = {}) {
446
- const windowDays = opts.windowDays ?? 90;
447
- const anchor = opts.anchor ?? toIsoDate(/* @__PURE__ */ new Date());
448
- const minPrior = opts.minPriorImpressions ?? 10;
449
- const minRecent = opts.minRecentImpressions ?? 50;
450
- const limit = opts.limit ?? 20;
451
- const windowExpr = sql`
452
- WITH pk AS (
453
- SELECT
454
- query,
455
- url,
456
- ${page_queries.date} AS date,
457
- ${page_queries.impressions} AS impressions,
458
- ${page_queries.sum_position} AS sum_position,
459
- CASE
460
- WHEN ${page_queries.date} >= (DATE ${sql.raw(`'${anchor}'`)} - INTERVAL ${sql.raw(`${windowDays}`)} DAY)
461
- THEN 'recent' ELSE 'prior'
462
- END AS period
463
- FROM ${page_queries}
464
- WHERE ${page_queries.date} >= (DATE ${sql.raw(`'${anchor}'`)} - INTERVAL ${sql.raw(`${windowDays * 2}`)} DAY)
465
- AND ${page_queries.date} < (DATE ${sql.raw(`'${anchor}'`)} + INTERVAL 1 DAY)
466
- ),
467
- agg AS (
468
- SELECT
469
- query, url, period,
470
- SUM(impressions) AS impr,
471
- SUM(sum_position) / NULLIF(SUM(impressions), 0) + 1 AS weighted_pos
472
- FROM pk
473
- GROUP BY query, url, period
474
- ),
475
- paired AS (
476
- SELECT
477
- query, url,
478
- MAX(CASE WHEN period = 'recent' THEN impr END) AS recent_impr,
479
- MAX(CASE WHEN period = 'recent' THEN weighted_pos END) AS recent_pos,
480
- MAX(CASE WHEN period = 'prior' THEN impr END) AS prior_impr,
481
- MAX(CASE WHEN period = 'prior' THEN weighted_pos END) AS prior_pos
482
- FROM agg
483
- GROUP BY query, url
484
- ),
485
- best AS (
486
- SELECT
487
- query, url, recent_impr, recent_pos, prior_impr, prior_pos,
488
- ROW_NUMBER() OVER (PARTITION BY query ORDER BY recent_impr DESC NULLS LAST) AS rn
489
- FROM paired
490
- WHERE prior_impr >= ${minPrior} AND recent_impr >= ${minRecent}
491
- )
492
- SELECT
493
- query, url,
494
- recent_impr, recent_pos, prior_impr, prior_pos,
495
- (prior_pos - recent_pos)
496
- * LN(recent_impr + 1)
497
- * CASE WHEN recent_pos BETWEEN 8 AND 20 THEN 1.5 ELSE 1.0 END
498
- AS momentum_score
499
- FROM best
500
- WHERE rn = 1
501
- ORDER BY momentum_score DESC NULLS LAST
502
- LIMIT ${limit}
503
- `;
504
- return await runner.db.execute(windowExpr);
505
- }
506
444
  function createOpfsHandleRegistry(backend) {
507
445
  const entries = /* @__PURE__ */ new Map();
508
446
  const pending = /* @__PURE__ */ new Map();
@@ -1616,4 +1554,4 @@ function createBrowserAnalysisRuntime(boot, options = {}) {
1616
1554
  }
1617
1555
  };
1618
1556
  }
1619
- export { BrowserAttachBudgetExceededError, DuckDBWasmDatabase, OpfsQuotaExceededError, attachOpfsParquetTables, attachParquetTables, attachParquetUrlTables, attachParquetUrlTablesResult, bootDuckDBWasm, browserAttachErrors, clearOpfsSnapshotCache, compileArchetypeSql, countries, createBrowserAnalysisRuntime, createClient, createInsightRunner, dates, drizzle, estimateOpfsStorage, hourly_pages, isBrowserAttachError, mergeScope, overlayViewBody, page_queries, pages, queries, readOpfsSnapshotFile, requestPersistentStorage, resolveWindow, schema, scopeFor, strikingMomentum, tableForArchetype };
1557
+ export { BrowserAttachBudgetExceededError, DuckDBWasmDatabase, OpfsQuotaExceededError, attachOpfsParquetTables, attachParquetTables, attachParquetUrlTables, attachParquetUrlTablesResult, bootDuckDBWasm, browserAttachErrors, clearOpfsSnapshotCache, compileArchetypeSql, countries, createBrowserAnalysisRuntime, createClient, createInsightRunner, dates, drizzle, estimateOpfsStorage, hourly_pages, isBrowserAttachError, mergeScope, overlayViewBody, page_queries, pages, queries, readOpfsSnapshotFile, requestPersistentStorage, resolveWindow, schema, scopeFor, tableForArchetype };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/engine-duckdb-wasm",
3
3
  "type": "module",
4
- "version": "0.40.2",
4
+ "version": "1.0.0",
5
5
  "description": "DuckDB-WASM engine adapter for @gscdump/analysis — typed browser analytics against parquet via R2.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -33,10 +33,10 @@
33
33
  "dist"
34
34
  ],
35
35
  "engines": {
36
- "node": ">=18"
36
+ "node": ">=22"
37
37
  },
38
38
  "peerDependencies": {
39
- "@duckdb/duckdb-wasm": "^1.32.0"
39
+ "@duckdb/duckdb-wasm": "^1.33.1-dev57.0"
40
40
  },
41
41
  "peerDependenciesMeta": {
42
42
  "@duckdb/duckdb-wasm": {
@@ -45,12 +45,12 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "drizzle-orm": "1.0.0-rc.3",
48
- "gscdump": "0.40.2",
49
- "@gscdump/engine": "0.40.2",
50
- "@gscdump/contracts": "0.40.2"
48
+ "@gscdump/contracts": "^1.0.0",
49
+ "gscdump": "^1.0.0",
50
+ "@gscdump/engine": "^1.0.0"
51
51
  },
52
52
  "devDependencies": {
53
- "@duckdb/duckdb-wasm": "^1.32.0",
53
+ "@duckdb/duckdb-wasm": "1.33.1-dev57.0",
54
54
  "@vitest/browser": "^4.1.10",
55
55
  "@vitest/browser-playwright": "^4.1.10",
56
56
  "playwright": "^1.61.1",