@lunora/d1 1.0.0-alpha.5 → 1.0.0-alpha.51

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/LICENSE.md CHANGED
@@ -103,3 +103,9 @@ Unless required by applicable law or agreed to in writing, software distributed
103
103
  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
104
  CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
105
  specific language governing permissions and limitations under the License.
106
+
107
+ <!-- DEPENDENCIES -->
108
+ <!-- /DEPENDENCIES -->
109
+
110
+ <!-- TYPE_DEPENDENCIES -->
111
+ <!-- /TYPE_DEPENDENCIES -->
@@ -1,38 +1,40 @@
1
1
  /**
2
- * The Lunora **D1 dialect** the single source of truth for how `.global()`
3
- * tables are physically shaped in D1.
4
- *
5
- * Both the runtime (`runD1GlobalTableMigrations` in `d1-ctx-db.ts`, which
6
- * auto-provisions tables) and the `lunora migrate generate` SQL emitter
7
- * (`@lunora/cli`'s `migration-diff.ts`) derive their DDL from these helpers, so
8
- * the table a migration writes is byte-identical to the one the runtime creates.
9
- * Previously each encoded the dialect independently and a comment begged them to
10
- * stay "in lockstep"; this module makes the lockstep structural.
11
- *
12
- * Exposed as the `@lunora/d1/dialect` subpath. Pure no runtime dependencies
13
- * so the CLI can import it without pulling the D1 runtime.
14
- */
2
+ * Canonical SQL identifier quoter shared by `@lunora/d1` and `@lunora/do`.
3
+ *
4
+ * Double-quotes a SQL identifier and escapes any embedded double quotes by
5
+ * doubling them (`"` `""`) — the ANSI/SQLite/Postgres rule. This is a
6
+ * security-relevant primitive (it is the sole defense against identifier
7
+ * injection wherever a table/column name is spliced into raw SQL), so it must
8
+ * have exactly ONE definition rather than byte-identical copies that can drift.
9
+ *
10
+ * Like `shared/stable-key.ts`, it is deliberately **not** a package: `@lunora/d1`
11
+ * and `@lunora/do` sit on the same tier with no lower-level package to host it,
12
+ * so each imports this file by relative path and the bundler (packem/rollup)
13
+ * inlines it no runtime dependency edge, duplicated only in emitted output.
14
+ * Keep it genuinely zero-dependency (relative/built-in imports only) or inlining
15
+ * breaks. Consumers must drop `outDir`/`rootDir` from their `tsconfig.json` (a
16
+ * set `rootDir` raises TS6059 for this out-of-package file under `tsc --noEmit`).
17
+ */
18
+ declare const quoteIdentifier: (name: string) => string;
15
19
  /** SQLite column type affinities Lunora emits. */
16
20
  type SqlAffinity = "BLOB" | "INTEGER" | "REAL" | "TEXT";
17
- /** Double-quote (and escape) a SQL identifier. */
18
- declare const quoteIdentifier: (name: string) => string;
19
21
  /**
20
- * SQLite affinity for a column by its validator `kind`, chosen so the value the
21
- * D1 layer serializes round-trips intact:
22
- * - `boolean` → INTEGER (stored as 1/0)
23
- * - `number`/`timestamp`/`date` → REAL (numeric, never coerced to text)
24
- * - `bytes` → BLOB
25
- * - everything else → TEXT — string/id/literal, `bigint` (serialized as a
26
- * decimal string), and object/array/record/union/any (JSON). A numeric affinity
27
- * would coerce a numeric-looking string and corrupt the decode.
28
- */
22
+ * SQLite affinity for a column by its validator `kind`, chosen so the value the
23
+ * D1 layer serializes round-trips intact:
24
+ * - `boolean` → INTEGER (stored as 1/0)
25
+ * - `number`/`timestamp`/`date` → REAL (numeric, never coerced to text)
26
+ * - `bytes` → BLOB
27
+ * - everything else → TEXT — string/id/literal, `bigint` (serialized as a
28
+ * decimal string), and object/array/record/union/any (JSON). A numeric affinity
29
+ * would coerce a numeric-looking string and corrupt the decode.
30
+ */
29
31
  declare const sqlAffinityForKind: (kind: string | undefined) => SqlAffinity;
30
32
  /** Framework columns every global table carries: the physical `id` (exposed as `_id`) and `_creationTime`. */
31
33
  declare const frameworkColumnDdl: () => ReadonlyArray<string>;
32
34
  /**
33
- * Resolve a schema field to its physical D1 column: `_id`/`id` both map to the
34
- * physical `id` column, `_creationTime` to its own, every other field to itself.
35
- */
35
+ * Resolve a schema field to its physical D1 column: `_id`/`id` both map to the
36
+ * physical `id` column, `_creationTime` to its own, every other field to itself.
37
+ */
36
38
  declare const columnRef: (field: string) => string;
37
39
  /** Physical index identifier — `&lt;table>_&lt;name>`, so two tables' like-named indexes don't collide in SQLite's flat index namespace. */
38
40
  declare const physicalIndexName: (tableName: string, indexName: string) => string;
package/dist/dialect.d.ts CHANGED
@@ -1,38 +1,40 @@
1
1
  /**
2
- * The Lunora **D1 dialect** the single source of truth for how `.global()`
3
- * tables are physically shaped in D1.
4
- *
5
- * Both the runtime (`runD1GlobalTableMigrations` in `d1-ctx-db.ts`, which
6
- * auto-provisions tables) and the `lunora migrate generate` SQL emitter
7
- * (`@lunora/cli`'s `migration-diff.ts`) derive their DDL from these helpers, so
8
- * the table a migration writes is byte-identical to the one the runtime creates.
9
- * Previously each encoded the dialect independently and a comment begged them to
10
- * stay "in lockstep"; this module makes the lockstep structural.
11
- *
12
- * Exposed as the `@lunora/d1/dialect` subpath. Pure no runtime dependencies
13
- * so the CLI can import it without pulling the D1 runtime.
14
- */
2
+ * Canonical SQL identifier quoter shared by `@lunora/d1` and `@lunora/do`.
3
+ *
4
+ * Double-quotes a SQL identifier and escapes any embedded double quotes by
5
+ * doubling them (`"` `""`) — the ANSI/SQLite/Postgres rule. This is a
6
+ * security-relevant primitive (it is the sole defense against identifier
7
+ * injection wherever a table/column name is spliced into raw SQL), so it must
8
+ * have exactly ONE definition rather than byte-identical copies that can drift.
9
+ *
10
+ * Like `shared/stable-key.ts`, it is deliberately **not** a package: `@lunora/d1`
11
+ * and `@lunora/do` sit on the same tier with no lower-level package to host it,
12
+ * so each imports this file by relative path and the bundler (packem/rollup)
13
+ * inlines it no runtime dependency edge, duplicated only in emitted output.
14
+ * Keep it genuinely zero-dependency (relative/built-in imports only) or inlining
15
+ * breaks. Consumers must drop `outDir`/`rootDir` from their `tsconfig.json` (a
16
+ * set `rootDir` raises TS6059 for this out-of-package file under `tsc --noEmit`).
17
+ */
18
+ declare const quoteIdentifier: (name: string) => string;
15
19
  /** SQLite column type affinities Lunora emits. */
16
20
  type SqlAffinity = "BLOB" | "INTEGER" | "REAL" | "TEXT";
17
- /** Double-quote (and escape) a SQL identifier. */
18
- declare const quoteIdentifier: (name: string) => string;
19
21
  /**
20
- * SQLite affinity for a column by its validator `kind`, chosen so the value the
21
- * D1 layer serializes round-trips intact:
22
- * - `boolean` → INTEGER (stored as 1/0)
23
- * - `number`/`timestamp`/`date` → REAL (numeric, never coerced to text)
24
- * - `bytes` → BLOB
25
- * - everything else → TEXT — string/id/literal, `bigint` (serialized as a
26
- * decimal string), and object/array/record/union/any (JSON). A numeric affinity
27
- * would coerce a numeric-looking string and corrupt the decode.
28
- */
22
+ * SQLite affinity for a column by its validator `kind`, chosen so the value the
23
+ * D1 layer serializes round-trips intact:
24
+ * - `boolean` → INTEGER (stored as 1/0)
25
+ * - `number`/`timestamp`/`date` → REAL (numeric, never coerced to text)
26
+ * - `bytes` → BLOB
27
+ * - everything else → TEXT — string/id/literal, `bigint` (serialized as a
28
+ * decimal string), and object/array/record/union/any (JSON). A numeric affinity
29
+ * would coerce a numeric-looking string and corrupt the decode.
30
+ */
29
31
  declare const sqlAffinityForKind: (kind: string | undefined) => SqlAffinity;
30
32
  /** Framework columns every global table carries: the physical `id` (exposed as `_id`) and `_creationTime`. */
31
33
  declare const frameworkColumnDdl: () => ReadonlyArray<string>;
32
34
  /**
33
- * Resolve a schema field to its physical D1 column: `_id`/`id` both map to the
34
- * physical `id` column, `_creationTime` to its own, every other field to itself.
35
- */
35
+ * Resolve a schema field to its physical D1 column: `_id`/`id` both map to the
36
+ * physical `id` column, `_creationTime` to its own, every other field to itself.
37
+ */
36
38
  declare const columnRef: (field: string) => string;
37
39
  /** Physical index identifier — `&lt;table>_&lt;name>`, so two tables' like-named indexes don't collide in SQLite's flat index namespace. */
38
40
  declare const physicalIndexName: (tableName: string, indexName: string) => string;
package/dist/dialect.mjs CHANGED
@@ -1,35 +1 @@
1
- const quoteIdentifier = (name) => `"${name.replaceAll('"', '""')}"`;
2
- const sqlAffinityForKind = (kind) => {
3
- switch (kind) {
4
- case "boolean": {
5
- return "INTEGER";
6
- }
7
- case "bytes": {
8
- return "BLOB";
9
- }
10
- case "date":
11
- case "number":
12
- case "timestamp": {
13
- return "REAL";
14
- }
15
- default: {
16
- return "TEXT";
17
- }
18
- }
19
- };
20
- const frameworkColumnDdl = () => [
21
- `${quoteIdentifier("id")} TEXT PRIMARY KEY`,
22
- `${quoteIdentifier("_creationTime")} REAL NOT NULL`
23
- ];
24
- const columnRef = (field) => {
25
- if (field === "_id" || field === "id") {
26
- return quoteIdentifier("id");
27
- }
28
- if (field === "_creationTime") {
29
- return quoteIdentifier("_creationTime");
30
- }
31
- return quoteIdentifier(field);
32
- };
33
- const physicalIndexName = (tableName, indexName) => quoteIdentifier(`${tableName}_${indexName}`);
34
-
35
- export { columnRef, frameworkColumnDdl, physicalIndexName, quoteIdentifier, sqlAffinityForKind };
1
+ import{quoteIdentifier as i}from"./packem_shared/quoteIdentifier-CObIFRhb.mjs";const t=e=>{switch(e){case"boolean":return"INTEGER";case"bytes":return"BLOB";case"date":case"number":case"timestamp":return"REAL";default:return"TEXT"}},a=()=>[`${i("id")} TEXT PRIMARY KEY`,`${i("_creationTime")} REAL NOT NULL`],o=e=>e==="_id"||e==="id"?i("id"):e==="_creationTime"?i("_creationTime"):i(e),c=(e,r)=>i(`${e}_${r}`);export{o as columnRef,a as frameworkColumnDdl,c as physicalIndexName,i as quoteIdentifier,t as sqlAffinityForKind};
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { SchemaLike, DatabaseWriterLike } from '@lunora/do';
2
- import { SqlCtxDbOptions, createSqlCtxDb, SqlCtxExec, readSqlCdcChanges, SqlDialect } from '@lunora/sql-store';
2
+ import { SqlCtxDbOptions, SqlCtxExec, createSqlCtxDb, readSqlCdcChanges, SqlDialect } from '@lunora/sql-store';
3
3
  export { type SqlCtxExec as D1Exec, type SqlCtxDbOptions, type SqlCtxExec, createSqlCtxDb } from '@lunora/sql-store';
4
4
  import { BatchItem, BatchResponse } from 'drizzle-orm/batch';
5
5
  import { DrizzleD1Database } from 'drizzle-orm/d1';
@@ -13,8 +13,10 @@ declare const runD1GlobalTableMigrations: (exec: SqlCtxExec, schema: SchemaLike)
13
13
  declare const runD1AggregateMigrations: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
14
14
  /** Materialize the `__rank_&lt;index>` companion tables for the schema's rank indexes. */
15
15
  declare const runD1RankMigrations: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
16
- /** Materialize the `__fts_&lt;index>` fts5 shadow tables for the schema's search indexes (no-op without fts5). */
16
+ /** Materialize (and backfill) the `__fts_&lt;index>` fts5 shadow tables for the schema's search indexes. */
17
17
  declare const runD1SearchMigrations: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
18
+ /** Index existing rows into every search companion, including the `staged: true` ones migrations leave empty. */
19
+ declare const backfillD1SearchIndexes: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
18
20
  /** Create the `__cdc_log` table in D1 (idempotent; only run when CDC is enabled). */
19
21
  declare const runD1CdcMigration: (exec: SqlCtxExec) => Promise<void>;
20
22
  /** Read changelog entries newer than `sinceSeq` in commit order. */
@@ -42,32 +44,42 @@ interface ImportResult {
42
44
  inserted: Record<string, number>;
43
45
  }
44
46
  /**
45
- * Return every `.global()` table in the schema, optionally narrowed by an
46
- * allowlist. Shard-local tables are skipped here — they're handled by the DO
47
- * helpers — so callers get a clean separation between the two storage planes.
48
- */
47
+ * Return every `.global()` table in the schema, optionally narrowed by an
48
+ * allowlist. Shard-local tables are skipped here — they're handled by the DO
49
+ * helpers — so callers get a clean separation between the two storage planes.
50
+ */
49
51
  declare const selectGlobalTables: (schema: SchemaLike, requested?: ReadonlyArray<string>) => string[];
50
52
  interface ExportGlobalArgs {
51
53
  batchSize?: number;
52
54
  tables?: ReadonlyArray<string>;
53
55
  }
54
56
  /**
55
- * Yield rows from every requested `.global()` table in batches. Uses
56
- * `LIMIT ?/OFFSET ?` because D1 globals don't have a stable keyset abstraction
57
- * here (the writer's `findMany` does, but at the cost of routing through the
58
- * full validator pipeline; for a snapshot stream a plain offset scan is
59
- * sufficient and predictable).
60
- */
57
+ * Yield rows from every requested `.global()` table in batches.
58
+ *
59
+ * Keyset-paginates on the physical primary key (`id` every `.global()` table
60
+ * carries it, see `frameworkColumnDdl`): `WHERE "id" > ? ORDER BY "id" LIMIT ?`,
61
+ * carrying the last id forward. A plain `LIMIT/OFFSET` scan would be wrong here —
62
+ * SQLite gives no ordering guarantee for an unordered SELECT and each page is a
63
+ * separate query, so pages could overlap or skip rows (and any concurrent
64
+ * insert/delete would shift offsets and silently drop/duplicate rows in the
65
+ * snapshot). Keyset paging is deterministic under concurrent writes and avoids
66
+ * O(n^2) OFFSET scans on large tables.
67
+ *
68
+ * Tables are provisioned first (idempotent `CREATE … IF NOT EXISTS`): `.global()`
69
+ * tables are created lazily on first write, so a fresh deployment — or any table
70
+ * never written — would otherwise abort the stream with a raw `no such table`
71
+ * instead of exporting it as empty.
72
+ */
61
73
  declare const exportGlobalRows: (exec: SqlCtxExec, schema: SchemaLike, args: ExportGlobalArgs) => AsyncGenerator<ExportRow, void, undefined>;
62
74
  interface ImportGlobalArgs {
63
75
  /**
64
- * Optional direct exec handle to the same D1 database the writer targets.
65
- * When supplied, the conflict pre-probe issues a single
66
- * `SELECT 1 FROM &lt;table> WHERE id = ? LIMIT 1` against the row's declared
67
- * table instead of falling back to `writer.get(id)`, which scans every
68
- * global table looking for the id. Strongly recommended for large schemas
69
- * — the writer-fallback is O(N tables) per row.
70
- */
76
+ * Optional direct exec handle to the same D1 database the writer targets.
77
+ * When supplied, the conflict pre-probe issues a single
78
+ * `SELECT 1 FROM &lt;table> WHERE id = ? LIMIT 1` against the row's declared
79
+ * table instead of falling back to `writer.get(id)`, which scans every
80
+ * global table looking for the id. Strongly recommended for large schemas
81
+ * — the writer-fallback is O(N tables) per row.
82
+ */
71
83
  exec?: D1ExecLike;
72
84
  rows: ReadonlyArray<ExportRow>;
73
85
  startLine?: number;
@@ -77,20 +89,19 @@ interface D1ExecLike {
77
89
  all: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
78
90
  }
79
91
  /**
80
- * Import rows into `.global()` tables via the schema-aware D1 writer. The
81
- * writer rejects unknown ids on `insert` (the writer assigns one when `_id` is
82
- * absent); we pre-probe each row's `_id` so a collision is reported as a
83
- * conflict instead of bubbled as a UNIQUE error. Schema-failed rows surface in
84
- * `errors`; the rest land.
85
- */
92
+ * Import rows into `.global()` tables via the schema-aware D1 writer. The
93
+ * writer rejects unknown ids on `insert` (the writer assigns one when `_id` is
94
+ * absent); we pre-probe each row's `_id` so a collision is reported as a
95
+ * conflict instead of bubbled as a UNIQUE error. Schema-failed rows surface in
96
+ * `errors`; the rest land.
97
+ */
86
98
  declare const importGlobalRows: (writer: DatabaseWriterLike, schema: SchemaLike, args: ImportGlobalArgs) => Promise<ImportResult>;
87
99
  /**
88
- * Minimal structural projection of `D1Database` to keep the adapter
89
- * compatible with the real workers-types value as well as unit-test doubles.
90
- */
100
+ * Minimal structural projection of `D1Database` to keep the adapter
101
+ * compatible with the real workers-types value as well as unit-test doubles.
102
+ */
91
103
  interface D1DatabaseLike {
92
104
  batch?: (statements: D1PreparedStatementLike[]) => Promise<unknown[]>;
93
- exec?: (sql: string) => Promise<unknown>;
94
105
  prepare: (sql: string) => D1PreparedStatementLike;
95
106
  withSession: (bookmark?: string) => D1SessionLike;
96
107
  }
@@ -131,67 +142,67 @@ declare class D1Session {
131
142
  }>;
132
143
  first<T = unknown>(sql: string, ...binds: unknown[]): Promise<T | null>;
133
144
  /**
134
- * Returns the most recent bookmark known to the session, or `undefined`
135
- * when D1 has not issued one yet.
136
- */
145
+ * Returns the most recent bookmark known to the session, or `undefined`
146
+ * when D1 has not issued one yet.
147
+ */
137
148
  getBookmark(): string | undefined;
138
149
  }
139
150
  declare class D1Client {
140
151
  private readonly db;
141
152
  /**
142
- * SQL string -> prepared statement. Prepared statements are reusable in
143
- * D1; preparing the same SQL twice forces the worker to round-trip the
144
- * statement plan. Caching is per-instance so unit-test isolation holds.
145
- * Bounded to {@link STMT_CACHE_CAPACITY} via LRU eviction.
146
- */
153
+ * SQL string -> prepared statement. Prepared statements are reusable in
154
+ * D1; preparing the same SQL twice forces the worker to round-trip the
155
+ * statement plan. Caching is per-instance so unit-test isolation holds.
156
+ * Bounded to {@link STMT_CACHE_CAPACITY} via LRU eviction.
157
+ */
147
158
  private readonly stmtCache;
148
159
  /**
149
- * Lazily-built drizzle handle over the bare binding. Memoised so a single
150
- * `D1Client` reuses the same dialect/session machinery across calls.
151
- */
160
+ * Lazily-built drizzle handle over the bare binding. Memoised so a single
161
+ * `D1Client` reuses the same dialect/session machinery across calls.
162
+ */
152
163
  private drizzleHandle;
153
164
  constructor(database: D1DatabaseLike);
154
165
  /**
155
- * Open a Sessions-API scoped session. Pass the bookmark forwarded by
156
- * the client to opt into read-your-writes consistency.
157
- *
158
- * With no bookmark this is the first request of a session — there is no
159
- * prior write to read, so we open with the explicit `"first-unconstrained"`
160
- * constraint (Cloudflare's lowest-latency default: the first read may serve
161
- * from any replica). Read-your-writes for sequenced requests still flows
162
- * through the forwarded bookmark; a caller needing a strongly-consistent
163
- * very-first read should pass `"first-primary"` as the bookmark instead.
164
- */
166
+ * Open a Sessions-API scoped session. Pass the bookmark forwarded by
167
+ * the client to opt into read-your-writes consistency.
168
+ *
169
+ * With no bookmark this is the first request of a session — there is no
170
+ * prior write to read, so we open with the explicit `"first-unconstrained"`
171
+ * constraint (Cloudflare's lowest-latency default: the first read may serve
172
+ * from any replica). Read-your-writes for sequenced requests still flows
173
+ * through the forwarded bookmark; a caller needing a strongly-consistent
174
+ * very-first read should pass `"first-primary"` as the bookmark instead.
175
+ */
165
176
  withSession(bookmark?: string): D1Session;
166
177
  /**
167
- * Prepare a statement, reusing a cached one when the SQL text matches.
168
- * `bind()` on a prepared statement returns a new bound statement and
169
- * leaves the underlying prepared plan reusable, so cache hits are safe
170
- * even when the previous caller already called `.bind(...).run()`.
171
- */
178
+ * Prepare a statement, reusing a cached one when the SQL text matches.
179
+ * `bind()` on a prepared statement returns a new bound statement and
180
+ * leaves the underlying prepared plan reusable, so cache hits are safe
181
+ * even when the previous caller already called `.bind(...).run()`.
182
+ */
172
183
  prepare(sql: string): D1PreparedStatementLike;
173
184
  /**
174
- * Drizzle handle over the bare `env.DB` binding. Used for typed queries
175
- * against generated `sqliteTable` schemas; does **not** participate in the
176
- * D1 Sessions API (no bookmark pinning). For bookmark-scoped reads, use
177
- * {@link drizzleSession} instead.
178
- */
185
+ * Drizzle handle over the bare `env.DB` binding. Used for typed queries
186
+ * against generated `sqliteTable` schemas; does **not** participate in the
187
+ * D1 Sessions API (no bookmark pinning). For bookmark-scoped reads, use
188
+ * {@link drizzleSession} instead.
189
+ */
179
190
  get drizzle(): DrizzleD1Database<Record<string, unknown>>;
180
191
  /**
181
- * Drizzle handle scoped to a D1 Sessions-API session. The bookmark, when
182
- * supplied, opts into read-your-writes consistency for follow-up reads on
183
- * the same session.
184
- *
185
- * A `D1DatabaseSession` exposes the same `prepare` / `batch` surface
186
- * drizzle calls into, so a single `unknown` cast lets us treat the session
187
- * as a `D1Database` for driver-construction purposes.
188
- */
192
+ * Drizzle handle scoped to a D1 Sessions-API session. The bookmark, when
193
+ * supplied, opts into read-your-writes consistency for follow-up reads on
194
+ * the same session.
195
+ *
196
+ * A `D1DatabaseSession` exposes the same `prepare` / `batch` surface
197
+ * drizzle calls into, so a single `unknown` cast lets us treat the session
198
+ * as a `D1Database` for driver-construction purposes.
199
+ */
189
200
  drizzleSession(bookmark?: string): DrizzleD1Database<Record<string, unknown>>;
190
201
  /**
191
- * Atomic batch over the drizzle d1 driver. Mirrors `db.batch([...])`
192
- * exactly; exposed on the client so callers don't need to hold a drizzle
193
- * handle just to run a typed batch.
194
- */
202
+ * Atomic batch over the drizzle d1 driver. Mirrors `db.batch([...])`
203
+ * exactly; exposed on the client so callers don't need to hold a drizzle
204
+ * handle just to run a typed batch.
205
+ */
195
206
  batch<U extends BatchItem<"sqlite">, T extends Readonly<[U, ...U[]]>>(items: T): Promise<BatchResponse<T>>;
196
207
  /** Direct access to the underlying binding (advanced use only). */
197
208
  get raw(): D1DatabaseLike;
@@ -205,24 +216,24 @@ interface GlobalTableInfo {
205
216
  interface GlobalTablePage {
206
217
  columns: string[];
207
218
  /**
208
- * Foreign-key columns (local column → referenced table) for tables that carry
209
- * real SQL `REFERENCES` constraints — recovered from `PRAGMA foreign_key_list`.
210
- * Schema `.global()` tables omit this (their refs come from `describeTables`);
211
- * external tables (e.g. better-auth's `session`/`twoFactor`) expose it so the
212
- * schema diagram can draw their global→global FK edges.
213
- */
219
+ * Foreign-key columns (local column → referenced table) for tables that carry
220
+ * real SQL `REFERENCES` constraints — recovered from `PRAGMA foreign_key_list`.
221
+ * Schema `.global()` tables omit this (their refs come from `describeTables`);
222
+ * external tables (e.g. better-auth's `session`/`twoFactor`) expose it so the
223
+ * schema diagram can draw their global→global FK edges.
224
+ */
214
225
  refs?: Record<string, string>;
215
226
  rows: Record<string, unknown>[];
216
227
  total: number;
217
228
  }
218
229
  /**
219
- * One equality constraint a facet-value click adds to the global browser's view:
220
- * `column = value` (or `column IS NULL` when `value` is nullish). `column` is a
221
- * displayed column name, validated against the table's columns and mapped to its
222
- * physical column (`_id` → `id`) before it is quoted; `value` is the **raw stored
223
- * value** the facet returned (a SQLite scalar), bound as a parameter and never
224
- * interpolated. AND-combined with the other clauses.
225
- */
230
+ * One equality constraint a facet-value click adds to the global browser's view:
231
+ * `column = value` (or `column IS NULL` when `value` is nullish). `column` is a
232
+ * displayed column name, validated against the table's columns and mapped to its
233
+ * physical column (`_id` → `id`) before it is quoted; `value` is the **raw stored
234
+ * value** the facet returned (a SQLite scalar), bound as a parameter and never
235
+ * interpolated. AND-combined with the other clauses.
236
+ */
226
237
  interface GlobalFilterClause {
227
238
  column: string;
228
239
  value: unknown;
@@ -234,13 +245,13 @@ interface ReadGlobalTablePageOptions {
234
245
  table: string;
235
246
  }
236
247
  /**
237
- * Options for {@link facetGlobalColumn} — the read-only "what values does this
238
- * column hold?" summary for the global (D1) browser. `column` is the displayed
239
- * column to group by (validated and mapped to its physical column, never
240
- * interpolated); `filters` mirrors {@link ReadGlobalTablePageOptions}'s eq
241
- * constraints so the facet reflects the **active view** (the same rows the
242
- * browser is previewing); `limit` caps the distinct values returned (clamped).
243
- */
248
+ * Options for {@link facetGlobalColumn} — the read-only "what values does this
249
+ * column hold?" summary for the global (D1) browser. `column` is the displayed
250
+ * column to group by (validated and mapped to its physical column, never
251
+ * interpolated); `filters` mirrors {@link ReadGlobalTablePageOptions}'s eq
252
+ * constraints so the facet reflects the **active view** (the same rows the
253
+ * browser is previewing); `limit` caps the distinct values returned (clamped).
254
+ */
244
255
  interface FacetGlobalColumnOptions {
245
256
  column: string;
246
257
  filters?: GlobalFilterClause[];
@@ -253,43 +264,43 @@ interface GlobalFacetValue {
253
264
  value: unknown;
254
265
  }
255
266
  /**
256
- * Payload of a {@link facetGlobalColumn} call: the top-N distinct `values` (each
257
- * with a `count`) ordered by frequency, plus `truncated` — `true` when more
258
- * distinct values existed beyond the cap, so the UI can say so rather than imply
259
- * the list is exhaustive. Mirrors the shard browser's `FacetColumnResult`.
260
- */
267
+ * Payload of a {@link facetGlobalColumn} call: the top-N distinct `values` (each
268
+ * with a `count`) ordered by frequency, plus `truncated` — `true` when more
269
+ * distinct values existed beyond the cap, so the UI can say so rather than imply
270
+ * the list is exhaustive. Mirrors the shard browser's `FacetColumnResult`.
271
+ */
261
272
  interface GlobalFacetResult {
262
273
  truncated: boolean;
263
274
  values: GlobalFacetValue[];
264
275
  }
265
276
  /**
266
- * List every browsable D1 table with its row count, ordered by name. Surfaces
267
- * both the schema's `.global()` tables (provisioned first) and external tables
268
- * (auth, etc.); internal/companion tables are excluded.
269
- */
277
+ * List every browsable D1 table with its row count, ordered by name. Surfaces
278
+ * both the schema's `.global()` tables (provisioned first) and external tables
279
+ * (auth, etc.); internal/companion tables are excluded.
280
+ */
270
281
  declare const listGlobalTables: (exec: SqlCtxExec, schema: SchemaLike) => Promise<GlobalTableInfo[]>;
271
282
  /**
272
- * Read a page of rows from one D1 table. The table is validated against the live
273
- * browsable-table list before its name is interpolated, so this can't be coerced
274
- * into reading an internal table or injecting SQL. `limit` is clamped to
275
- * `[1, 500]`; `offset` floors at `0`. `filters` AND-narrows the page to rows
276
- * matching each `column = value` eq constraint (a facet-value drill-down), bound
277
- * through {@link buildEqPredicate} so they never inject SQL.
278
- */
283
+ * Read a page of rows from one D1 table. The table is validated against the live
284
+ * browsable-table list before its name is interpolated, so this can't be coerced
285
+ * into reading an internal table or injecting SQL. `limit` is clamped to
286
+ * `[1, 500]`; `offset` floors at `0`. `filters` AND-narrows the page to rows
287
+ * matching each `column = value` eq constraint (a facet-value drill-down), bound
288
+ * through {@link buildEqPredicate} so they never inject SQL.
289
+ */
279
290
  declare const readGlobalTablePage: (exec: SqlCtxExec, schema: SchemaLike, options: ReadGlobalTablePageOptions) => Promise<GlobalTablePage>;
280
291
  /**
281
- * Summarise the distinct values of one displayed column over the **active view**
282
- * (the same eq `filters` the global browser is previewing) — the D1 twin of the
283
- * shard browser's `facetColumn`. Read-only: a `SELECT col AS value, COUNT(*) AS
284
- * count … GROUP BY col ORDER BY count DESC LIMIT N+1`, with the column validated
285
- * against the table's displayed columns (typed 404 if unknown), mapped to its
286
- * physical column, and quoted — never interpolated from caller input. The extra
287
- * over-fetched row is dropped and surfaced as `truncated`. A sensitive column on
288
- * an external (non-schema) table is never grouped — it collapses to a single
289
- * redacted `•••` bucket — mirroring the page browser's value redaction so the
290
- * facet can't leak credentials. The returned `value` is the raw stored scalar, so
291
- * a click feeds it straight back as an eq filter.
292
- */
292
+ * Summarise the distinct values of one displayed column over the **active view**
293
+ * (the same eq `filters` the global browser is previewing) — the D1 twin of the
294
+ * shard browser's `facetColumn`. Read-only: a `SELECT col AS value, COUNT(*) AS
295
+ * count … GROUP BY col ORDER BY count DESC LIMIT N+1`, with the column validated
296
+ * against the table's displayed columns (typed 404 if unknown), mapped to its
297
+ * physical column, and quoted — never interpolated from caller input. The extra
298
+ * over-fetched row is dropped and surfaced as `truncated`. A sensitive column on
299
+ * an external (non-schema) table is never grouped — it collapses to a single
300
+ * redacted `•••` bucket — mirroring the page browser's value redaction so the
301
+ * facet can't leak credentials. The returned `value` is the raw stored scalar, so
302
+ * a click feeds it straight back as an eq filter.
303
+ */
293
304
  declare const facetGlobalColumn: (exec: SqlCtxExec, schema: SchemaLike, options: FacetGlobalColumnOptions) => Promise<GlobalFacetResult>;
294
305
  interface Migration {
295
306
  /** Human-readable name, e.g. `001_init` (used in logs). */
@@ -310,20 +321,20 @@ interface MigrationRunnerResult {
310
321
  }[];
311
322
  }
312
323
  /**
313
- * Sequentially applies pending migrations against a D1 database via the
314
- * drizzle-orm/d1 driver. Each migration is hashed (SHA-256 over its SQL
315
- * text); the hash is stored in `__drizzle_migrations`, so re-applying the
316
- * same SQL under a different `version` is rejected and identical migrations
317
- * are skipped idempotently.
318
- */
324
+ * Sequentially applies pending migrations against a D1 database via the
325
+ * drizzle-orm/d1 driver. Each migration is hashed (SHA-256 over its SQL
326
+ * text); the hash is stored in `__drizzle_migrations`, so re-applying the
327
+ * same SQL under a different `version` is rejected and identical migrations
328
+ * are skipped idempotently.
329
+ */
319
330
  declare class MigrationRunner {
320
331
  private readonly client;
321
332
  private readonly migrations;
322
333
  /**
323
- * Accepts either a {@link D1Client} (preferred — gets typed batches +
324
- * drizzle handle for free) or a raw `D1DatabaseLike` binding (wrapped on
325
- * the caller's behalf so existing `@lunora/cli` callers keep working).
326
- */
334
+ * Accepts either a {@link D1Client} (preferred — gets typed batches +
335
+ * drizzle handle for free) or a raw `D1DatabaseLike` binding (wrapped on
336
+ * the caller's behalf so existing `@lunora/cli` callers keep working).
337
+ */
327
338
  constructor(database: D1Client | D1DatabaseLike, migrations: Migration[]);
328
339
  run(): Promise<MigrationRunnerResult>;
329
340
  private applyOne;
@@ -331,9 +342,9 @@ declare class MigrationRunner {
331
342
  private assertUniqueSql;
332
343
  }
333
344
  /**
334
- * The canonical SQLite dialect: column affinities, the shared SQLite value
335
- * codec, `RETURNING` support (both D1 and `node:sqlite`), and `sqlite_master`
336
- * table probing. The rest of the per-statement shaping is drizzle's.
337
- */
345
+ * The canonical SQLite dialect: column affinities, the shared SQLite value
346
+ * codec, `RETURNING` support (both D1 and `node:sqlite`), and `sqlite_master`
347
+ * table probing. The rest of the per-statement shaping is drizzle's.
348
+ */
338
349
  declare const sqliteDialect: SqlDialect;
339
- export { D1Client, type D1ContextDatabaseOptions as D1CtxDbOptions, type D1DatabaseLike, type D1PreparedStatementLike, D1Session, type D1SessionLike, type ExportGlobalArgs, type FacetGlobalColumnOptions, type ExportRow as GlobalExportRow, type GlobalFacetResult, type GlobalFacetValue, type GlobalFilterClause, type ImportError as GlobalImportError, type ImportResult as GlobalImportResult, type GlobalTableInfo, type GlobalTablePage, type ImportGlobalArgs, type Migration, MigrationRunner, type MigrationRunnerResult, type ReadGlobalTablePageOptions, createD1ContextDatabase as createD1CtxDb, exportGlobalRows, facetGlobalColumn, importGlobalRows, listGlobalTables, readD1CdcChanges, readGlobalTablePage, runD1AggregateMigrations, runD1CdcMigration, runD1GlobalTableMigrations, runD1RankMigrations, runD1SearchMigrations, selectGlobalTables, sqliteDialect, trimD1CdcChanges };
350
+ export { D1Client, type D1ContextDatabaseOptions as D1CtxDbOptions, type D1DatabaseLike, type D1PreparedStatementLike, D1Session, type D1SessionLike, type ExportGlobalArgs, type FacetGlobalColumnOptions, type ExportRow as GlobalExportRow, type GlobalFacetResult, type GlobalFacetValue, type GlobalFilterClause, type ImportError as GlobalImportError, type ImportResult as GlobalImportResult, type GlobalTableInfo, type GlobalTablePage, type ImportGlobalArgs, type Migration, MigrationRunner, type MigrationRunnerResult, type ReadGlobalTablePageOptions, backfillD1SearchIndexes, createD1ContextDatabase as createD1CtxDb, exportGlobalRows, facetGlobalColumn, importGlobalRows, listGlobalTables, readD1CdcChanges, readGlobalTablePage, runD1AggregateMigrations, runD1CdcMigration, runD1GlobalTableMigrations, runD1RankMigrations, runD1SearchMigrations, selectGlobalTables, sqliteDialect, trimD1CdcChanges };