@gscdump/engine 1.4.11 → 1.5.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/dist/entities/empty-types.d.mts +22 -0
- package/dist/entities/empty-types.mjs +58 -0
- package/dist/entities/indexing-metadata.d.mts +26 -0
- package/dist/entities/indexing-metadata.mjs +31 -0
- package/dist/entities/inspection.d.mts +240 -0
- package/dist/entities/inspection.mjs +443 -0
- package/dist/entities/io.mjs +16 -0
- package/dist/{query-dim.d.mts → entities/query-dim.d.mts} +3 -3
- package/dist/{query-dim.mjs → entities/query-dim.mjs} +4 -4
- package/dist/{sitemap-projection.mjs → entities/sitemap-projection.mjs} +1 -1
- package/dist/entities/sitemap-shared.d.mts +199 -0
- package/dist/entities/sitemap-shared.mjs +243 -0
- package/dist/entities/sitemap-write.d.mts +3 -0
- package/dist/entities/sitemap-write.mjs +528 -0
- package/dist/entities/sitemap.d.mts +3 -0
- package/dist/entities/sitemap.mjs +91 -0
- package/dist/entities.d.mts +9 -481
- package/dist/entities.mjs +7 -1380
- package/dist/rollups/canonical.d.mts +71 -0
- package/dist/rollups/canonical.mjs +335 -0
- package/dist/rollups/core.d.mts +201 -0
- package/dist/rollups/core.mjs +116 -0
- package/dist/rollups/dates.mjs +11 -0
- package/dist/rollups/defaults.d.mts +11 -0
- package/dist/rollups/defaults.mjs +17 -0
- package/dist/rollups/hourly.d.mts +38 -0
- package/dist/rollups/hourly.mjs +38 -0
- package/dist/rollups/indexing.d.mts +46 -0
- package/dist/rollups/indexing.mjs +357 -0
- package/dist/rollups/traffic.d.mts +38 -0
- package/dist/rollups/traffic.mjs +289 -0
- package/dist/rollups/windows.d.mts +90 -0
- package/dist/rollups/windows.mjs +176 -0
- package/dist/rollups.d.mts +8 -471
- package/dist/rollups.mjs +7 -1316
- package/package.json +4 -4
- /package/dist/{sitemap-projection.d.mts → entities/sitemap-projection.d.mts} +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DataSource } from "../storage.mjs";
|
|
2
|
+
import { TenantCtx } from "@gscdump/contracts";
|
|
3
|
+
interface EmptyTypesDoc {
|
|
4
|
+
version: 1;
|
|
5
|
+
/** SearchType strings detected as empty for this (user, site). */
|
|
6
|
+
emptyTypes: string[];
|
|
7
|
+
/** When each type was last marked empty (unix ms). Helps debug stale skips. */
|
|
8
|
+
markedAt: Record<string, number>;
|
|
9
|
+
}
|
|
10
|
+
interface EmptyTypesStore {
|
|
11
|
+
load: (ctx: TenantCtx) => Promise<EmptyTypesDoc>;
|
|
12
|
+
/** Add types to the empty set, preserving existing markers. No-op if all already present. */
|
|
13
|
+
mark: (ctx: TenantCtx, types: readonly string[], now?: number) => Promise<EmptyTypesDoc>;
|
|
14
|
+
/** Remove types from the empty set. Returns the updated doc. */
|
|
15
|
+
clear: (ctx: TenantCtx, types: readonly string[]) => Promise<EmptyTypesDoc>;
|
|
16
|
+
}
|
|
17
|
+
interface CreateEmptyTypesStoreOptions {
|
|
18
|
+
dataSource: DataSource;
|
|
19
|
+
now?: () => number;
|
|
20
|
+
}
|
|
21
|
+
declare function createEmptyTypesStore(opts: CreateEmptyTypesStoreOptions): EmptyTypesStore;
|
|
22
|
+
export { CreateEmptyTypesStoreOptions, EmptyTypesDoc, EmptyTypesStore, createEmptyTypesStore };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { emptyTypesKey } from "../entity-keys.mjs";
|
|
2
|
+
import { readOptional } from "../adapters/read-optional.mjs";
|
|
3
|
+
import { encodeJsonBigintSafe } from "@gscdump/lakehouse/bigint";
|
|
4
|
+
function createEmptyTypesStore(opts) {
|
|
5
|
+
const ds = opts.dataSource;
|
|
6
|
+
const now = opts.now ?? (() => Date.now());
|
|
7
|
+
async function readDoc(key) {
|
|
8
|
+
const bytes = await readOptional(ds, key);
|
|
9
|
+
if (bytes === void 0) return {
|
|
10
|
+
version: 1,
|
|
11
|
+
emptyTypes: [],
|
|
12
|
+
markedAt: {}
|
|
13
|
+
};
|
|
14
|
+
return JSON.parse(new TextDecoder().decode(bytes));
|
|
15
|
+
}
|
|
16
|
+
async function writeDoc(key, doc) {
|
|
17
|
+
await ds.write(key, encodeJsonBigintSafe(doc));
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
async load(ctx) {
|
|
21
|
+
return readDoc(emptyTypesKey(ctx));
|
|
22
|
+
},
|
|
23
|
+
async mark(ctx, types, at) {
|
|
24
|
+
if (types.length === 0) return readDoc(emptyTypesKey(ctx));
|
|
25
|
+
const key = emptyTypesKey(ctx);
|
|
26
|
+
const doc = await readDoc(key);
|
|
27
|
+
const stamp = at ?? now();
|
|
28
|
+
let changed = false;
|
|
29
|
+
for (const t of types) {
|
|
30
|
+
if (!doc.emptyTypes.includes(t)) {
|
|
31
|
+
doc.emptyTypes.push(t);
|
|
32
|
+
changed = true;
|
|
33
|
+
}
|
|
34
|
+
if (doc.markedAt[t] === void 0) {
|
|
35
|
+
doc.markedAt[t] = stamp;
|
|
36
|
+
changed = true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (changed) {
|
|
40
|
+
doc.emptyTypes.sort();
|
|
41
|
+
await writeDoc(key, doc);
|
|
42
|
+
}
|
|
43
|
+
return doc;
|
|
44
|
+
},
|
|
45
|
+
async clear(ctx, types) {
|
|
46
|
+
if (types.length === 0) return readDoc(emptyTypesKey(ctx));
|
|
47
|
+
const key = emptyTypesKey(ctx);
|
|
48
|
+
const doc = await readDoc(key);
|
|
49
|
+
const drop = new Set(types);
|
|
50
|
+
const before = doc.emptyTypes.length;
|
|
51
|
+
doc.emptyTypes = doc.emptyTypes.filter((t) => !drop.has(t));
|
|
52
|
+
for (const t of drop) delete doc.markedAt[t];
|
|
53
|
+
if (doc.emptyTypes.length !== before) await writeDoc(key, doc);
|
|
54
|
+
return doc;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export { createEmptyTypesStore };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { DataSource } from "../storage.mjs";
|
|
2
|
+
import { TenantCtx } from "@gscdump/contracts";
|
|
3
|
+
interface IndexingMetadataRecord {
|
|
4
|
+
url: string;
|
|
5
|
+
capturedAt: string;
|
|
6
|
+
/** ISO-8601 notifyTime of the latest `URL_UPDATED` notification we've seen. */
|
|
7
|
+
latestUpdateAt?: string;
|
|
8
|
+
/** ISO-8601 notifyTime of the latest `URL_REMOVED` notification we've seen. */
|
|
9
|
+
latestRemoveAt?: string;
|
|
10
|
+
raw?: unknown;
|
|
11
|
+
}
|
|
12
|
+
interface IndexingMetadataIndex {
|
|
13
|
+
version: 1;
|
|
14
|
+
records: Record<string, IndexingMetadataRecord>;
|
|
15
|
+
}
|
|
16
|
+
interface IndexingMetadataStore {
|
|
17
|
+
writeBatch: (ctx: TenantCtx, records: readonly IndexingMetadataRecord[]) => Promise<void>;
|
|
18
|
+
loadIndex: (ctx: TenantCtx) => Promise<IndexingMetadataIndex>;
|
|
19
|
+
getLatest: (ctx: TenantCtx, url: string) => Promise<IndexingMetadataRecord | undefined>;
|
|
20
|
+
}
|
|
21
|
+
interface CreateIndexingMetadataStoreOptions {
|
|
22
|
+
dataSource: DataSource;
|
|
23
|
+
hash?: (url: string) => string;
|
|
24
|
+
}
|
|
25
|
+
declare function createIndexingMetadataStore(opts: CreateIndexingMetadataStoreOptions): IndexingMetadataStore;
|
|
26
|
+
export { CreateIndexingMetadataStoreOptions, IndexingMetadataIndex, IndexingMetadataRecord, IndexingMetadataStore, createIndexingMetadataStore };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { hashUrl, indexingMetadataIndexKey } from "../entity-keys.mjs";
|
|
2
|
+
import { readOptional } from "../adapters/read-optional.mjs";
|
|
3
|
+
import { encodeJsonBigintSafe } from "@gscdump/lakehouse/bigint";
|
|
4
|
+
function createIndexingMetadataStore(opts) {
|
|
5
|
+
const ds = opts.dataSource;
|
|
6
|
+
const hash = opts.hash ?? hashUrl;
|
|
7
|
+
async function readIndex(key) {
|
|
8
|
+
const bytes = await readOptional(ds, key);
|
|
9
|
+
if (bytes === void 0) return {
|
|
10
|
+
version: 1,
|
|
11
|
+
records: {}
|
|
12
|
+
};
|
|
13
|
+
return JSON.parse(new TextDecoder().decode(bytes));
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
async writeBatch(ctx, records) {
|
|
17
|
+
if (records.length === 0) return;
|
|
18
|
+
const key = indexingMetadataIndexKey(ctx);
|
|
19
|
+
const index = await readIndex(key);
|
|
20
|
+
for (const r of records) index.records[hash(r.url)] = r;
|
|
21
|
+
await ds.write(key, encodeJsonBigintSafe(index));
|
|
22
|
+
},
|
|
23
|
+
async loadIndex(ctx) {
|
|
24
|
+
return readIndex(indexingMetadataIndexKey(ctx));
|
|
25
|
+
},
|
|
26
|
+
async getLatest(ctx, url) {
|
|
27
|
+
return (await readIndex(indexingMetadataIndexKey(ctx))).records[hash(url)];
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export { createIndexingMetadataStore };
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { DataSource } from "../storage.mjs";
|
|
2
|
+
import { ScheduleState } from "../schedule.mjs";
|
|
3
|
+
import { TenantCtx } from "@gscdump/contracts";
|
|
4
|
+
import { CanonicalDifferenceKind } from "gscdump";
|
|
5
|
+
/**
|
|
6
|
+
* GSC URL inspection result fields we persist. Mirrors the
|
|
7
|
+
* `searchconsole_v1.Schema$UrlInspectionResult` shape but as plain JSON
|
|
8
|
+
* so storage doesn't depend on the googleapis type tree.
|
|
9
|
+
*/
|
|
10
|
+
interface InspectionRecord {
|
|
11
|
+
url: string;
|
|
12
|
+
/** ISO-8601 timestamp of when we ran the inspection. */
|
|
13
|
+
inspectedAt: string;
|
|
14
|
+
/** PASS / NEUTRAL / FAIL — the headline verdict from indexStatusResult. */
|
|
15
|
+
indexStatus?: string;
|
|
16
|
+
/** Last-crawl timestamp the API reports (ISO-8601). */
|
|
17
|
+
lastCrawlTime?: string;
|
|
18
|
+
/** Canonical URL Google selected. */
|
|
19
|
+
googleCanonical?: string;
|
|
20
|
+
/** Canonical URL the page declares. */
|
|
21
|
+
userCanonical?: string;
|
|
22
|
+
/** Crawl/index/serving disposition strings as the API returns them. */
|
|
23
|
+
coverageState?: string;
|
|
24
|
+
robotsTxtState?: string;
|
|
25
|
+
indexingState?: string;
|
|
26
|
+
pageFetchState?: string;
|
|
27
|
+
mobileUsabilityVerdict?: string;
|
|
28
|
+
richResultsVerdict?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Free-form payload for fields we don't promote to first-class columns
|
|
31
|
+
* (e.g. `referringUrls`, `crawledAs`). Keeps the wire format forward-compat
|
|
32
|
+
* without bumping the schema for every API addition.
|
|
33
|
+
*
|
|
34
|
+
* Recognised keys:
|
|
35
|
+
* - `schedule`: optional `ScheduleState` from {@link inspectionPolicy}
|
|
36
|
+
* governing when this URL is next due for re-inspection. Undefined on
|
|
37
|
+
* pre-§0 records — readers must tolerate the missing field and fall
|
|
38
|
+
* back to default policy on first observe.
|
|
39
|
+
*/
|
|
40
|
+
raw?: {
|
|
41
|
+
schedule?: ScheduleState;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Wire shape persisted to disk/R2. */
|
|
46
|
+
interface InspectionIndex {
|
|
47
|
+
version: 1;
|
|
48
|
+
/** Map of urlHash → InspectionRecord (latest only). */
|
|
49
|
+
records: Record<string, InspectionRecord>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Append-only history shard, one blob per `appendHistory` call.
|
|
53
|
+
* Keyed by UUID under the month directory — retries write a new blob,
|
|
54
|
+
* never RMW an existing one. Idempotent under job retries.
|
|
55
|
+
*/
|
|
56
|
+
interface InspectionHistoryShard {
|
|
57
|
+
version: 1;
|
|
58
|
+
/** Records persisted in this batch. */
|
|
59
|
+
records: InspectionRecord[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Directory prefix for a month's history shards. Each shard is a UUID-keyed
|
|
63
|
+
* blob under this prefix; `appendHistory` writes one per call, `loadHistory`
|
|
64
|
+
* lists + concatenates.
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* Row shape for the inspections parquet sidecar. Caller-side schema for
|
|
68
|
+
* `materialize` — D1 is the source of truth in the 2026-05-19 redesign, so
|
|
69
|
+
* consumers stream rows from `url_indexing_status` and pass them in. The
|
|
70
|
+
* parquet sidecar exists for DuckDB JOIN seams; readers go through
|
|
71
|
+
* `parquetUri`.
|
|
72
|
+
*/
|
|
73
|
+
interface InspectionParquetRow {
|
|
74
|
+
[column: string]: string | number | null;
|
|
75
|
+
urlHash: string;
|
|
76
|
+
url: string;
|
|
77
|
+
inspectedAt: string;
|
|
78
|
+
indexStatus: string | null;
|
|
79
|
+
lastCrawlTime: string | null;
|
|
80
|
+
googleCanonical: string | null;
|
|
81
|
+
userCanonical: string | null;
|
|
82
|
+
coverageState: string | null;
|
|
83
|
+
robotsTxtState: string | null;
|
|
84
|
+
indexingState: string | null;
|
|
85
|
+
pageFetchState: string | null;
|
|
86
|
+
mobileUsabilityVerdict: string | null;
|
|
87
|
+
richResultsVerdict: string | null;
|
|
88
|
+
scheduleNextAt: number | null;
|
|
89
|
+
scheduleConsecutiveUnchanged: number | null;
|
|
90
|
+
schedulePolicyVersion: number | null;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Row shape for the append-only inspection-event store. Superset of
|
|
94
|
+
* {@link InspectionParquetRow}: carries the full-fidelity columns the lossy
|
|
95
|
+
* `materialize` parquet dropped (`crawlingUserAgent`, `richResultsItems`,
|
|
96
|
+
* `sitemaps`, `referringUrls`, `mobileIssues`, `inspectionResultLink`,
|
|
97
|
+
* `firstCheckedAt`, `checkCount`). Object/array fields are persisted as JSON
|
|
98
|
+
* strings — read paths unpack them with DuckDB's JSON functions.
|
|
99
|
+
*
|
|
100
|
+
* `firstCheckedAt` / `checkCount` are caller-managed: the writer carries the
|
|
101
|
+
* earliest-seen timestamp + running observation count forward. Compaction
|
|
102
|
+
* preserves the EARLIEST `firstCheckedAt` per url (mirrors the sitemap store's
|
|
103
|
+
* `firstSeenAt` preservation); every other column is taken from the
|
|
104
|
+
* newest-by-`inspectedAt` event.
|
|
105
|
+
*/
|
|
106
|
+
interface InspectionEventRow extends InspectionParquetRow {
|
|
107
|
+
/** Declared-vs-selected canonical classification, computed at inspection ingest. */
|
|
108
|
+
canonicalMismatchKind: CanonicalDifferenceKind;
|
|
109
|
+
crawlingUserAgent: string | null;
|
|
110
|
+
/** JSON-encoded `RichResultsItem[]`. */
|
|
111
|
+
richResultsItems: string | null;
|
|
112
|
+
/** JSON-encoded list of sitemap URLs referencing this page. */
|
|
113
|
+
sitemaps: string | null;
|
|
114
|
+
/** JSON-encoded list of referring URLs. */
|
|
115
|
+
referringUrls: string | null;
|
|
116
|
+
/** JSON-encoded mobile-usability issues. */
|
|
117
|
+
mobileIssues: string | null;
|
|
118
|
+
inspectionResultLink: string | null;
|
|
119
|
+
/** ISO-8601 timestamp of the first inspection we ever recorded for this url. */
|
|
120
|
+
firstCheckedAt: string | null;
|
|
121
|
+
/** Total number of inspections recorded for this url. */
|
|
122
|
+
checkCount: number | null;
|
|
123
|
+
/**
|
|
124
|
+
* Stored next-recheck unix-seconds + priority as computed AT INSPECT TIME.
|
|
125
|
+
* Carried verbatim (NOT recomputed at read) because the scheduling policy can
|
|
126
|
+
* change over time — `__gsc/inspections` must replay the historical value to
|
|
127
|
+
* keep its frozen wire shape byte-stable.
|
|
128
|
+
*/
|
|
129
|
+
nextCheckAfter: number | null;
|
|
130
|
+
nextCheckPriority: string | null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Hard cap on a single `appendHistory` shard payload. Encoded bytes >
|
|
134
|
+
* this threshold throws — the caller logs and moves on (D1 is
|
|
135
|
+
* authoritative, R2 history is a sidecar). At `URLS_PER_JOB=3` a real
|
|
136
|
+
* batch encodes to ~10 KB so the cap is purely defensive against future
|
|
137
|
+
* batch-size bumps.
|
|
138
|
+
*/
|
|
139
|
+
declare const INSPECTION_HISTORY_MAX_BYTES: number;
|
|
140
|
+
interface InspectionStore {
|
|
141
|
+
/**
|
|
142
|
+
* Append a batch of fresh inspection results as an immutable per-batch
|
|
143
|
+
* shard under `history/<YYYY-MM>/<batchId>.json`. Idempotent under job
|
|
144
|
+
* retry (caller-supplied UUID per logical batch), no read-before-write,
|
|
145
|
+
* one PUT per month-group within the batch.
|
|
146
|
+
*
|
|
147
|
+
* Throws if the encoded payload exceeds {@link INSPECTION_HISTORY_MAX_BYTES}.
|
|
148
|
+
*/
|
|
149
|
+
appendHistory: (ctx: TenantCtx, records: readonly InspectionRecord[], opts?: {
|
|
150
|
+
batchId?: string;
|
|
151
|
+
}) => Promise<void>;
|
|
152
|
+
/**
|
|
153
|
+
* Read every shard in a month directory and concatenate. Best-effort:
|
|
154
|
+
* shards that fail to decode are skipped (logged via console). Returns
|
|
155
|
+
* `undefined` if the month has no shards.
|
|
156
|
+
*/
|
|
157
|
+
loadHistory: (ctx: TenantCtx, yearMonth: string) => Promise<InspectionHistoryShard | undefined>;
|
|
158
|
+
/**
|
|
159
|
+
* Encode caller-provided rows into the inspections parquet sidecar at
|
|
160
|
+
* `entities/inspections/index.parquet`. Sorted by `urlHash` so DuckDB
|
|
161
|
+
* row-group stats can prune URL-keyed JOINs efficiently. One PUT.
|
|
162
|
+
*
|
|
163
|
+
* D1 is the source of truth in the 2026-05-19 redesign; this rebuilds
|
|
164
|
+
* the parquet from D1 rows the caller streams in (engine has no D1
|
|
165
|
+
* access). Triggered by `indexing/complete` post-hook.
|
|
166
|
+
*
|
|
167
|
+
* Returns the parquet object key (matches {@link parquetUri} after write).
|
|
168
|
+
*/
|
|
169
|
+
materialize: (ctx: TenantCtx, rows: Iterable<InspectionParquetRow>) => Promise<{
|
|
170
|
+
key: string;
|
|
171
|
+
rowCount: number;
|
|
172
|
+
bytes: number;
|
|
173
|
+
}>;
|
|
174
|
+
/**
|
|
175
|
+
* Append a batch of inspection results as an immutable per-batch parquet
|
|
176
|
+
* under `events/<YYYY-MM>/<batchId>.parquet`, partitioned by the `YYYY-MM`
|
|
177
|
+
* of each row's `inspectedAt` (a batch spanning a month boundary writes one
|
|
178
|
+
* file per month). No read-before-write; idempotent under job retry (same
|
|
179
|
+
* `batchId` → same key → whole-file overwrite). Rows carry the FULL column
|
|
180
|
+
* set ({@link INSPECTION_EVENT_COLUMNS}); this is the append-only
|
|
181
|
+
* source-of-truth that supersedes {@link InspectionStore.materialize}.
|
|
182
|
+
*
|
|
183
|
+
* Returns the keys written + total row count. Empty input is a no-op.
|
|
184
|
+
*/
|
|
185
|
+
appendInspectionEvents: (ctx: TenantCtx, rows: readonly InspectionEventRow[], opts?: {
|
|
186
|
+
batchId?: string;
|
|
187
|
+
}) => Promise<{
|
|
188
|
+
keys: string[];
|
|
189
|
+
rowCount: number;
|
|
190
|
+
}>;
|
|
191
|
+
/**
|
|
192
|
+
* Fold every outstanding event file into the `base.parquet`: latest-per-url
|
|
193
|
+
* by max `inspectedAt` (newest-wins), preserving the earliest non-null
|
|
194
|
+
* `firstCheckedAt` per url. Writes the new base then deletes the consumed
|
|
195
|
+
* event files — file-level only, never row-level (ADR-0002). Idempotent +
|
|
196
|
+
* re-runnable: a crash after the base write but before the delete just
|
|
197
|
+
* re-folds the same events (newest-wins makes that a no-op). A real read
|
|
198
|
+
* failure on the existing base propagates rather than rebuilding from events
|
|
199
|
+
* alone (which would drop URLs only the base held).
|
|
200
|
+
*
|
|
201
|
+
* No-op (no base rewrite) when there are zero outstanding events.
|
|
202
|
+
*/
|
|
203
|
+
compactInspections: (ctx: TenantCtx, opts?: {
|
|
204
|
+
/**
|
|
205
|
+
* Also record state changes into the durable transitions sidecar.
|
|
206
|
+
* Default OFF so publishing this is inert until a canary opts in.
|
|
207
|
+
*/
|
|
208
|
+
transitions?: boolean;
|
|
209
|
+
}) => Promise<{
|
|
210
|
+
baseRowCount: number;
|
|
211
|
+
eventsFolded: number;
|
|
212
|
+
eventFilesDeleted: number;
|
|
213
|
+
transitionsWritten: number;
|
|
214
|
+
}>;
|
|
215
|
+
/**
|
|
216
|
+
* Rewrite a legacy latest-only base with the canonical kind derived from the
|
|
217
|
+
* canonical pair it already retains. Outstanding events must be compacted first.
|
|
218
|
+
*/
|
|
219
|
+
backfillCanonicalMismatchKinds: (ctx: TenantCtx) => Promise<{
|
|
220
|
+
baseRowCount: number;
|
|
221
|
+
rowsBackfilled: number;
|
|
222
|
+
rewritten: boolean;
|
|
223
|
+
}>;
|
|
224
|
+
/**
|
|
225
|
+
* DuckDB-resolvable URI for the materialised parquet sidecar, or
|
|
226
|
+
* `undefined` if the underlying `DataSource` has no native URI shape
|
|
227
|
+
* (in-memory tests). When defined, read paths can `read_parquet(<uri>)`
|
|
228
|
+
* directly without staging bytes through JS.
|
|
229
|
+
*
|
|
230
|
+
* Does not check existence — caller is responsible for ensuring
|
|
231
|
+
* `materialize` has run at least once. Returning a URI for a missing key
|
|
232
|
+
* is safe; DuckDB will surface a 404 / not-found at query time.
|
|
233
|
+
*/
|
|
234
|
+
parquetUri: (ctx: TenantCtx) => string | undefined;
|
|
235
|
+
}
|
|
236
|
+
interface CreateInspectionStoreOptions {
|
|
237
|
+
dataSource: DataSource;
|
|
238
|
+
}
|
|
239
|
+
declare function createInspectionStore(opts: CreateInspectionStoreOptions): InspectionStore;
|
|
240
|
+
export { CreateInspectionStoreOptions, INSPECTION_HISTORY_MAX_BYTES, InspectionEventRow, InspectionHistoryShard, InspectionIndex, InspectionParquetRow, InspectionRecord, InspectionStore, createInspectionStore };
|