@gscdump/engine-sqlite 0.32.12 → 0.33.3

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
@@ -68,6 +68,16 @@ Always import `sql` from `@gscdump/engine-sqlite` — not `drizzle-orm` directly
68
68
  - `sqliteResolverAdapter` / `createSqliteResolverAdapter` / `probeSqliteRegex` — dialect adapter for the resolver kit.
69
69
  - `resolveWindow` (re-exported from `@gscdump/engine/period`).
70
70
 
71
+ ## D1 Analytics Table Status
72
+
73
+ The `gsc_*` analytics tables remain a supported compatibility surface. The
74
+ 2026-06-29 Iceberg migration audit found active package exports, resolver tests,
75
+ and docs for `gsc_pages`, `gsc_keywords`, `gsc_page_keywords`, `gsc_countries`,
76
+ and `gsc_devices`. Do not remove these tables as part of the Iceberg/canonical
77
+ migration. A future retirement should be staged behind a consumer usage audit,
78
+ dual-read/shadow-read checks, and a release note that names the replacement
79
+ Iceberg/R2 SQL path.
80
+
71
81
  ## Related
72
82
 
73
83
  - [`@gscdump/engine`](../engine) — Storage contracts + dialect-neutral resolver.
package/dist/index.d.mts CHANGED
@@ -342,22 +342,6 @@ declare const gsc_keywords: import("drizzle-orm/sqlite-core").SQLiteTableWithCol
342
342
  identity: undefined;
343
343
  generated: undefined;
344
344
  }, {}>;
345
- query_canonical: import("drizzle-orm/sqlite-core").SQLiteColumn<{
346
- name: string;
347
- tableName: "gsc_keywords";
348
- dataType: "string";
349
- data: string;
350
- driverParam: string;
351
- notNull: false;
352
- hasDefault: false;
353
- isPrimaryKey: false;
354
- isAutoincrement: false;
355
- hasRuntimeDefault: false;
356
- enumValues: [string, ...string[]];
357
- baseColumn: never;
358
- identity: undefined;
359
- generated: undefined;
360
- }, {}>;
361
345
  id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
362
346
  name: string;
363
347
  tableName: "gsc_keywords";
@@ -1010,22 +994,6 @@ declare const gsc_page_keywords: import("drizzle-orm/sqlite-core").SQLiteTableWi
1010
994
  identity: undefined;
1011
995
  generated: undefined;
1012
996
  }, {}>;
1013
- query_canonical: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1014
- name: string;
1015
- tableName: "gsc_page_keywords";
1016
- dataType: "string";
1017
- data: string;
1018
- driverParam: string;
1019
- notNull: false;
1020
- hasDefault: false;
1021
- isPrimaryKey: false;
1022
- isAutoincrement: false;
1023
- hasRuntimeDefault: false;
1024
- enumValues: [string, ...string[]];
1025
- baseColumn: never;
1026
- identity: undefined;
1027
- generated: undefined;
1028
- }, {}>;
1029
997
  id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1030
998
  name: string;
1031
999
  tableName: "gsc_page_keywords";
@@ -1138,6 +1106,125 @@ declare const gsc_page_keywords: import("drizzle-orm/sqlite-core").SQLiteTableWi
1138
1106
  };
1139
1107
  dialect: "sqlite";
1140
1108
  }>;
1109
+ declare const gsc_query_dim: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
1110
+ name: "gsc_query_dim";
1111
+ schema: undefined;
1112
+ columns: {
1113
+ site_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1114
+ name: string;
1115
+ tableName: "gsc_query_dim";
1116
+ dataType: "string";
1117
+ data: string;
1118
+ driverParam: string;
1119
+ notNull: true;
1120
+ hasDefault: false;
1121
+ isPrimaryKey: false;
1122
+ isAutoincrement: false;
1123
+ hasRuntimeDefault: false;
1124
+ enumValues: [string, ...string[]];
1125
+ baseColumn: never;
1126
+ identity: undefined;
1127
+ generated: undefined;
1128
+ }, {}>;
1129
+ query: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1130
+ name: string;
1131
+ tableName: "gsc_query_dim";
1132
+ dataType: "string";
1133
+ data: string;
1134
+ driverParam: string;
1135
+ notNull: true;
1136
+ hasDefault: false;
1137
+ isPrimaryKey: false;
1138
+ isAutoincrement: false;
1139
+ hasRuntimeDefault: false;
1140
+ enumValues: [string, ...string[]];
1141
+ baseColumn: never;
1142
+ identity: undefined;
1143
+ generated: undefined;
1144
+ }, {}>;
1145
+ query_canonical: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1146
+ name: string;
1147
+ tableName: "gsc_query_dim";
1148
+ dataType: "string";
1149
+ data: string;
1150
+ driverParam: string;
1151
+ notNull: true;
1152
+ hasDefault: false;
1153
+ isPrimaryKey: false;
1154
+ isAutoincrement: false;
1155
+ hasRuntimeDefault: false;
1156
+ enumValues: [string, ...string[]];
1157
+ baseColumn: never;
1158
+ identity: undefined;
1159
+ generated: undefined;
1160
+ }, {}>;
1161
+ normalizer_version: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1162
+ name: string;
1163
+ tableName: "gsc_query_dim";
1164
+ dataType: "number int53";
1165
+ data: number;
1166
+ driverParam: number;
1167
+ notNull: true;
1168
+ hasDefault: false;
1169
+ isPrimaryKey: false;
1170
+ isAutoincrement: false;
1171
+ hasRuntimeDefault: false;
1172
+ enumValues: undefined;
1173
+ baseColumn: never;
1174
+ identity: undefined;
1175
+ generated: undefined;
1176
+ }, {}>;
1177
+ intent_code: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1178
+ name: string;
1179
+ tableName: "gsc_query_dim";
1180
+ dataType: "number int53";
1181
+ data: number;
1182
+ driverParam: number;
1183
+ notNull: false;
1184
+ hasDefault: false;
1185
+ isPrimaryKey: false;
1186
+ isAutoincrement: false;
1187
+ hasRuntimeDefault: false;
1188
+ enumValues: undefined;
1189
+ baseColumn: never;
1190
+ identity: undefined;
1191
+ generated: undefined;
1192
+ }, {}>;
1193
+ intent_version: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1194
+ name: string;
1195
+ tableName: "gsc_query_dim";
1196
+ dataType: "number int53";
1197
+ data: number;
1198
+ driverParam: number;
1199
+ notNull: false;
1200
+ hasDefault: false;
1201
+ isPrimaryKey: false;
1202
+ isAutoincrement: false;
1203
+ hasRuntimeDefault: false;
1204
+ enumValues: undefined;
1205
+ baseColumn: never;
1206
+ identity: undefined;
1207
+ generated: undefined;
1208
+ }, {}>;
1209
+ built_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1210
+ name: string;
1211
+ tableName: "gsc_query_dim";
1212
+ dataType: "number int53";
1213
+ data: number;
1214
+ driverParam: number;
1215
+ notNull: false;
1216
+ hasDefault: false;
1217
+ isPrimaryKey: false;
1218
+ isAutoincrement: false;
1219
+ hasRuntimeDefault: false;
1220
+ enumValues: undefined;
1221
+ baseColumn: never;
1222
+ identity: undefined;
1223
+ generated: undefined;
1224
+ }, {}>;
1225
+ };
1226
+ dialect: "sqlite";
1227
+ }>;
1141
1228
  declare const schema: {
1142
1229
  gsc_pages: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
1143
1230
  name: "gsc_pages";
@@ -1451,22 +1538,6 @@ declare const schema: {
1451
1538
  identity: undefined;
1452
1539
  generated: undefined;
1453
1540
  }, {}>;
1454
- query_canonical: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1455
- name: string;
1456
- tableName: "gsc_keywords";
1457
- dataType: "string";
1458
- data: string;
1459
- driverParam: string;
1460
- notNull: false;
1461
- hasDefault: false;
1462
- isPrimaryKey: false;
1463
- isAutoincrement: false;
1464
- hasRuntimeDefault: false;
1465
- enumValues: [string, ...string[]];
1466
- baseColumn: never;
1467
- identity: undefined;
1468
- generated: undefined;
1469
- }, {}>;
1470
1541
  id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
1471
1542
  name: string;
1472
1543
  tableName: "gsc_keywords";
@@ -2119,22 +2190,6 @@ declare const schema: {
2119
2190
  identity: undefined;
2120
2191
  generated: undefined;
2121
2192
  }, {}>;
2122
- query_canonical: import("drizzle-orm/sqlite-core").SQLiteColumn<{
2123
- name: string;
2124
- tableName: "gsc_page_keywords";
2125
- dataType: "string";
2126
- data: string;
2127
- driverParam: string;
2128
- notNull: false;
2129
- hasDefault: false;
2130
- isPrimaryKey: false;
2131
- isAutoincrement: false;
2132
- hasRuntimeDefault: false;
2133
- enumValues: [string, ...string[]];
2134
- baseColumn: never;
2135
- identity: undefined;
2136
- generated: undefined;
2137
- }, {}>;
2138
2193
  id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
2139
2194
  name: string;
2140
2195
  tableName: "gsc_page_keywords";
@@ -2803,22 +2858,6 @@ declare const schema: {
2803
2858
  identity: undefined;
2804
2859
  generated: undefined;
2805
2860
  }, {}>;
2806
- query_canonical: import("drizzle-orm/sqlite-core").SQLiteColumn<{
2807
- name: string;
2808
- tableName: "gsc_search_appearance_queries";
2809
- dataType: "string";
2810
- data: string;
2811
- driverParam: string;
2812
- notNull: false;
2813
- hasDefault: false;
2814
- isPrimaryKey: false;
2815
- isAutoincrement: false;
2816
- hasRuntimeDefault: false;
2817
- enumValues: [string, ...string[]];
2818
- baseColumn: never;
2819
- identity: undefined;
2820
- generated: undefined;
2821
- }, {}>;
2822
2861
  id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
2823
2862
  name: string;
2824
2863
  tableName: "gsc_search_appearance_queries";
@@ -3063,22 +3102,6 @@ declare const schema: {
3063
3102
  identity: undefined;
3064
3103
  generated: undefined;
3065
3104
  }, {}>;
3066
- query_canonical: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3067
- name: string;
3068
- tableName: "gsc_search_appearance_page_queries";
3069
- dataType: "string";
3070
- data: string;
3071
- driverParam: string;
3072
- notNull: false;
3073
- hasDefault: false;
3074
- isPrimaryKey: false;
3075
- isAutoincrement: false;
3076
- hasRuntimeDefault: false;
3077
- enumValues: [string, ...string[]];
3078
- baseColumn: never;
3079
- identity: undefined;
3080
- generated: undefined;
3081
- }, {}>;
3082
3105
  id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3083
3106
  name: string;
3084
3107
  tableName: "gsc_search_appearance_page_queries";
@@ -3419,6 +3442,125 @@ declare const schema: {
3419
3442
  };
3420
3443
  dialect: "sqlite";
3421
3444
  }>;
3445
+ gsc_query_dim: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
3446
+ name: "gsc_query_dim";
3447
+ schema: undefined;
3448
+ columns: {
3449
+ site_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3450
+ name: string;
3451
+ tableName: "gsc_query_dim";
3452
+ dataType: "string";
3453
+ data: string;
3454
+ driverParam: string;
3455
+ notNull: true;
3456
+ hasDefault: false;
3457
+ isPrimaryKey: false;
3458
+ isAutoincrement: false;
3459
+ hasRuntimeDefault: false;
3460
+ enumValues: [string, ...string[]];
3461
+ baseColumn: never;
3462
+ identity: undefined;
3463
+ generated: undefined;
3464
+ }, {}>;
3465
+ query: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3466
+ name: string;
3467
+ tableName: "gsc_query_dim";
3468
+ dataType: "string";
3469
+ data: string;
3470
+ driverParam: string;
3471
+ notNull: true;
3472
+ hasDefault: false;
3473
+ isPrimaryKey: false;
3474
+ isAutoincrement: false;
3475
+ hasRuntimeDefault: false;
3476
+ enumValues: [string, ...string[]];
3477
+ baseColumn: never;
3478
+ identity: undefined;
3479
+ generated: undefined;
3480
+ }, {}>;
3481
+ query_canonical: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3482
+ name: string;
3483
+ tableName: "gsc_query_dim";
3484
+ dataType: "string";
3485
+ data: string;
3486
+ driverParam: string;
3487
+ notNull: true;
3488
+ hasDefault: false;
3489
+ isPrimaryKey: false;
3490
+ isAutoincrement: false;
3491
+ hasRuntimeDefault: false;
3492
+ enumValues: [string, ...string[]];
3493
+ baseColumn: never;
3494
+ identity: undefined;
3495
+ generated: undefined;
3496
+ }, {}>;
3497
+ normalizer_version: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3498
+ name: string;
3499
+ tableName: "gsc_query_dim";
3500
+ dataType: "number int53";
3501
+ data: number;
3502
+ driverParam: number;
3503
+ notNull: true;
3504
+ hasDefault: false;
3505
+ isPrimaryKey: false;
3506
+ isAutoincrement: false;
3507
+ hasRuntimeDefault: false;
3508
+ enumValues: undefined;
3509
+ baseColumn: never;
3510
+ identity: undefined;
3511
+ generated: undefined;
3512
+ }, {}>;
3513
+ intent_code: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3514
+ name: string;
3515
+ tableName: "gsc_query_dim";
3516
+ dataType: "number int53";
3517
+ data: number;
3518
+ driverParam: number;
3519
+ notNull: false;
3520
+ hasDefault: false;
3521
+ isPrimaryKey: false;
3522
+ isAutoincrement: false;
3523
+ hasRuntimeDefault: false;
3524
+ enumValues: undefined;
3525
+ baseColumn: never;
3526
+ identity: undefined;
3527
+ generated: undefined;
3528
+ }, {}>;
3529
+ intent_version: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3530
+ name: string;
3531
+ tableName: "gsc_query_dim";
3532
+ dataType: "number int53";
3533
+ data: number;
3534
+ driverParam: number;
3535
+ notNull: false;
3536
+ hasDefault: false;
3537
+ isPrimaryKey: false;
3538
+ isAutoincrement: false;
3539
+ hasRuntimeDefault: false;
3540
+ enumValues: undefined;
3541
+ baseColumn: never;
3542
+ identity: undefined;
3543
+ generated: undefined;
3544
+ }, {}>;
3545
+ built_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
3546
+ name: string;
3547
+ tableName: "gsc_query_dim";
3548
+ dataType: "number int53";
3549
+ data: number;
3550
+ driverParam: number;
3551
+ notNull: false;
3552
+ hasDefault: false;
3553
+ isPrimaryKey: false;
3554
+ isAutoincrement: false;
3555
+ hasRuntimeDefault: false;
3556
+ enumValues: undefined;
3557
+ baseColumn: never;
3558
+ identity: undefined;
3559
+ generated: undefined;
3560
+ }, {}>;
3561
+ };
3562
+ dialect: "sqlite";
3563
+ }>;
3422
3564
  };
3423
3565
  type Schema = typeof schema;
3424
3566
  declare function compileSqlite(query: SQL$1): {
@@ -3457,7 +3599,7 @@ declare function createSqliteInsightRunner<TSchema extends Record<string, unknow
3457
3599
  * (one or both). This lets callers pass unbounded query-string params
3458
3600
  * through without first normalizing them.
3459
3601
  */
3460
- declare const scopeFor: (table: "gsc_pages" | "gsc_keywords" | "gsc_countries" | "gsc_devices" | "gsc_page_keywords" | "gsc_search_appearance" | "gsc_search_appearance_pages" | "gsc_search_appearance_queries" | "gsc_search_appearance_page_queries" | "gsc_hourly_pages", opts: ScopedRunnerOptions) => TableScope, mergeScope: typeof import("@gscdump/engine/scope").mergeScope;
3602
+ declare const scopeFor: (table: "gsc_pages" | "gsc_keywords" | "gsc_countries" | "gsc_devices" | "gsc_page_keywords" | "gsc_search_appearance" | "gsc_search_appearance_pages" | "gsc_search_appearance_queries" | "gsc_search_appearance_page_queries" | "gsc_query_dim" | "gsc_hourly_pages", opts: ScopedRunnerOptions) => TableScope, mergeScope: typeof import("@gscdump/engine/scope").mergeScope;
3461
3603
  type SqliteQueryExecutor = SqliteRowExecutor;
3462
3604
  interface EngineConfig {
3463
3605
  executor: SqliteQueryExecutor;
@@ -4257,7 +4399,7 @@ interface CreateSqliteResolverAdapterOptions {
4257
4399
  regex?: boolean;
4258
4400
  }
4259
4401
  declare function createSqliteResolverAdapter(options?: CreateSqliteResolverAdapterOptions): ResolverAdapter<TableKey>;
4260
- declare const sqliteResolverAdapter: ResolverAdapter<"gsc_pages" | "gsc_keywords" | "gsc_countries" | "gsc_devices" | "gsc_page_keywords" | "gsc_search_appearance" | "gsc_search_appearance_pages" | "gsc_search_appearance_queries" | "gsc_search_appearance_page_queries" | "gsc_hourly_pages">;
4402
+ declare const sqliteResolverAdapter: ResolverAdapter<"gsc_pages" | "gsc_keywords" | "gsc_countries" | "gsc_devices" | "gsc_page_keywords" | "gsc_search_appearance" | "gsc_search_appearance_pages" | "gsc_search_appearance_queries" | "gsc_search_appearance_page_queries" | "gsc_query_dim" | "gsc_hourly_pages">;
4261
4403
  /**
4262
4404
  * One-shot probe that detects whether the host SQLite has a working REGEXP
4263
4405
  * function. SQLite ships REGEXP as a no-op stub by default; D1, libsql, and
@@ -4275,4 +4417,4 @@ interface CreateSqliteResolverAdapterFromExecutorOptions {
4275
4417
  * an executor handy.
4276
4418
  */
4277
4419
  declare function createSqliteResolverAdapterFromExecutor(options: CreateSqliteResolverAdapterFromExecutorOptions): Promise<ResolverAdapter<TableKey>>;
4278
- export { type AnalyticsManifestDb, type CachedManifestStore, type CachedManifestStoreOptions, type ComparisonMode, type EngineConfig, type R2LockInsert, type R2LockSelect, type R2ManifestInsert, type R2ManifestSelect, type R2ShadowDiffInsert, type R2ShadowDiffSelect, type R2SyncStateInsert, type R2SyncStateSelect, type R2WatermarkInsert, type R2WatermarkSelect, type R2WriteErrorInsert, type R2WriteErrorSelect, type ResolveWindowOptions, type ResolvedWindow, type SQL, type Schema, type ScopedRunnerOptions, type SqliteInsightRunner, type SqliteInsightRunnerOptions, type SqliteQueryExecutor, type SqliteRowExecutor, type TableKey, type TableScope, type WindowPreset, aggClicks, aggCtr, aggImpressions, aggPosition, and, compileSqlite, createCachedManifestStore, createD1ManifestStore, createEngine, createSqliteInsightRunner, createSqliteResolverAdapter, createSqliteResolverAdapterFromExecutor, eq, gsc_countries, gsc_devices, gsc_keywords, gsc_page_keywords, gsc_pages, gte, lte, mergeScope, probeSqliteRegex, r2Locks, r2Manifest, r2ShadowDiffs, r2SyncStates, r2Watermarks, r2WriteErrors, resolveWindow, schema, scopeFor, sql, sqliteResolverAdapter };
4420
+ export { type AnalyticsManifestDb, type CachedManifestStore, type CachedManifestStoreOptions, type ComparisonMode, type EngineConfig, type R2LockInsert, type R2LockSelect, type R2ManifestInsert, type R2ManifestSelect, type R2ShadowDiffInsert, type R2ShadowDiffSelect, type R2SyncStateInsert, type R2SyncStateSelect, type R2WatermarkInsert, type R2WatermarkSelect, type R2WriteErrorInsert, type R2WriteErrorSelect, type ResolveWindowOptions, type ResolvedWindow, type SQL, type Schema, type ScopedRunnerOptions, type SqliteInsightRunner, type SqliteInsightRunnerOptions, type SqliteQueryExecutor, type SqliteRowExecutor, type TableKey, type TableScope, type WindowPreset, aggClicks, aggCtr, aggImpressions, aggPosition, and, compileSqlite, createCachedManifestStore, createD1ManifestStore, createEngine, createSqliteInsightRunner, createSqliteResolverAdapter, createSqliteResolverAdapterFromExecutor, eq, gsc_countries, gsc_devices, gsc_keywords, gsc_page_keywords, gsc_pages, gsc_query_dim, gte, lte, mergeScope, probeSqliteRegex, r2Locks, r2Manifest, r2ShadowDiffs, r2SyncStates, r2Watermarks, r2WriteErrors, resolveWindow, schema, scopeFor, sql, sqliteResolverAdapter };
package/dist/index.mjs CHANGED
@@ -20,6 +20,7 @@ function createCachedManifestStore(inner, options = {}) {
20
20
  const userId = String(scope.userId);
21
21
  if (scope.siteId && scope.table && scope.searchType !== void 0) {
22
22
  cache.delete(`${userId}\0${scope.siteId}\0${scope.table}\0${scope.searchType}`);
23
+ cache.delete(`${userId}\0${scope.siteId}\0${scope.table}\0`);
23
24
  return;
24
25
  }
25
26
  const prefix = scope.siteId && scope.table ? `${userId}\0${scope.siteId}\0${scope.table}\0` : scope.siteId ? `${userId}\0${scope.siteId}\0` : `${userId}\0`;
@@ -48,6 +49,12 @@ function createCachedManifestStore(inner, options = {}) {
48
49
  table: entry.table,
49
50
  searchType: entry.searchType
50
51
  });
52
+ for (const e of superseding ?? []) bust({
53
+ userId: e.userId,
54
+ siteId: e.siteId ?? "",
55
+ table: e.table,
56
+ searchType: e.searchType
57
+ });
51
58
  },
52
59
  registerVersions: async (entries, superseding) => {
53
60
  await inner.registerVersions(entries, superseding);
@@ -57,15 +64,36 @@ function createCachedManifestStore(inner, options = {}) {
57
64
  table: e.table,
58
65
  searchType: e.searchType
59
66
  });
67
+ for (const e of superseding ?? []) bust({
68
+ userId: e.userId,
69
+ siteId: e.siteId ?? "",
70
+ table: e.table,
71
+ searchType: e.searchType
72
+ });
60
73
  },
61
74
  listRetired: inner.listRetired.bind(inner),
62
- delete: inner.delete.bind(inner),
75
+ delete: async (entries) => {
76
+ await inner.delete(entries);
77
+ for (const e of entries) bust({
78
+ userId: e.userId,
79
+ siteId: e.siteId ?? "",
80
+ table: e.table,
81
+ searchType: e.searchType
82
+ });
83
+ },
63
84
  getWatermarks: inner.getWatermarks.bind(inner),
64
85
  bumpWatermark: inner.bumpWatermark.bind(inner),
65
86
  getSyncStates: inner.getSyncStates.bind(inner),
66
87
  setSyncState: inner.setSyncState.bind(inner),
67
88
  withLock: inner.withLock.bind(inner),
68
- purgeTenant: inner.purgeTenant.bind(inner),
89
+ purgeTenant: async (filter) => {
90
+ const result = await inner.purgeTenant(filter);
91
+ bust({
92
+ userId: filter.userId,
93
+ siteId: filter.siteId
94
+ });
95
+ return result;
96
+ },
69
97
  bust,
70
98
  clear: () => cache.clear(),
71
99
  stats: () => ({ size: cache.size })
@@ -92,68 +120,78 @@ const gsc_pages = sqliteTable("gsc_pages", {
92
120
  ...baseCols(),
93
121
  url: text("url").notNull(),
94
122
  ...metricCols()
95
- });
123
+ }, (t) => [index("idx_gsc_pages_site_date").on(t.site_id, t.date)]);
96
124
  const gsc_keywords = sqliteTable("gsc_keywords", {
97
125
  ...baseCols(),
98
126
  query: text("query").notNull(),
99
- query_canonical: text("query_canonical"),
100
127
  ...metricCols()
101
- });
128
+ }, (t) => [index("idx_gsc_keywords_site_date").on(t.site_id, t.date)]);
102
129
  const gsc_countries = sqliteTable("gsc_countries", {
103
130
  ...baseCols(),
104
131
  country: text("country").notNull(),
105
132
  ...metricCols()
106
- });
133
+ }, (t) => [index("idx_gsc_countries_site_date").on(t.site_id, t.date)]);
107
134
  const gsc_devices = sqliteTable("gsc_devices", {
108
135
  ...baseCols(),
109
136
  device: text("device").notNull(),
110
137
  ...metricCols()
111
- });
138
+ }, (t) => [index("idx_gsc_devices_site_date").on(t.site_id, t.date)]);
112
139
  const gsc_page_keywords = sqliteTable("gsc_page_keywords", {
113
140
  ...baseCols(),
114
141
  url: text("url").notNull(),
115
142
  query: text("query").notNull(),
116
- query_canonical: text("query_canonical"),
117
143
  ...metricCols()
118
- });
144
+ }, (t) => [index("idx_gsc_page_keywords_site_date").on(t.site_id, t.date)]);
145
+ const gsc_search_appearance = sqliteTable("gsc_search_appearance", {
146
+ ...baseCols(),
147
+ searchAppearance: text("searchAppearance").notNull(),
148
+ ...metricCols()
149
+ }, (t) => [index("idx_gsc_search_appearance_site_date").on(t.site_id, t.date)]);
150
+ const gsc_search_appearance_pages = sqliteTable("gsc_search_appearance_pages", {
151
+ ...baseCols(),
152
+ searchAppearance: text("searchAppearance").notNull(),
153
+ url: text("url").notNull(),
154
+ ...metricCols()
155
+ }, (t) => [index("idx_gsc_search_appearance_pages_site_date").on(t.site_id, t.date)]);
156
+ const gsc_search_appearance_queries = sqliteTable("gsc_search_appearance_queries", {
157
+ ...baseCols(),
158
+ searchAppearance: text("searchAppearance").notNull(),
159
+ query: text("query").notNull(),
160
+ ...metricCols()
161
+ }, (t) => [index("idx_gsc_search_appearance_queries_site_date").on(t.site_id, t.date)]);
162
+ const gsc_search_appearance_page_queries = sqliteTable("gsc_search_appearance_page_queries", {
163
+ ...baseCols(),
164
+ searchAppearance: text("searchAppearance").notNull(),
165
+ url: text("url").notNull(),
166
+ query: text("query").notNull(),
167
+ ...metricCols()
168
+ }, (t) => [index("idx_gsc_search_appearance_page_queries_site_date").on(t.site_id, t.date)]);
169
+ const gsc_query_dim = sqliteTable("gsc_query_dim", {
170
+ site_id: text("site_id").notNull(),
171
+ query: text("query").notNull(),
172
+ query_canonical: text("query_canonical").notNull(),
173
+ normalizer_version: integer("normalizer_version").notNull(),
174
+ intent_code: integer("intent_code"),
175
+ intent_version: integer("intent_version"),
176
+ built_at: integer("built_at")
177
+ }, (t) => [index("idx_gsc_query_dim_site_query").on(t.site_id, t.query)]);
119
178
  const schema = {
120
179
  gsc_pages,
121
180
  gsc_keywords,
122
181
  gsc_countries,
123
182
  gsc_devices,
124
183
  gsc_page_keywords,
125
- gsc_search_appearance: sqliteTable("gsc_search_appearance", {
126
- ...baseCols(),
127
- searchAppearance: text("searchAppearance").notNull(),
128
- ...metricCols()
129
- }),
130
- gsc_search_appearance_pages: sqliteTable("gsc_search_appearance_pages", {
131
- ...baseCols(),
132
- searchAppearance: text("searchAppearance").notNull(),
133
- url: text("url").notNull(),
134
- ...metricCols()
135
- }),
136
- gsc_search_appearance_queries: sqliteTable("gsc_search_appearance_queries", {
137
- ...baseCols(),
138
- searchAppearance: text("searchAppearance").notNull(),
139
- query: text("query").notNull(),
140
- query_canonical: text("query_canonical"),
141
- ...metricCols()
142
- }),
143
- gsc_search_appearance_page_queries: sqliteTable("gsc_search_appearance_page_queries", {
144
- ...baseCols(),
145
- searchAppearance: text("searchAppearance").notNull(),
146
- url: text("url").notNull(),
147
- query: text("query").notNull(),
148
- query_canonical: text("query_canonical"),
149
- ...metricCols()
150
- }),
184
+ gsc_search_appearance,
185
+ gsc_search_appearance_pages,
186
+ gsc_search_appearance_queries,
187
+ gsc_search_appearance_page_queries,
151
188
  gsc_hourly_pages: sqliteTable("gsc_hourly_pages", {
152
189
  ...baseCols(),
153
190
  url: text("url").notNull(),
154
191
  hour: integer("hour").notNull(),
155
192
  ...metricCols()
156
- })
193
+ }, (t) => [index("idx_gsc_hourly_pages_site_date").on(t.site_id, t.date)]),
194
+ gsc_query_dim
157
195
  };
158
196
  const GSC_TABLE_TO_LOGICAL = {
159
197
  gsc_pages: "pages",
@@ -165,7 +203,8 @@ const GSC_TABLE_TO_LOGICAL = {
165
203
  gsc_search_appearance_pages: "search_appearance_pages",
166
204
  gsc_search_appearance_queries: "search_appearance_queries",
167
205
  gsc_search_appearance_page_queries: "search_appearance_page_queries",
168
- gsc_hourly_pages: "hourly_pages"
206
+ gsc_hourly_pages: "hourly_pages",
207
+ gsc_query_dim: null
169
208
  };
170
209
  assertSchemaInSync({
171
210
  label: "sqlite",
@@ -217,6 +256,8 @@ function createSqliteResolverAdapter(options = {}) {
217
256
  regexPredicate: (expr, pattern, negate) => negate ? sql$1`NOT (${expr} REGEXP ${pattern})` : sql$1`${expr} REGEXP ${pattern}`,
218
257
  tableLabel: "sqlite/resolver-adapter",
219
258
  includeSiteId: true,
259
+ queryDimTableRef: () => sql$1.raw("\"gsc_query_dim\" AS \"query_dim\""),
260
+ queryDimSiteScoped: true,
220
261
  compile: compileSqlite,
221
262
  capabilities: {
222
263
  regex: options.regex ?? false,
@@ -272,6 +313,7 @@ const r2Manifest = sqliteTable("r2_manifest", {
272
313
  schemaVersion: integer("schema_version")
273
314
  }, (t) => [
274
315
  index("idx_r2_manifest_live").on(t.userId, t.siteId, t.table, t.partition, t.retiredAt),
316
+ index("idx_r2_manifest_lookup").on(t.userId, t.siteId, t.table, t.searchType, t.tier, t.partition, t.retiredAt),
275
317
  index("idx_r2_manifest_retired").on(t.retiredAt),
276
318
  index("idx_r2_manifest_tier").on(t.userId, t.siteId, t.table, t.tier, t.retiredAt),
277
319
  unique("r2_manifest_object_key_unique").on(t.objectKey)
@@ -372,6 +414,8 @@ const LOCK_TTL_MS = 3e4;
372
414
  const LOCK_ACQUIRE_TIMEOUT_MS = 5e3;
373
415
  const LOCK_RETRY_MIN_MS = 25;
374
416
  const LOCK_RETRY_MAX_MS = 150;
417
+ const D1_BATCH_LIMIT = 95;
418
+ const D1_IN_CLAUSE_CHUNK = 90;
375
419
  function lockScopeKey(scope) {
376
420
  return `${scope.userId}|${siteIdOf(scope.siteId)}|${scope.table}|${scope.partition}`;
377
421
  }
@@ -396,15 +440,15 @@ function createD1ManifestStore(db) {
396
440
  }
397
441
  if (filter.searchType !== void 0) baseConds.push(filter.searchType === "web" ? or(eq$1(r2Manifest.searchType, "web"), isNull(r2Manifest.searchType)) : eq$1(r2Manifest.searchType, filter.searchType));
398
442
  const PARTITION_CHUNK = 80;
399
- if (filter.partitions && filter.partitions.length > 0) {
400
- const out = [];
443
+ if (filter.partitions) {
444
+ if (filter.partitions.length === 0) return [];
445
+ const statements = [];
401
446
  for (let i = 0; i < filter.partitions.length; i += PARTITION_CHUNK) {
402
447
  const slice = filter.partitions.slice(i, i + PARTITION_CHUNK);
403
448
  const conds = [...baseConds, inArray(r2Manifest.partition, slice)];
404
- const rows = await db.select().from(r2Manifest).where(and$1(...conds));
405
- for (const r of rows) out.push(fromRow(r));
449
+ statements.push(db.select().from(r2Manifest).where(and$1(...conds)));
406
450
  }
407
- return out;
451
+ return (await db.batch(statements)).flat().map((r) => fromRow(r));
408
452
  }
409
453
  return (await db.select().from(r2Manifest).where(and$1(...baseConds))).map(fromRow);
410
454
  }
@@ -415,9 +459,8 @@ function createD1ManifestStore(db) {
415
459
  const statements = [];
416
460
  if (superseding && superseding.length > 0) {
417
461
  const keys = superseding.map((s) => s.objectKey);
418
- const CHUNK = 90;
419
- for (let i = 0; i < keys.length; i += CHUNK) {
420
- const slice = keys.slice(i, i + CHUNK);
462
+ for (let i = 0; i < keys.length; i += D1_IN_CLAUSE_CHUNK) {
463
+ const slice = keys.slice(i, i + D1_IN_CLAUSE_CHUNK);
421
464
  statements.push(db.update(r2Manifest).set({ retiredAt: supersededAt }).where(and$1(inArray(r2Manifest.objectKey, slice), isNull(r2Manifest.retiredAt))));
422
465
  }
423
466
  }
@@ -438,9 +481,8 @@ function createD1ManifestStore(db) {
438
481
  }
439
482
  }));
440
483
  if (statements.length === 0) return;
441
- const BATCH_LIMIT = 95;
442
- for (let i = 0; i < statements.length; i += BATCH_LIMIT) {
443
- const chunk = statements.slice(i, i + BATCH_LIMIT);
484
+ for (let i = 0; i < statements.length; i += D1_BATCH_LIMIT) {
485
+ const chunk = statements.slice(i, i + D1_BATCH_LIMIT);
444
486
  await db.batch(chunk);
445
487
  }
446
488
  }
@@ -450,8 +492,9 @@ function createD1ManifestStore(db) {
450
492
  async function deleteEntries(entries) {
451
493
  if (entries.length === 0) return;
452
494
  const keys = entries.map((e) => e.objectKey);
453
- const CHUNK = 90;
454
- for (let i = 0; i < keys.length; i += CHUNK) await db.delete(r2Manifest).where(inArray(r2Manifest.objectKey, keys.slice(i, i + CHUNK)));
495
+ const statements = [];
496
+ for (let i = 0; i < keys.length; i += D1_IN_CLAUSE_CHUNK) statements.push(db.delete(r2Manifest).where(inArray(r2Manifest.objectKey, keys.slice(i, i + D1_IN_CLAUSE_CHUNK))));
497
+ for (let i = 0; i < statements.length; i += D1_BATCH_LIMIT) await db.batch(statements.slice(i, i + D1_BATCH_LIMIT));
455
498
  }
456
499
  async function getWatermarks(filter) {
457
500
  const conds = [eq$1(r2Watermarks.userId, Number(filter.userId))];
@@ -484,7 +527,7 @@ function createD1ManifestStore(db) {
484
527
  set: {
485
528
  newestDateSynced: sql$1`CASE WHEN excluded.newest_date_synced > newest_date_synced THEN excluded.newest_date_synced ELSE newest_date_synced END`,
486
529
  oldestDateSynced: sql$1`CASE WHEN excluded.oldest_date_synced < oldest_date_synced THEN excluded.oldest_date_synced ELSE oldest_date_synced END`,
487
- lastSyncAt: sql$1`excluded.last_sync_at`
530
+ lastSyncAt: sql$1`CASE WHEN excluded.last_sync_at > last_sync_at THEN excluded.last_sync_at ELSE last_sync_at END`
488
531
  }
489
532
  }).run();
490
533
  }
@@ -607,4 +650,4 @@ function createD1ManifestStore(db) {
607
650
  purgeTenant
608
651
  };
609
652
  }
610
- export { aggClicks, aggCtr, aggImpressions, aggPosition, and, compileSqlite, createCachedManifestStore, createD1ManifestStore, createEngine, createSqliteInsightRunner, createSqliteResolverAdapter, createSqliteResolverAdapterFromExecutor, eq, gsc_countries, gsc_devices, gsc_keywords, gsc_page_keywords, gsc_pages, gte, lte, mergeScope, probeSqliteRegex, r2Locks, r2Manifest, r2ShadowDiffs, r2SyncStates, r2Watermarks, r2WriteErrors, resolveWindow, schema, scopeFor, sql, sqliteResolverAdapter };
653
+ export { aggClicks, aggCtr, aggImpressions, aggPosition, and, compileSqlite, createCachedManifestStore, createD1ManifestStore, createEngine, createSqliteInsightRunner, createSqliteResolverAdapter, createSqliteResolverAdapterFromExecutor, eq, gsc_countries, gsc_devices, gsc_keywords, gsc_page_keywords, gsc_pages, gsc_query_dim, gte, lte, mergeScope, probeSqliteRegex, r2Locks, r2Manifest, r2ShadowDiffs, r2SyncStates, r2Watermarks, r2WriteErrors, resolveWindow, schema, scopeFor, sql, sqliteResolverAdapter };
@@ -16,6 +16,7 @@ const r2Manifest = sqliteTable("r2_manifest", {
16
16
  schemaVersion: integer("schema_version")
17
17
  }, (t) => [
18
18
  index("idx_r2_manifest_live").on(t.userId, t.siteId, t.table, t.partition, t.retiredAt),
19
+ index("idx_r2_manifest_lookup").on(t.userId, t.siteId, t.table, t.searchType, t.tier, t.partition, t.retiredAt),
19
20
  index("idx_r2_manifest_retired").on(t.retiredAt),
20
21
  index("idx_r2_manifest_tier").on(t.userId, t.siteId, t.table, t.tier, t.retiredAt),
21
22
  unique("r2_manifest_object_key_unique").on(t.objectKey)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/engine-sqlite",
3
3
  "type": "module",
4
- "version": "0.32.12",
4
+ "version": "0.33.3",
5
5
  "description": "SQLite / D1 engine adapter for @gscdump/analysis — typed analytics over sqlite-proxy executors (Cloudflare D1, libsql).",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -44,8 +44,8 @@
44
44
  "drizzle-orm": "1.0.0-rc.3"
45
45
  },
46
46
  "dependencies": {
47
- "@gscdump/engine": "0.32.12",
48
- "gscdump": "0.32.12"
47
+ "@gscdump/engine": "0.33.3",
48
+ "gscdump": "0.33.3"
49
49
  },
50
50
  "devDependencies": {
51
51
  "drizzle-orm": "1.0.0-rc.3",