@gscdump/engine-duckdb-wasm 1.4.0 → 1.4.2

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/index.d.mts CHANGED
@@ -1,495 +1,11 @@
1
- import { Assume, DrizzleConfig, entityKind } from "drizzle-orm";
2
- import { PgAsyncDatabase, PgAsyncPreparedQuery, PgAsyncSession, PgDialect, PgQueryResultHKT } from "drizzle-orm/pg-core";
3
- import { AnyRelations, EmptyRelations, ExtractTablesWithRelations, Schema as Schema$1 } from "drizzle-orm/relations";
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
- import { AnalyzerRegistry } from "@gscdump/engine/analyzer";
7
- import { Result } from "gscdump/result";
1
+ import { CompiledArchetypeSql, compileArchetypeSql, tableForArchetype } from "./archetype-sql.mjs";
2
+ import { DuckDBWasmClient, createClient } from "./drizzle-adapter/client.mjs";
3
+ import { DuckDBWasmDatabase, DuckDBWasmDrizzleDatabase, drizzle } from "./drizzle-adapter/driver.mjs";
4
+ import "./drizzle-adapter/index.mjs";
5
+ import { AttachOpfsTablesOptions, OpfsAttachTiming, OpfsAttachTimingStage, OpfsAttachedHandle, OpfsFileProgress, OpfsParquetFile, OpfsParquetTable, OpfsQuotaExceededError, attachOpfsParquetTables, clearOpfsSnapshotCache, estimateOpfsStorage, readOpfsSnapshotFile, requestPersistentStorage } from "./opfs.mjs";
6
+ import { overlayViewBody } from "./overlay-view.mjs";
7
+ import { Schema, countries, dates, hourly_pages, page_queries, pages, queries, schema } from "./schema.mjs";
8
+ import { InsightRunner, InsightRunnerOptions, ScopedRunnerOptions, TableScope, createInsightRunner, mergeScope, scopeFor } from "./runner.mjs";
9
+ import { AnalyzeResult, AttachParquetTablesOptions, AttachParquetUrlTablesOptions, AttachedTablesHandle, BootDuckDBWasmOptions, BrowserAnalysisRuntime, BrowserAttachBudgetExceededError, BrowserAttachError, BrowserParquetFile, BrowserParquetTable, BrowserParquetUrlTable, DuckDBWasmBootResult, QueryResult, attachParquetTables, attachParquetUrlTables, attachParquetUrlTablesResult, bootDuckDBWasm, browserAttachErrors, createBrowserAnalysisRuntime, isBrowserAttachError } from "./runtime.mjs";
8
10
  import { ComparisonMode, ResolveWindowOptions, ResolvedWindow, WindowPreset, resolveWindow } from "@gscdump/engine/period";
9
- import { ArchetypeQuery } from "@gscdump/contracts/archetypes";
10
- import { AsyncDuckDB, AsyncDuckDBConnection, DuckDBBundles, DuckDBConfig } from "@duckdb/duckdb-wasm";
11
- import { AnalysisParams } from "@gscdump/engine/analysis-types";
12
- /** A compiled, parameterised statement. */
13
- interface CompiledArchetypeSql {
14
- sql: string;
15
- params: unknown[];
16
- /** The fact-table view the query reads. */
17
- table: string;
18
- }
19
- /**
20
- * Compile one archetype query to DuckDB SQL. Throws for `aux-cloud-only`.
21
- */
22
- declare function compileArchetypeSql(query: ArchetypeQuery): CompiledArchetypeSql;
23
- /** The fact-table view an archetype reads — drives per-table browser routing. */
24
- declare function tableForArchetype(query: ArchetypeQuery): string | null;
25
- interface DuckDBWasmClient {
26
- db: AsyncDuckDB;
27
- conn: AsyncDuckDBConnection;
28
- query: (sql: string, params?: unknown[]) => Promise<Record<string, unknown>[]>;
29
- close: () => Promise<void>;
30
- }
31
- declare function createClient(db: AsyncDuckDB, conn: AsyncDuckDBConnection): Promise<DuckDBWasmClient>;
32
- type Row = Record<string, unknown>;
33
- interface DuckDBWasmQueryResultHKT extends PgQueryResultHKT {
34
- type: Assume<this['row'], Row>[];
35
- }
36
- type SchemaRelations<TSchema extends Schema$1> = ExtractTablesWithRelations<Record<string, never>, TSchema>;
37
- declare class DuckDBWasmDatabase<TRelations extends AnyRelations = EmptyRelations> extends PgAsyncDatabase<DuckDBWasmQueryResultHKT, TRelations> {
38
- static readonly [entityKind]: string;
39
- }
40
- interface DuckDBWasmDrizzleDatabase<TSchema extends Schema$1 = Record<string, never>, TRelations extends AnyRelations = SchemaRelations<TSchema>> extends DuckDBWasmDatabase<TRelations> {
41
- $client: Promise<DuckDBWasmClient>;
42
- }
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
- /** A parquet data file to materialise into OPFS. */
45
- interface OpfsParquetFile {
46
- /** Same-origin URL carrying a signed size hint + short-lived access token. */
47
- url: string;
48
- /** Expected byte size — drives progress + a cheap pre-verify shortcut. */
49
- bytes: number;
50
- /**
51
- * Opaque content-stable identifier for this file (e.g. the Iceberg data-
52
- * file object key). Encoded into the OPFS filename so the same hash is the
53
- * same cache entry. NOT required to be a SHA-256. When omitted, the cache
54
- * key falls back to `(table, index)` and only the byte size is verified
55
- * (degraded — stale entries can survive a content change).
56
- */
57
- contentHash?: string;
58
- /** Row count — diagnostics only. */
59
- rowCount?: number;
60
- }
61
- /** One logical table and the parquet files that compose it. */
62
- interface OpfsParquetTable {
63
- /** Iceberg table name — becomes the DuckDB view name. */
64
- table: string;
65
- files: OpfsParquetFile[];
66
- /**
67
- * Recent-window overlay parquet (the non-stable tail the lake excludes). When
68
- * present it is materialised into OPFS alongside `files` and the view unions
69
- * it with an anti-join dedup: the lake (`files`) serves every day it has, the
70
- * overlay serves ONLY days the lake lacks. So a stale overlay whose days have
71
- * since landed in the lake can't double-count, and a day that stabilised but
72
- * isn't yet in the lake still serves from the overlay. Its `contentHash` must
73
- * change when the overlay bytes change (it is overwritten in place) so the
74
- * cache re-downloads.
75
- */
76
- overlay?: OpfsParquetFile;
77
- }
78
- interface AttachOpfsTablesOptions {
79
- db: AsyncDuckDB;
80
- conn: AsyncDuckDBConnection;
81
- tables: OpfsParquetTable[];
82
- /** DuckDB schema the views are created in. Default `main`. */
83
- schema?: string;
84
- /** `fetch` override (tests). Default `globalThis.fetch`. */
85
- fetch?: typeof fetch;
86
- /** Request init for the parquet downloads (auth headers, credentials mode). */
87
- fetchInit?: RequestInit;
88
- /** Caps simultaneous downloads. Default 2. */
89
- fetchConcurrency?: number;
90
- /** Abort signal threaded through downloads + registration. */
91
- signal?: AbortSignal;
92
- /** Snapshot version associated with this file set — echoed on the handle. */
93
- version?: string;
94
- /** Ticks once per file as it lands in OPFS + registers. UI progress. */
95
- onFileProgress?: (info: OpfsFileProgress) => void;
96
- /**
97
- * Low-volume diagnostics for the OPFS attach waterfall. This is intentionally
98
- * phase-level rather than a logger so hosts can join it with their own route
99
- * timings without parsing console text.
100
- */
101
- onTiming?: (info: OpfsAttachTiming) => void;
102
- /**
103
- * Serializer for the operations that mutate the DuckDB-WASM virtual
104
- * filesystem / catalog (`registerFileHandle`, `dropFile`, `CREATE`/`DROP
105
- * VIEW`) — those are not concurrency-safe across consumers sharing one
106
- * `AsyncDuckDB`. Callers with a shared DB pass their global attach mutex
107
- * here so ONLY these mutations serialize; the parquet downloads (network +
108
- * OPFS writes, no DB interaction) run outside the lock and overlap across
109
- * concurrent attaches. Wrapping the whole `attachOpfsParquetTables` call in
110
- * the mutex instead serializes every table's downloads end-to-end — the
111
- * dominant cold-load cost.
112
- *
113
- * The returned handle's `detach()` is NOT routed through this — callers
114
- * that pass a lock typically already hold it around teardown, and the lock
115
- * is not reentrant.
116
- *
117
- * Default: run inline (caller owns the DB exclusively).
118
- */
119
- withDb?: <T>(fn: () => Promise<T>) => Promise<T>;
120
- /**
121
- * Recover a table degraded by an OPFS sync-access-handle / write conflict
122
- * (the multi-tab case — another tab holds the file's exclusive handle) by
123
- * reading the already-cached bytes via the lock-free File API (or HTTP on a
124
- * genuine cache miss) and registering them as in-memory buffers, so the table
125
- * attaches from the shared cache instead of being pushed back to the caller.
126
- * Quota / incomplete degradations are NEVER recovered this way — buffering a
127
- * quota-exceeding set risks OOM, and the caller routes those to its tail.
128
- * Default true.
129
- */
130
- recoverContention?: boolean;
131
- }
132
- interface OpfsFileProgress {
133
- table: string;
134
- /** OPFS file name. */
135
- file: string;
136
- /** Index within the flat file list. */
137
- index: number;
138
- /** Total files across all tables. */
139
- total: number;
140
- /** Bytes of this file (cumulative caller-side). */
141
- bytes: number;
142
- /** `'cache-hit'` — already in OPFS, verified; `'downloaded'` — fetched. */
143
- outcome: 'cache-hit' | 'downloaded';
144
- /** Time spent probing/downloading/writing this file before DuckDB registration. */
145
- materialiseMs?: number;
146
- /** Time spent inside DuckDB's file-registration mutation lock for this file. */
147
- registerMs?: number;
148
- /** End-to-end file phase time, materialise + register + callback overhead. */
149
- totalMs?: number;
150
- }
151
- type OpfsAttachTimingStage = 'persist' | 'root' | 'plan' | 'duckdb-import' | 'sweep' | 'materialise' | 'register' | 'downloads' | 'view' | 'recovery' | 'total';
152
- interface OpfsAttachTiming {
153
- stage: OpfsAttachTimingStage;
154
- durationMs: number;
155
- table?: string;
156
- file?: string;
157
- files?: number;
158
- tables?: number;
159
- bytes?: number;
160
- outcome?: 'cache-hit' | 'downloaded';
161
- }
162
- /** Handle returned from {@link attachOpfsParquetTables}. */
163
- interface OpfsAttachedHandle {
164
- version: string | undefined;
165
- /** Tables that successfully attached (a per-table failure drops only that table). */
166
- tables: string[];
167
- schema: string;
168
- /** Total bytes materialised into OPFS for this attach. */
169
- bytesAttached: number;
170
- /**
171
- * Tables that could NOT be attached because OPFS ran out of quota. The
172
- * caller routes these to the server tail. Empty on a clean attach.
173
- */
174
- degradedTables: string[];
175
- /**
176
- * Why each degraded table degraded. 'quota' is actionable (the caller can
177
- * reclaim space via `clearOpfsSnapshotCache` and retry once); 'contention'
178
- * and 'incomplete' are transient multi-tab races the buffer fallback
179
- * already absorbs.
180
- */
181
- degradeReasons: Partial<Record<string, 'quota' | 'contention' | 'incomplete'>>;
182
- /** Detach the created views + release the registered OPFS file handles. */
183
- detach: () => Promise<void>;
184
- }
185
- /**
186
- * Raised when OPFS cannot hold the file set. Carries the partial state so the
187
- * caller can degrade — attach what fit, route the rest server-side.
188
- */
189
- declare class OpfsQuotaExceededError extends Error {
190
- name: string;
191
- /** Tables that did not fit. */
192
- readonly degradedTables: string[];
193
- constructor(message: string, degradedTables: string[]);
194
- }
195
- /**
196
- * Request persistent storage so the browser is less likely to evict the OPFS
197
- * cache under pressure. Returns the granted state — `false` is normal for an
198
- * un-engaged origin and is NOT an error; it just means eviction is possible.
199
- */
200
- declare function requestPersistentStorage(): Promise<boolean>;
201
- /** Best-effort `{ usageBytes, quotaBytes }` from the Storage API. */
202
- declare function estimateOpfsStorage(): Promise<{
203
- usageBytes?: number;
204
- quotaBytes?: number;
205
- }>;
206
- /**
207
- * Read a content-addressed OPFS snapshot file via the async File API and return
208
- * its bytes, or null when absent / size-mismatched (partial / stale write).
209
- *
210
- * `getFile()` takes NO lock — unlike DuckDB's `BROWSER_FSACCESS` sync access
211
- * handle — so it reads cleanly while ANOTHER tab holds the same file open. That
212
- * is the basis for cross-tab cache sharing: a tab that loses the exclusive-handle
213
- * race reads the shared cached bytes here instead of re-downloading. The
214
- * filename derivation is the SAME `opfsFileName` + `contentHashSlug` the attach
215
- * path writes, so consumers reuse the engine's naming with no replicated slug
216
- * logic to drift out of lock-step. `index` is only the disambiguator for the
217
- * degraded no-`contentHash` fallback (mirrors `attachOpfsParquetTables`).
218
- */
219
- declare function readOpfsSnapshotFile(table: string, contentHash: string | undefined, index: number, expectedBytes: number): Promise<Uint8Array | null>;
220
- /**
221
- * Download every parquet file in `tables` into OPFS, content-hash verify, and
222
- * attach them as DuckDB-WASM views. Attach-once: call this once per
223
- * `(site, table)` span; re-query without re-attaching for filter / range
224
- * changes inside the span.
225
- *
226
- * Quota handling: a `QuotaExceededError` while writing a table's files does
227
- * NOT throw — that table is recorded in `degradedTables` and skipped; the
228
- * caller routes it to the server tail. The remaining tables still attach.
229
- */
230
- declare function attachOpfsParquetTables(options: AttachOpfsTablesOptions): Promise<OpfsAttachedHandle>;
231
- /**
232
- * Delete every OPFS entry this module created. Used to reclaim space after a
233
- * quota error, or to force a clean re-download. Best-effort — missing entries
234
- * are ignored.
235
- */
236
- declare function clearOpfsSnapshotCache(): Promise<void>;
237
- /**
238
- * Browser-side recent-overlay merge-on-read SQL — shared by the OPFS attach path
239
- * (`opfs.ts`) and the in-memory buffer attach path (consumers'
240
- * `registerParquetView`).
241
- *
242
- * The lake serves every day it has; the overlay serves ONLY days the lake lacks
243
- * (`date NOT IN (SELECT DISTINCT date FROM lake)`), unioned with
244
- * `UNION ALL BY NAME`. This is the browser sibling of the server's
245
- * `overlayMergeEnvelope` (in gscdump.com); kept SEPARATE because the browser path
246
- * can read the lake once via a `MATERIALIZED` CTE (CPU-bound DuckDB-WASM, bounded
247
- * per-site buffers) where the server's many-s3-file reads prefer projection
248
- * pushdown over a re-scan.
249
- *
250
- * Both `lakeSelect` / `overlaySelect` must already expose a `date` column cast to
251
- * DATE (the overlay stores ISO strings; `SELECT * REPLACE (CAST(date AS DATE) AS
252
- * date)`), so `UNION ALL BY NAME` merges them type-uniformly.
253
- */
254
- /**
255
- * The view BODY (no `CREATE VIEW` wrapper) merging a base lake relation and a
256
- * recent overlay. Returns null when neither side exists; the lake verbatim with
257
- * no overlay; the overlay verbatim with no lake (every recent row is wanted).
258
- *
259
- * `materializeLake` (default true): wrap the lake in a `MATERIALIZED` CTE so it is
260
- * scanned ONCE and reused for both the served rows and the anti-join date set — a
261
- * plain CTE inlines and re-scans the parquet, the dominant cost in DuckDB-WASM.
262
- * Set false to keep the streaming re-scan shape (lower peak memory, two scans).
263
- */
264
- declare function overlayViewBody(args: {
265
- lakeSelect: string | null;
266
- overlaySelect: string | null;
267
- materializeLake?: boolean;
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: "countries" | "dates" | "hourly_pages" | "page_queries" | "pages" | "queries" | "search_appearance" | "search_appearance_page_queries" | "search_appearance_pages" | "search_appearance_queries", opts: ScopedRunnerOptions) => TableScope, mergeScope: typeof import("@gscdump/engine/scope").mergeScope;
290
- interface QueryResult {
291
- rows: Record<string, unknown>[];
292
- queryMs: number;
293
- }
294
- interface AnalyzeResult {
295
- results: Record<string, unknown>[];
296
- meta: Record<string, unknown>;
297
- queryMs: number;
298
- }
299
- interface DuckDBWasmBootResult {
300
- db: AsyncDuckDB;
301
- conn: AsyncDuckDBConnection;
302
- }
303
- interface BootDuckDBWasmOptions {
304
- /**
305
- * DuckDB-WASM logger. Defaults to a `ConsoleLogger` thresholded at
306
- * `LogLevel.WARNING`, so real warnings/errors still surface but the per-query
307
- * INFO events (START/OK/RUN) — which DuckDB's default `ConsoleLogger()` emits
308
- * as raw objects, flooding the host console with dozens of lines per render —
309
- * are dropped. Pass `new ConsoleLogger(LogLevel.DEBUG)` to see everything, or
310
- * `new VoidLogger()` to silence it entirely.
311
- */
312
- logger?: unknown;
313
- /**
314
- * Override the jsDelivr-hosted bundle map. Required in environments where
315
- * the default CDN is unreachable or where hosts must serve the WASM +
316
- * worker assets themselves (e.g. Cloudflare Workers' 25 MB per-asset cap).
317
- */
318
- bundles?: DuckDBBundles;
319
- /**
320
- * Extra DuckDB open config. The browser runtime always forces HTTP files
321
- * into range-only mode (reliable HEAD probes, no full HTTP fallback) so a
322
- * server that cannot answer bounded reads fails closed.
323
- */
324
- config?: DuckDBConfig;
325
- /**
326
- * Cap DuckDB's memory with `SET memory_limit=<value>` right after open (e.g.
327
- * `'2GB'`, `'512MB'`). A runaway query then errors with a clean
328
- * out-of-memory rather than growing the WASM heap until the tab crashes —
329
- * DuckDB has no statement-level timeout, so abandoned queries are otherwise
330
- * only stopped by the caller's `AbortSignal` (which the runtime forwards to
331
- * `conn.cancelSent()`). Opt-in: omit to keep DuckDB-WASM's default sizing.
332
- * Accepts `<number>` with an optional `B`/`KB`/`MB`/`GB`/`TB` suffix.
333
- */
334
- memoryLimit?: string;
335
- }
336
- interface BrowserParquetFile {
337
- bytes: Uint8Array;
338
- name?: string;
339
- }
340
- interface BrowserParquetTable {
341
- table: string;
342
- files: BrowserParquetFile[];
343
- }
344
- interface BrowserParquetUrlTable {
345
- table: string;
346
- urls: string[];
347
- }
348
- interface AttachParquetTablesOptions {
349
- db: AsyncDuckDB;
350
- conn: AsyncDuckDBConnection;
351
- tables: BrowserParquetTable[];
352
- schema?: string;
353
- }
354
- interface AttachParquetUrlTablesOptions {
355
- db: AsyncDuckDB;
356
- conn: AsyncDuckDBConnection;
357
- tables: BrowserParquetUrlTable[];
358
- fetch?: typeof fetch;
359
- schema?: string;
360
- /**
361
- * Request init used only for runtime-owned HEAD / one-byte Range preflights.
362
- * DuckDB-WASM's internal HTTP reader cannot receive custom fetch headers;
363
- * URL reads must therefore be authorized by the URL itself.
364
- */
365
- fetchInit?: RequestInit;
366
- /**
367
- * Caps simultaneous URL preflights. Browser source endpoints should already
368
- * return small, coverage-planned URL sets; this is the runtime's local
369
- * guard against accidental unbounded attachment.
370
- */
371
- fetchConcurrency?: number;
372
- /** Reject before preflight when the URL set exceeds this many parquet files. */
373
- maxFiles?: number;
374
- /** Reject before registration when hinted or authoritative bytes exceed budget. */
375
- maxBytes?: number;
376
- /** Abort signal passed through to URL preflights and registration. */
377
- signal?: AbortSignal;
378
- /**
379
- * How DuckDB reads the parquet bytes:
380
- * - `'http'` (default): register the URL as an HTTP file; DuckDB issues
381
- * its own range reads during query execution. Right for large parquet
382
- * where only some column chunks are touched per query.
383
- * - `'buffer'`: fetch the full file once into an `ArrayBuffer` and register
384
- * it via `registerFileBuffer`. DuckDB makes zero HTTP calls after
385
- * registration — every query reads from the in-memory copy. Right for
386
- * tiny files (e.g. `dates` daily-totals parquet, <50 KB per file) where
387
- * the per-file round-trip overhead dominates the actual bytes moved.
388
- */
389
- attachMode?: 'http' | 'buffer';
390
- /**
391
- * When `true` (default), skip per-file HEAD/Range preflight if the URL
392
- * carries a signed `?s=<bytes>.<sig>` size hint — the size is already
393
- * known and DuckDB will learn `Accept-Ranges` from its first read.
394
- * Eliminates one round-trip per file on hosts that mint size hints. Set
395
- * `false` to force preflight against URLs whose size you don't trust.
396
- */
397
- trustSizeHint?: boolean;
398
- /**
399
- * Manifest version the caller associates with this set of URLs. Returned
400
- * on the resulting handle so callers can compare against a fresh manifest
401
- * probe without re-attaching. Purely advisory — the runtime never derives
402
- * behavior from the value itself.
403
- */
404
- version?: number | string;
405
- /**
406
- * Called once per parquet file after it's been fetched and registered with
407
- * DuckDB. For URL-backed HTTP files this means "preflighted and registered"
408
- * rather than fully downloaded; DuckDB then performs range reads during the
409
- * query. Fires in bounded-concurrency completion order, which is still not
410
- * guaranteed to match manifest URL order. Used by UI progress indicators to
411
- * tick a per-site counter; a no-op default keeps the hot path free.
412
- */
413
- onFileAttached?: (info: {
414
- table: string;
415
- index: number;
416
- total: number;
417
- }) => void;
418
- }
419
- /**
420
- * Handle returned from {@link attachParquetUrlTables}. Lets callers detach
421
- * the created views (for lazy re-attach on a new manifest version) or cheap-
422
- * check the embedded version against a fresh probe.
423
- */
424
- interface AttachedTablesHandle {
425
- version: number | string | undefined;
426
- tables: string[];
427
- schema: string;
428
- detach: () => Promise<void>;
429
- }
430
- interface BrowserAnalysisRuntime {
431
- db: AsyncDuckDB;
432
- conn: AsyncDuckDBConnection;
433
- query: (sql: string, params?: unknown[], signal?: AbortSignal) => Promise<QueryResult>;
434
- analyze: (params: AnalysisParams, registry: AnalyzerRegistry, options?: {
435
- signal?: AbortSignal;
436
- }) => Promise<AnalyzeResult>;
437
- /**
438
- * Returns true when `expected` doesn't match the version the runtime was
439
- * attached with — cheap check callers can run before each query to decide
440
- * whether to detach + re-attach against a fresher manifest. Undefined
441
- * values on either side compare equal so the no-version path is a no-op.
442
- */
443
- isStale: (expected: number | string | undefined) => boolean;
444
- /** Update the runtime's cached manifest version in-place (e.g. after a re-attach). */
445
- setVersion: (version: number | string | undefined) => void;
446
- /**
447
- * Update the list of attached table names. Lets callers fast-fail in
448
- * `analyze()` when a SQL plan references a table that wasn't in the manifest
449
- * for this site (e.g. site has only `queries` parquet, analyzer wants
450
- * `page_queries`) — surface a clean `AttachedTableMissingError` so the
451
- * caller can route to cloud fallback without paying the SQL execution cost.
452
- */
453
- setAttachedTables: (tables: readonly string[]) => void;
454
- close: () => Promise<void>;
455
- }
456
- declare class BrowserAttachBudgetExceededError extends Error {
457
- name: string;
458
- }
459
- interface BrowserAttachError {
460
- kind: 'browser-attach-budget-exceeded';
461
- message: string;
462
- /** Which budget tripped: the file count, the hinted byte plan, or the running byte plan. */
463
- budget: 'maxFiles' | 'maxBytes';
464
- }
465
- declare const browserAttachErrors: {
466
- readonly maxFilesExceeded: (files: number, maxFiles: number) => BrowserAttachError;
467
- readonly hintedBytesExceeded: (hintedBytes: number, maxBytes: number) => BrowserAttachError;
468
- readonly plannedBytesExceeded: (plannedBytes: number, maxBytes: number) => BrowserAttachError;
469
- };
470
- declare function isBrowserAttachError(value: unknown): value is BrowserAttachError;
471
- declare function bootDuckDBWasm(options?: BootDuckDBWasmOptions): Promise<DuckDBWasmBootResult>;
472
- declare function attachParquetTables(options: AttachParquetTablesOptions): Promise<void>;
473
- /**
474
- * Errors-as-values core for {@link attachParquetUrlTables}: returns a typed
475
- * {@link BrowserAttachError} when the requested file set blows the local file-
476
- * count / byte budget, so callers can branch (route the affected tables
477
- * server-side) instead of catching an untyped throw. WASM/DuckDB/HTTP IO
478
- * failures stay defects and propagate. `attachParquetUrlTables` is the thin
479
- * throwing wrapper preserving the historical `BrowserAttachBudgetExceededError`.
480
- */
481
- declare function attachParquetUrlTablesResult(options: AttachParquetUrlTablesOptions): Promise<Result<AttachedTablesHandle, BrowserAttachError>>;
482
- /**
483
- * Attach browser parquet URL tables, throwing
484
- * {@link BrowserAttachBudgetExceededError} when the requested set blows the
485
- * file-count / byte budget. Thin throwing wrapper over
486
- * {@link attachParquetUrlTablesResult}; existing call sites and their
487
- * `instanceof BrowserAttachBudgetExceededError` checks keep holding.
488
- */
489
- declare function attachParquetUrlTables(options: AttachParquetUrlTablesOptions): Promise<AttachedTablesHandle>;
490
- declare function createBrowserAnalysisRuntime(boot: DuckDBWasmBootResult, options?: {
491
- schema?: string;
492
- version?: number | string;
493
- attachedTables?: readonly string[];
494
- }): BrowserAnalysisRuntime;
495
11
  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 };