@lunora/bindings 1.0.0-alpha.7 → 1.0.0-alpha.9

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.
@@ -1,8 +1,8 @@
1
1
  import { LunoraError } from '@lunora/errors';
2
2
  /**
3
- * A composed SQL fragment. Carries the finished `text`; `toString()` returns it
4
- * so a fragment can be dropped straight into a template or `String(...)`.
5
- */
3
+ * A composed SQL fragment. Carries the finished `text`; `toString()` returns it
4
+ * so a fragment can be dropped straight into a template or `String(...)`.
5
+ */
6
6
  declare class Sql {
7
7
  readonly text: string;
8
8
  constructor(text: string);
@@ -11,32 +11,32 @@ declare class Sql {
11
11
  /** True when `value` is a {@link Sql} fragment (an already-trusted, pre-escaped span). */
12
12
  declare const isSql: (value: unknown) => value is Sql;
13
13
  /**
14
- * Wrap an already-trusted string as a {@link Sql} fragment so {@link sql}
15
- * splices it **verbatim** (no escaping). Use ONLY for SQL you constructed
16
- * yourself (identifiers, keywords, sub-fragments) — never for user input.
17
- */
14
+ * Wrap an already-trusted string as a {@link Sql} fragment so {@link sql}
15
+ * splices it **verbatim** (no escaping). Use ONLY for SQL you constructed
16
+ * yourself (identifiers, keywords, sub-fragments) — never for user input.
17
+ */
18
18
  declare const raw: (text: string) => Sql;
19
19
  /** Resolve a `string | Sql` to its raw text. A bare string is taken as trusted SQL (callers pass identifiers/fragments here). */
20
20
  declare const toText: (value: Sql | string) => string;
21
21
  /**
22
- * Render a JS value as an R2 SQL literal:
23
- *
24
- * - `null` / `undefined` → `NULL`
25
- * - `boolean` → `true` / `false`
26
- * - finite `number` / `bigint` → the numeric text (non-finite throws — `NaN`/`Infinity` have no SQL literal)
27
- * - `Date` → an RFC3339 string literal (R2 SQL's `timestamp` form)
28
- * - `string` → a single-quoted, escaped literal
29
- * - `Array` → a parenthesised, comma-separated list of literals (for `IN (...)`)
30
- *
31
- * Anything else (object, symbol, function) throws — there is no safe SQL literal
32
- * for it, and silently coercing would risk a malformed or injectable statement.
33
- */
22
+ * Render a JS value as an R2 SQL literal:
23
+ *
24
+ * - `null` / `undefined` → `NULL`
25
+ * - `boolean` → `true` / `false`
26
+ * - finite `number` / `bigint` → the numeric text (non-finite throws — `NaN`/`Infinity` have no SQL literal)
27
+ * - `Date` → an RFC3339 string literal (R2 SQL's `timestamp` form)
28
+ * - `string` → a single-quoted, escaped literal
29
+ * - `Array` → a parenthesised, comma-separated list of literals (for `IN (...)`)
30
+ *
31
+ * Anything else (object, symbol, function) throws — there is no safe SQL literal
32
+ * for it, and silently coercing would risk a malformed or injectable statement.
33
+ */
34
34
  declare const lit: (value: unknown) => string;
35
35
  /**
36
- * Tagged template producing a safe {@link Sql} fragment. Each interpolation is
37
- * escaped with {@link lit} unless it is already a {@link Sql} (spliced
38
- * verbatim), so user values can never break out of their literal.
39
- */
36
+ * Tagged template producing a safe {@link Sql} fragment. Each interpolation is
37
+ * escaped with {@link lit} unless it is already a {@link Sql} (spliced
38
+ * verbatim), so user values can never break out of their literal.
39
+ */
40
40
  declare const sql: (strings: TemplateStringsArray, ...values: unknown[]) => Sql;
41
41
  /** Join SQL fragments/strings with `separator` into one {@link Sql} (e.g. `AND`-ed conditions). */
42
42
  declare const joinSql: (parts: ReadonlyArray<Sql | string>, separator: string) => Sql;
@@ -52,29 +52,29 @@ declare const desc: (expr: Sql | string) => OrderTerm;
52
52
  /** Render one {@link OrderTerm} to SQL. */
53
53
  declare const renderOrderTerm: (term: OrderTerm) => string;
54
54
  /**
55
- * Public types for `@lunora/bindings/r2sql`.
56
- *
57
- * R2 SQL is Cloudflare's serverless, distributed query engine over **Apache
58
- * Iceberg** tables in [R2 Data Catalog](https://developers.cloudflare.com/r2/data-catalog/).
59
- * It has **no Workers binding** — every query is an HTTPS round-trip to the REST
60
- * endpoint (`POST …/r2-sql/query/{bucket}`). So, like Hyperdrive's `ctx.sql`, the
61
- * client is **non-deterministic external I/O**: it is wired onto `ActionCtx`
62
- * only (see the `r2sql_outside_action` advisor lint) and its reads are NOT
63
- * tracked by Lunora live queries.
64
- *
65
- * Everything here is deliberately structural (no hard dependency on
66
- * `@cloudflare/workers-types`) so unit tests can inject a plain `fetch` double
67
- * and never touch the network — mirroring `AnalyticsSqlConfig` in
68
- * `@lunora/bindings/analytics`.
69
- */
55
+ * Public types for `@lunora/bindings/r2sql`.
56
+ *
57
+ * R2 SQL is Cloudflare's serverless, distributed query engine over **Apache
58
+ * Iceberg** tables in [R2 Data Catalog](https://developers.cloudflare.com/r2/data-catalog/).
59
+ * It has **no Workers binding** — every query is an HTTPS round-trip to the REST
60
+ * endpoint (`POST …/r2-sql/query/{bucket}`). So, like Hyperdrive's `ctx.sql`, the
61
+ * client is **non-deterministic external I/O**: it is wired onto `ActionCtx`
62
+ * only (see the `r2sql_outside_action` advisor lint) and its reads are NOT
63
+ * tracked by Lunora live queries.
64
+ *
65
+ * Everything here is deliberately structural (no hard dependency on
66
+ * `@cloudflare/workers-types`) so unit tests can inject a plain `fetch` double
67
+ * and never touch the network — mirroring `AnalyticsSqlConfig` in
68
+ * `@lunora/bindings/analytics`.
69
+ */
70
70
  /**
71
- * Configuration for a {@link import("./client").R2SqlClient | R2SqlClient}.
72
- *
73
- * `apiToken` is a **secret** — a Cloudflare API token scoped to R2 SQL (read),
74
- * R2 Data Catalog, and R2 storage. It is never a binding and must never be
75
- * auto-scaffolded with a real value; the caller provides it from
76
- * env/`.dev.vars`.
77
- */
71
+ * Configuration for a {@link import("./client").R2SqlClient | R2SqlClient}.
72
+ *
73
+ * `apiToken` is a **secret** — a Cloudflare API token scoped to R2 SQL (read),
74
+ * R2 Data Catalog, and R2 storage. It is never a binding and must never be
75
+ * auto-scaffolded with a real value; the caller provides it from
76
+ * env/`.dev.vars`.
77
+ */
78
78
  interface R2SqlConfig {
79
79
  /** Cloudflare account id that owns the bucket/catalog. */
80
80
  accountId: string;
@@ -83,36 +83,36 @@ interface R2SqlConfig {
83
83
  /** The R2 bucket (warehouse) whose Data Catalog the queries run against. */
84
84
  bucket: string;
85
85
  /**
86
- * Override the REST base URL. Defaults to Cloudflare's public R2 SQL host
87
- * (`https://api.sql.cloudflarestorage.com/api/v1/accounts`). Injected in
88
- * tests, or pointed at a regional/preview host.
89
- */
86
+ * Override the REST base URL. Defaults to Cloudflare's public R2 SQL host
87
+ * (`https://api.sql.cloudflarestorage.com/api/v1/accounts`). Injected in
88
+ * tests, or pointed at a regional/preview host.
89
+ */
90
90
  endpoint?: string;
91
91
  /**
92
- * `fetch` implementation. Defaults to the global `fetch`; injected in tests
93
- * so a query never touches the network.
94
- */
92
+ * `fetch` implementation. Defaults to the global `fetch`; injected in tests
93
+ * so a query never touches the network.
94
+ */
95
95
  fetch?: typeof globalThis.fetch;
96
96
  }
97
97
  /**
98
- * One column descriptor in a result's schema: the column `name` and, when the
99
- * engine reports it, the Iceberg storage `type` (`integer`, `string`,
100
- * `timestamp`, …). R2 SQL does not always echo a schema block, so `type` is
101
- * optional and `columns` may be derived from the first row's keys.
102
- */
98
+ * One column descriptor in a result's schema: the column `name` and, when the
99
+ * engine reports it, the Iceberg storage `type` (`integer`, `string`,
100
+ * `timestamp`, …). R2 SQL does not always echo a schema block, so `type` is
101
+ * optional and `columns` may be derived from the first row's keys.
102
+ */
103
103
  interface R2SqlColumn {
104
104
  name: string;
105
105
  type?: string;
106
106
  }
107
107
  /**
108
- * A parsed R2 SQL result. R2 SQL returns a Cloudflare envelope
109
- * (`{ success, result, errors }`); we surface the `rows` (the `result` array of
110
- * column→value records), the inferred/echoed `columns`, and the `rowCount`.
111
- *
112
- * `Row` defaults to an open record; supply it (`from&lt;MyRow>(…)` /
113
- * `query&lt;MyRow>(…)`) to get typed result fields — R2 SQL tables live in Iceberg,
114
- * not `defineSchema`, so the row type is caller-declared rather than inferred.
115
- */
108
+ * A parsed R2 SQL result. R2 SQL returns a Cloudflare envelope
109
+ * (`{ success, result, errors }`); we surface the `rows` (the `result` array of
110
+ * column→value records), the inferred/echoed `columns`, and the `rowCount`.
111
+ *
112
+ * `Row` defaults to an open record; supply it (`from&lt;MyRow>(…)` /
113
+ * `query&lt;MyRow>(…)`) to get typed result fields — R2 SQL tables live in Iceberg,
114
+ * not `defineSchema`, so the row type is caller-declared rather than inferred.
115
+ */
116
116
  interface R2SqlResult<Row = Record<string, unknown>> {
117
117
  /** Column descriptors, echoed by the engine or inferred from the first row. */
118
118
  columns: R2SqlColumn[];
@@ -124,25 +124,25 @@ interface R2SqlResult<Row = Record<string, unknown>> {
124
124
  /** Options for {@link import("./client").R2SqlClient.explain | explain}. */
125
125
  interface R2SqlExplainOptions {
126
126
  /**
127
- * `"json"` runs `EXPLAIN FORMAT JSON` (structured plan); `"text"` (default)
128
- * runs a plain `EXPLAIN`.
129
- */
127
+ * `"json"` runs `EXPLAIN FORMAT JSON` (structured plan); `"text"` (default)
128
+ * runs a plain `EXPLAIN`.
129
+ */
130
130
  format?: "json" | "text";
131
131
  }
132
132
  /**
133
- * Executes a finished SQL string against R2 SQL and returns the parsed result.
134
- * Deliberately non-generic (the row type is a caller-side concern) — the typed
135
- * `run()` / `query()` boundaries cast the open result to the declared row.
136
- */
133
+ * Executes a finished SQL string against R2 SQL and returns the parsed result.
134
+ * Deliberately non-generic (the row type is a caller-side concern) — the typed
135
+ * `run()` / `query()` boundaries cast the open result to the declared row.
136
+ */
137
137
  type QueryExecutor = (statement: string) => Promise<R2SqlResult>;
138
138
  /** Anything that compiles to a statement and can run — a {@link import("./builder").SelectBuilder | SelectBuilder} or {@link import("./set-operation").SetOperation | SetOperation}. */
139
139
  interface Queryable<Row = Record<string, unknown>> {
140
140
  /**
141
- * True when this query carries its own `ORDER BY`/`LIMIT`, so a set
142
- * operation must parenthesise it (R2 SQL rejects a bare `LIMIT` before a set
143
- * operator). Read structurally by the set-operation renderer to avoid an
144
- * import cycle.
145
- */
141
+ * True when this query carries its own `ORDER BY`/`LIMIT`, so a set
142
+ * operation must parenthesise it (R2 SQL rejects a bare `LIMIT` before a set
143
+ * operator). Read structurally by the set-operation renderer to avoid an
144
+ * import cycle.
145
+ */
146
146
  readonly needsWrapForSetOperation?: boolean;
147
147
  run: () => Promise<R2SqlResult<Row>>;
148
148
  toSQL: () => string;
@@ -155,16 +155,16 @@ interface SetMember {
155
155
  query: Queryable<unknown>;
156
156
  }
157
157
  /**
158
- * A composition of queries via set operations. Chain more operations, or apply a
159
- * single `ORDER BY` / `LIMIT` to the combined result.
160
- */
158
+ * A composition of queries via set operations. Chain more operations, or apply a
159
+ * single `ORDER BY` / `LIMIT` to the combined result.
160
+ */
161
161
  declare class SetOperation<Row = Record<string, unknown>> implements Queryable<Row> {
162
162
  /**
163
- * Always `true`: a nested set operation must be parenthesised when it is a
164
- * member of another set operation, or mixed operators mis-associate — e.g.
165
- * `a.union(b.except(c))` must render `a UNION (b EXCEPT c)`, not the flat
166
- * `a UNION b EXCEPT c`.
167
- */
163
+ * Always `true`: a nested set operation must be parenthesised when it is a
164
+ * member of another set operation, or mixed operators mis-associate — e.g.
165
+ * `a.union(b.except(c))` must render `a UNION (b EXCEPT c)`, not the flat
166
+ * `a UNION b EXCEPT c`.
167
+ */
168
168
  readonly needsWrapForSetOperation = true;
169
169
  private readonly exec;
170
170
  private readonly members;
@@ -192,9 +192,9 @@ declare class SetOperation<Row = Record<string, unknown>> implements Queryable<R
192
192
  private add;
193
193
  }
194
194
  /**
195
- * A fluent `SELECT` over one Iceberg table (`namespace.table`), generic over the
196
- * caller-declared `Row` result type.
197
- */
195
+ * A fluent `SELECT` over one Iceberg table (`namespace.table`), generic over the
196
+ * caller-declared `Row` result type.
197
+ */
198
198
  declare class SelectBuilder<Row = Record<string, unknown>> implements Queryable<Row> {
199
199
  private readonly exec;
200
200
  private readonly table;
@@ -232,9 +232,9 @@ declare class SelectBuilder<Row = Record<string, unknown>> implements Queryable<
232
232
  /** Add `HAVING` condition(s) over aggregates; multiple are `AND`-ed. */
233
233
  having(...conditions: Condition[]): this;
234
234
  /**
235
- * `QUALIFY` — filter on a window function without a subquery, e.g.
236
- * `.qualify(fn.rowNumber().over({ partitionBy: "region", orderBy: desc("total") }).lte(3))`.
237
- */
235
+ * `QUALIFY` — filter on a window function without a subquery, e.g.
236
+ * `.qualify(fn.rowNumber().over({ partitionBy: "region", orderBy: desc("total") }).lte(3))`.
237
+ */
238
238
  qualify(condition: Condition): this;
239
239
  /** `ORDER BY` term(s) — bare strings (ASC) or {@link import("./order").asc | asc}/{@link import("./order").desc | desc} tags. */
240
240
  orderBy(...terms: OrderTerm[]): this;
@@ -262,18 +262,18 @@ declare class SelectBuilder<Row = Record<string, unknown>> implements Queryable<
262
262
  private setOperation;
263
263
  }
264
264
  /**
265
- * Thrown when R2 SQL responds with a non-2xx status, an `success: false`
266
- * envelope, or an unparseable body; carries the HTTP `status` and the raw body
267
- * for the caller to surface.
268
- */
265
+ * Thrown when R2 SQL responds with a non-2xx status, an `success: false`
266
+ * envelope, or an unparseable body; carries the HTTP `status` and the raw body
267
+ * for the caller to surface.
268
+ */
269
269
  declare class R2SqlError extends LunoraError {
270
270
  constructor(status: number, body: string);
271
271
  }
272
272
  /**
273
- * The typed R2 SQL surface bound to `ctx.r2sql` on **`ActionCtx` only**. This is
274
- * the exact type the generated ctx imports as
275
- * `import("@lunora/bindings/r2sql").R2SqlClient` — keep the name and shape stable.
276
- */
273
+ * The typed R2 SQL surface bound to `ctx.r2sql` on **`ActionCtx` only**. This is
274
+ * the exact type the generated ctx imports as
275
+ * `import("@lunora/bindings/r2sql").R2SqlClient` — keep the name and shape stable.
276
+ */
277
277
  interface R2SqlClient {
278
278
  /** Run `DESCRIBE namespace.table` — column names and Iceberg types. */
279
279
  describe: (table: string) => Promise<R2SqlResult>;
@@ -289,16 +289,16 @@ interface R2SqlClient {
289
289
  showTables: (namespace: string) => Promise<R2SqlResult>;
290
290
  }
291
291
  /**
292
- * Build an {@link R2SqlClient}. Each query POSTs to the bucket's
293
- * `r2-sql/query/{bucket}` endpoint with the bearer token, then normalises the
294
- * envelope into {@link R2SqlResult}.
295
- */
292
+ * Build an {@link R2SqlClient}. Each query POSTs to the bucket's
293
+ * `r2-sql/query/{bucket}` endpoint with the bearer token, then normalises the
294
+ * envelope into {@link R2SqlResult}.
295
+ */
296
296
  declare const createR2Sql: (config: R2SqlConfig) => R2SqlClient;
297
297
  /**
298
- * A windowed expression. Extends {@link Sql}, so it is usable anywhere a raw
299
- * fragment is; `.as(alias)` makes a `SELECT` item, and the comparison helpers
300
- * (`.lte`, `.gt`, `.between`, …) make `QUALIFY` conditions.
301
- */
298
+ * A windowed expression. Extends {@link Sql}, so it is usable anywhere a raw
299
+ * fragment is; `.as(alias)` makes a `SELECT` item, and the comparison helpers
300
+ * (`.lte`, `.gt`, `.between`, …) make `QUALIFY` conditions.
301
+ */
302
302
  declare class WindowExpression extends Sql {
303
303
  /** Alias the expression — `... AS alias` — for use in a `SELECT` list. */
304
304
  as(alias: string): Sql;
@@ -319,9 +319,9 @@ declare class WindowExpression extends Sql {
319
319
  /** The `OVER (...)` window specification. */
320
320
  interface OverSpec {
321
321
  /**
322
- * A raw frame clause, e.g. `"ROWS BETWEEN 2 PRECEDING AND CURRENT ROW"`.
323
- * Spliced verbatim — it is keyword-only SQL, not a value.
324
- */
322
+ * A raw frame clause, e.g. `"ROWS BETWEEN 2 PRECEDING AND CURRENT ROW"`.
323
+ * Spliced verbatim — it is keyword-only SQL, not a value.
324
+ */
325
325
  frame?: string;
326
326
  /** `ORDER BY` term(s) within the window. */
327
327
  orderBy?: OrderTerm | OrderTerm[];
@@ -329,9 +329,9 @@ interface OverSpec {
329
329
  partitionBy?: Sql | string | (Sql | string)[];
330
330
  }
331
331
  /**
332
- * A window function awaiting its `OVER (...)`. Call {@link WindowFunction.over |
333
- * .over} to bind a window and get a {@link WindowExpression}.
334
- */
332
+ * A window function awaiting its `OVER (...)`. Call {@link WindowFunction.over |
333
+ * .over} to bind a window and get a {@link WindowExpression}.
334
+ */
335
335
  declare class WindowFunction {
336
336
  private readonly callText;
337
337
  constructor(callText: string);
@@ -339,13 +339,13 @@ declare class WindowFunction {
339
339
  over(spec?: OverSpec): WindowExpression;
340
340
  }
341
341
  /**
342
- * Window-function builders. Each returns a {@link WindowFunction}; chain
343
- * `.over(...)` to bind the window.
344
- *
345
- * Ranking: `rowNumber`, `rank`, `denseRank`, `percentRank`, `cumeDist`,
346
- * `ntile`. Offset/value: `lag`, `lead`, `firstValue`, `lastValue`, `nthValue`.
347
- * Aggregates used as windows: `sum`, `avg`, `count`, `min`, `max`.
348
- */
342
+ * Window-function builders. Each returns a {@link WindowFunction}; chain
343
+ * `.over(...)` to bind the window.
344
+ *
345
+ * Ranking: `rowNumber`, `rank`, `denseRank`, `percentRank`, `cumeDist`,
346
+ * `ntile`. Offset/value: `lag`, `lead`, `firstValue`, `lastValue`, `nthValue`.
347
+ * Aggregates used as windows: `sum`, `avg`, `count`, `min`, `max`.
348
+ */
349
349
  declare const fn: {
350
350
  /** `AVG(column) OVER (...)`. */
351
351
  avg: (column: Sql | string) => WindowFunction;
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Minimal structural projection of `VectorizeIndex` so unit tests can pass a
3
- * plain-object double and the real Cloudflare binding satisfies the same shape.
4
- * Mirrors the surface documented at
5
- * https://developers.cloudflare.com/vectorize/reference/client-api/.
6
- */
2
+ * Minimal structural projection of `VectorizeIndex` so unit tests can pass a
3
+ * plain-object double and the real Cloudflare binding satisfies the same shape.
4
+ * Mirrors the surface documented at
5
+ * https://developers.cloudflare.com/vectorize/reference/client-api/.
6
+ */
7
7
  interface VectorizeIndexLike {
8
8
  deleteByIds: (ids: ReadonlyArray<string>) => Promise<VectorizeDeleteMutation>;
9
9
  describe?: () => Promise<VectorizeIndexDetails>;
@@ -51,17 +51,17 @@ interface VectorizeIndexDetails {
51
51
  vectorsCount: number;
52
52
  }
53
53
  /**
54
- * Bring-your-own-embedder: a user-supplied async fn that converts a single
55
- * source value (a row, a chunk, an arbitrary string) into a numeric vector.
56
- * The runtime calls this at upsert time so we don't couple to any provider.
57
- */
54
+ * Bring-your-own-embedder: a user-supplied async fn that converts a single
55
+ * source value (a row, a chunk, an arbitrary string) into a numeric vector.
56
+ * The runtime calls this at upsert time so we don't couple to any provider.
57
+ */
58
58
  type EmbedFunction<TInput = unknown> = (input: TInput) => Promise<ReadonlyArray<number>> | ReadonlyArray<number>;
59
59
  interface LunoraVectorsOptions {
60
60
  /**
61
- * Map of logical index name -> Vectorize binding. Most apps wire one
62
- * binding per index; multi-index apps register all of them here so calls
63
- * like `vectors.query("docs-body", ...)` can resolve to the right binding.
64
- */
61
+ * Map of logical index name -> Vectorize binding. Most apps wire one
62
+ * binding per index; multi-index apps register all of them here so calls
63
+ * like `vectors.query("docs-body", ...)` can resolve to the right binding.
64
+ */
65
65
  indexes: Record<string, VectorizeIndexLike>;
66
66
  }
67
67
  interface UpsertInput<TInput = unknown> {
@@ -91,9 +91,9 @@ interface LunoraVectors {
91
91
  upsertMany: <TInput>(indexName: string, inputs: ReadonlyArray<UpsertInput<TInput>>) => Promise<VectorizeUpsertMutation>;
92
92
  }
93
93
  /**
94
- * `(input: string) => vector`. Matches `@lunora/server`'s `VectorEmbedder` so
95
- * the bridged surface is assignable to the server's `VectorSearch` contract.
96
- */
94
+ * `(input: string) => vector`. Matches `@lunora/server`'s `VectorEmbedder` so
95
+ * the bridged surface is assignable to the server's `VectorSearch` contract.
96
+ */
97
97
  type VectorEmbedderLike = (input: string) => Promise<ReadonlyArray<number>> | ReadonlyArray<number>;
98
98
  interface VectorMatchLike {
99
99
  id: string;
@@ -115,11 +115,11 @@ interface VectorQueryInputLike {
115
115
  input?: string;
116
116
  namespace?: string;
117
117
  /**
118
- * How much stored metadata to return on matches. Defaults to `"indexed"`
119
- * (only fields declared as index metadata) rather than `"all"`, so a query
120
- * never leaks arbitrary stored fields by default. Callers that genuinely
121
- * need every field opt in with `"all"`; pass `"none"` to drop metadata.
122
- */
118
+ * How much stored metadata to return on matches. Defaults to `"indexed"`
119
+ * (only fields declared as index metadata) rather than `"all"`, so a query
120
+ * never leaks arbitrary stored fields by default. Callers that genuinely
121
+ * need every field opt in with `"all"`; pass `"none"` to drop metadata.
122
+ */
123
123
  returnMetadata?: "none" | "indexed" | "all";
124
124
  topK?: number;
125
125
  vector?: ReadonlyArray<number>;
@@ -132,10 +132,10 @@ interface VectorUpsertInputLike {
132
132
  namespace?: string;
133
133
  }
134
134
  /**
135
- * Structural mirror of `@lunora/server`'s `VectorSearch`. Declared here so the
136
- * adapter never imports `@lunora/server` (keeps the dependency edge one-way:
137
- * the generated DO depends on both, neither depends on the other).
138
- */
135
+ * Structural mirror of `@lunora/server`'s `VectorSearch`. Declared here so the
136
+ * adapter never imports `@lunora/server` (keeps the dependency edge one-way:
137
+ * the generated DO depends on both, neither depends on the other).
138
+ */
139
139
  interface VectorSearchLike {
140
140
  deleteByIds: (indexName: string, ids: ReadonlyArray<string>) => Promise<void>;
141
141
  getByIds: (indexName: string, ids: ReadonlyArray<string>) => Promise<ReadonlyArray<VectorRecordLike>>;
@@ -144,11 +144,11 @@ interface VectorSearchLike {
144
144
  upsertNow: (indexName: string, input: VectorUpsertInputLike) => Promise<void>;
145
145
  }
146
146
  /**
147
- * Bridge `LunoraVectors` (returns Vectorize mutation receipts) to the server's
148
- * `VectorSearch` contract (void mutations, server match/record shapes). Both
149
- * `upsert` and `upsertNow` write inline — this design has no post-commit queue,
150
- * so "now" and "deferred" collapse to the same synchronous call.
151
- */
147
+ * Bridge `LunoraVectors` (returns Vectorize mutation receipts) to the server's
148
+ * `VectorSearch` contract (void mutations, server match/record shapes). Both
149
+ * `upsert` and `upsertNow` write inline — this design has no post-commit queue,
150
+ * so "now" and "deferred" collapse to the same synchronous call.
151
+ */
152
152
  declare const createContextVectors: (lunora: LunoraVectors) => VectorSearchLike;
153
153
  /** A single row mutation observed by the ctx-db, fed to {@link createVectorSyncHook}. */
154
154
  interface WriteEvent {
@@ -176,43 +176,43 @@ interface VectorIndexDefinitionLike {
176
176
  table: string;
177
177
  }
178
178
  /**
179
- * Structural mirror of `@lunora/server`'s `Schema`, narrowed to the fields the
180
- * sync hook reads. Carries live `embed`/`select` closures, so the hook must be
181
- * built from the imported `schema` value — never a serialized descriptor.
182
- */
179
+ * Structural mirror of `@lunora/server`'s `Schema`, narrowed to the fields the
180
+ * sync hook reads. Carries live `embed`/`select` closures, so the hook must be
181
+ * built from the imported `schema` value — never a serialized descriptor.
182
+ */
183
183
  interface SchemaLike {
184
184
  tables: Record<string, TableDefinitionLike>;
185
185
  vectorIndexes: Record<string, VectorIndexDefinitionLike>;
186
186
  }
187
187
  /**
188
- * Build a {@link WriteHook} that keeps Vectorize in sync with row writes. On
189
- * insert/update it embeds each matching index's source (Shape A `row[field]`,
190
- * Shape B `select(row)`) and upserts; on delete it removes the row's id from
191
- * every index sourced from the table. Runs inline within the write path.
192
- *
193
- * Tenant isolation — IMPORTANT: Vectorize indexes are account-global and shared
194
- * by every shard DO. Without a `namespace`, a multi-tenant sharded app has NO
195
- * isolation between tenants in the vector index — one tenant's vectors are
196
- * queryable by another (ids/scores leak existence + semantic similarity even
197
- * when no metadata is indexed). The caller MUST pass `options.namespace` (the
198
- * shard / tenant key) so upserts are scoped, and MUST apply the same namespace
199
- * on the query side — query-side namespace filtering is mandatory, not optional.
200
- * The namespace is threaded onto upserts here; pass it from the shard DO that
201
- * owns this hook. Any namespace-less sync emits a one-time-per-index dev warning
202
- * (regardless of whether metadata is present); a genuinely single-tenant app
203
- * suppresses it with `allowSharedNamespace: true`.
204
- *
205
- * Consistency — IMPORTANT: this hook runs inline within the mutation but talks
206
- * to Vectorize, which is external and non-transactional. The per-index calls
207
- * fan out; if one fails after others have already applied, the SQLite write may
208
- * roll back while the applied Vectorize mutations cannot — leaving SQLite and
209
- * Vectorize diverged. We mitigate, not eliminate: upserts/deletes are
210
- * idempotent (keyed by row id), so a retry of the same write converges; and on
211
- * a fan-out failure we attempt a best-effort compensating delete of the row's
212
- * id from every affected index before re-throwing. A delete after a failed
213
- * upsert can itself fail — this is best-effort, the authoritative recovery is
214
- * re-running the (idempotent) write.
215
- */
188
+ * Build a {@link WriteHook} that keeps Vectorize in sync with row writes. On
189
+ * insert/update it embeds each matching index's source (Shape A `row[field]`,
190
+ * Shape B `select(row)`) and upserts; on delete it removes the row's id from
191
+ * every index sourced from the table. Runs inline within the write path.
192
+ *
193
+ * Tenant isolation — IMPORTANT: Vectorize indexes are account-global and shared
194
+ * by every shard DO. Without a `namespace`, a multi-tenant sharded app has NO
195
+ * isolation between tenants in the vector index — one tenant's vectors are
196
+ * queryable by another (ids/scores leak existence + semantic similarity even
197
+ * when no metadata is indexed). The caller MUST pass `options.namespace` (the
198
+ * shard / tenant key) so upserts are scoped, and MUST apply the same namespace
199
+ * on the query side — query-side namespace filtering is mandatory, not optional.
200
+ * The namespace is threaded onto upserts here; pass it from the shard DO that
201
+ * owns this hook. Any namespace-less sync emits a one-time-per-index dev warning
202
+ * (regardless of whether metadata is present); a genuinely single-tenant app
203
+ * suppresses it with `allowSharedNamespace: true`.
204
+ *
205
+ * Consistency — IMPORTANT: this hook runs inline within the mutation but talks
206
+ * to Vectorize, which is external and non-transactional. The per-index calls
207
+ * fan out; if one fails after others have already applied, the SQLite write may
208
+ * roll back while the applied Vectorize mutations cannot — leaving SQLite and
209
+ * Vectorize diverged. We mitigate, not eliminate: upserts/deletes are
210
+ * idempotent (keyed by row id), so a retry of the same write converges; and on
211
+ * a fan-out failure we attempt a best-effort compensating delete of the row's
212
+ * id from every affected index before re-throwing. A delete after a failed
213
+ * upsert can itself fail — this is best-effort, the authoritative recovery is
214
+ * re-running the (idempotent) write.
215
+ */
216
216
  declare const createVectorSyncHook: (options: {
217
217
  allowSharedNamespace?: boolean;
218
218
  namespace?: string;
@@ -220,11 +220,11 @@ declare const createVectorSyncHook: (options: {
220
220
  vectors: VectorSearchLike;
221
221
  }) => WriteHook;
222
222
  /**
223
- * One vector index as the generated `LUNORA_VECTOR_INDEXES` registry describes
224
- * it — the static schema shape, independent of any live binding. Structurally
225
- * the codegen `LunoraVectorIndex`, restated here so this package stays free of a
226
- * dependency on `@lunora/codegen`.
227
- */
223
+ * One vector index as the generated `LUNORA_VECTOR_INDEXES` registry describes
224
+ * it — the static schema shape, independent of any live binding. Structurally
225
+ * the codegen `LunoraVectorIndex`, restated here so this package stays free of a
226
+ * dependency on `@lunora/codegen`.
227
+ */
228
228
  interface VectorIndexRegistryEntry {
229
229
  dimensions?: number;
230
230
  field?: string;
@@ -245,9 +245,9 @@ interface VectorAdminQueryMatch {
245
245
  score: number;
246
246
  }
247
247
  /**
248
- * The admin introspector the worker passes to `createWorker({ vectorIntrospector })`.
249
- * `queryIndex` is present only when at least one embedder is wired.
250
- */
248
+ * The admin introspector the worker passes to `createWorker({ vectorIntrospector })`.
249
+ * `queryIndex` is present only when at least one embedder is wired.
250
+ */
251
251
  interface VectorAdminIntrospector {
252
252
  listIndexes: () => Promise<VectorAdminIndexSummary[]>;
253
253
  queryIndex?: (options: {
@@ -260,11 +260,11 @@ interface VectorAdminIntrospector {
260
260
  }
261
261
  interface VectorAdminIntrospectorOptions {
262
262
  /**
263
- * Per-index embedder (text → vector), keyed by index name. Supply the
264
- * schema's embedders to enable studio similarity queries; omit it (or leave
265
- * an index out) and that index lists read-only — `queryIndex` is withheld
266
- * entirely when no embedder is provided.
267
- */
263
+ * Per-index embedder (text → vector), keyed by index name. Supply the
264
+ * schema's embedders to enable studio similarity queries; omit it (or leave
265
+ * an index out) and that index lists read-only — `queryIndex` is withheld
266
+ * entirely when no embedder is provided.
267
+ */
268
268
  embedders?: Record<string, EmbedFunction<string>>;
269
269
  /** Live Vectorize bindings keyed by index name, from `env`. */
270
270
  indexes: Record<string, VectorizeIndexLike>;
@@ -272,14 +272,14 @@ interface VectorAdminIntrospectorOptions {
272
272
  registry: ReadonlyArray<VectorIndexRegistryEntry>;
273
273
  }
274
274
  /**
275
- * Build the read-only Vectorize introspector backing the studio's vector
276
- * browser. `listIndexes` returns the static registry, enriching each entry with
277
- * live `describe()` stats when the matching binding is present (a binding that
278
- * throws or lacks `describe` degrades to the static shape rather than failing
279
- * the whole list). `queryIndex` embeds the query text via the index's embedder
280
- * and runs an ANN search; it is omitted when no embedders are configured, so the
281
- * worker reports `VECTOR_QUERY_UNSUPPORTED` rather than half-answering.
282
- */
275
+ * Build the read-only Vectorize introspector backing the studio's vector
276
+ * browser. `listIndexes` returns the static registry, enriching each entry with
277
+ * live `describe()` stats when the matching binding is present (a binding that
278
+ * throws or lacks `describe` degrades to the static shape rather than failing
279
+ * the whole list). `queryIndex` embeds the query text via the index's embedder
280
+ * and runs an ANN search; it is omitted when no embedders are configured, so the
281
+ * worker reports `VECTOR_QUERY_UNSUPPORTED` rather than half-answering.
282
+ */
283
283
  declare const createVectorAdminIntrospector: (options: VectorAdminIntrospectorOptions) => VectorAdminIntrospector;
284
284
  declare const createVectors: (options: LunoraVectorsOptions) => LunoraVectors;
285
285
  export { type EmbedFunction, type LunoraVectors, type LunoraVectorsOptions, type QueryInput, type SchemaLike, type TableDefinitionLike, type TableVectorIndexLike, type UpsertInput, type VectorAdminIndexSummary, type VectorAdminIntrospector, type VectorAdminIntrospectorOptions, type VectorAdminQueryMatch, type VectorEmbedderLike, type VectorIndexDefinitionLike, type VectorIndexRegistryEntry, type VectorMatchLike, type VectorMatchesLike, type VectorMetric, type VectorQueryInputLike, type VectorRecordLike, type VectorSearchLike, type VectorUpsertInputLike, type VectorizeDeleteMutation, type VectorizeIndexDetails, type VectorizeIndexLike, type VectorizeMatch, type VectorizeMatches, type VectorizeQueryOptions, type VectorizeUpsertMutation, type VectorizeVector, type WriteEvent, type WriteHook, createContextVectors, createVectorAdminIntrospector, createVectorSyncHook, createVectors };