@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.
- package/dist/analytics/index.d.mts +70 -70
- package/dist/analytics/index.d.ts +70 -70
- package/dist/images/index.d.mts +147 -147
- package/dist/images/index.d.ts +147 -147
- package/dist/kv/index.d.mts +89 -89
- package/dist/kv/index.d.ts +89 -89
- package/dist/pipelines/index.d.mts +24 -24
- package/dist/pipelines/index.d.ts +24 -24
- package/dist/r2sql/index.d.mts +120 -120
- package/dist/r2sql/index.d.ts +120 -120
- package/dist/vectors/index.d.mts +83 -83
- package/dist/vectors/index.d.ts +83 -83
- package/package.json +2 -2
package/dist/r2sql/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
93
|
-
|
|
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<MyRow>(…)` /
|
|
113
|
-
* `query<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<MyRow>(…)` /
|
|
113
|
+
* `query<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
|
-
|
|
128
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
236
|
-
|
|
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
|
-
|
|
323
|
-
|
|
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;
|
package/dist/vectors/index.d.mts
CHANGED
|
@@ -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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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 };
|