@lunora/bindings 1.0.0-alpha.1 → 1.0.0-alpha.11
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 +6 -0
- package/dist/analytics/index.d.mts +73 -73
- package/dist/analytics/index.d.ts +73 -73
- package/dist/analytics/index.mjs +1 -1
- package/dist/images/index.d.mts +147 -147
- package/dist/images/index.d.ts +147 -147
- package/dist/images/index.mjs +3 -3
- package/dist/kv/index.d.mts +146 -52
- package/dist/kv/index.d.ts +146 -52
- package/dist/kv/index.mjs +2 -1
- package/dist/packem_shared/{AnalyticsSqlError-CGTdsi4H.mjs → AnalyticsSqlError-C2nz3jpH.mjs} +4 -5
- package/dist/packem_shared/{R2SqlError-DkQZ4Omg.mjs → R2SqlError-drPKSCZ3.mjs} +9 -9
- package/dist/packem_shared/{SelectBuilder-BGXfCF0J.mjs → SelectBuilder-BOqJQHEv.mjs} +6 -5
- package/dist/packem_shared/{SetOperation-CGRu681M.mjs → SetOperation-DmPgUL8W.mjs} +3 -2
- package/dist/packem_shared/{Sql-CkDyJ_Sc.mjs → Sql-B3zq2YGx.mjs} +21 -1
- package/dist/packem_shared/{WindowExpression-C2vj7oNX.mjs → WindowExpression-BT_uA6g1.mjs} +1 -1
- package/dist/packem_shared/{WindowFunction-CuKHfZX3.mjs → WindowFunction-DrnuZUF6.mjs} +3 -3
- package/dist/packem_shared/{asc-C6Jbaa6R.mjs → asc-DZbQCxh1.mjs} +1 -1
- package/dist/packem_shared/{buildImageDeliveryUrl-D1sVfIOP.mjs → buildImageDeliveryUrl-qZ7XbqTL.mjs} +9 -4
- package/dist/packem_shared/{buildSignedImageUrl-Otdgc_jO.mjs → buildSignedImageUrl-DNUFfyGP.mjs} +47 -30
- package/dist/packem_shared/{concurrent-Dj5sOibv.mjs → concurrent-CkCEVwqP.mjs} +17 -1
- package/dist/packem_shared/{createContextVectors-BSizpmu5.mjs → createContextVectors-DwZtnPeC.mjs} +1 -1
- package/dist/packem_shared/{createImages-CJrvqX0u.mjs → createImages-BzRnsz3H.mjs} +8 -3
- package/dist/packem_shared/{createKv-DTiSt216.mjs → createKv-C8Iyu5hD.mjs} +18 -14
- package/dist/packem_shared/createKvIntrospector-Byk4GfsY.mjs +77 -0
- package/dist/packem_shared/{createVectorAdminIntrospector-BJUOM6VW.mjs → createVectorAdminIntrospector-DuSvcBa5.mjs} +6 -4
- package/dist/packem_shared/{createVectors-LSpGoKCd.mjs → createVectors-CTSrctiK.mjs} +10 -6
- package/dist/pipelines/index.d.mts +24 -24
- package/dist/pipelines/index.d.ts +24 -24
- package/dist/r2sql/index.d.mts +122 -122
- package/dist/r2sql/index.d.ts +122 -122
- package/dist/r2sql/index.mjs +7 -7
- package/dist/vectors/index.d.mts +83 -83
- package/dist/vectors/index.d.ts +83 -83
- package/dist/vectors/index.mjs +3 -3
- package/package.json +4 -1
package/dist/kv/index.d.mts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The value types Workers KV can store / return. Mirrors Cloudflare's
|
|
3
|
-
* `KVNamespace` `get`/`put` body unions; declared here so the package stays
|
|
4
|
-
* runtime-agnostic and the `*Like` interfaces don't pull in
|
|
5
|
-
* `@cloudflare/workers-types` at runtime.
|
|
6
|
-
*/
|
|
2
|
+
* The value types Workers KV can store / return. Mirrors Cloudflare's
|
|
3
|
+
* `KVNamespace` `get`/`put` body unions; declared here so the package stays
|
|
4
|
+
* runtime-agnostic and the `*Like` interfaces don't pull in
|
|
5
|
+
* `@cloudflare/workers-types` at runtime.
|
|
6
|
+
*/
|
|
7
7
|
type KvValue = ReadableStream | ArrayBuffer | ArrayBufferView | string;
|
|
8
8
|
/** How a raw KV read should decode the stored value. Mirrors KV's `type` option. */
|
|
9
9
|
type KvValueType = "text" | "json" | "arrayBuffer" | "stream";
|
|
10
10
|
/**
|
|
11
|
-
* Per-read options forwarded to the binding. `cacheTtl` is KV's edge-cache TTL
|
|
12
|
-
* (seconds, min 60); `type` selects the decode mode for {@link Kv.getRaw}.
|
|
13
|
-
*/
|
|
11
|
+
* Per-read options forwarded to the binding. `cacheTtl` is KV's edge-cache TTL
|
|
12
|
+
* (seconds, min 60); `type` selects the decode mode for {@link Kv.getRaw}.
|
|
13
|
+
*/
|
|
14
14
|
interface KvGetOptions {
|
|
15
15
|
/** KV edge-cache TTL in seconds (minimum 60). Forwarded verbatim. */
|
|
16
16
|
cacheTtl?: number;
|
|
@@ -18,23 +18,23 @@ interface KvGetOptions {
|
|
|
18
18
|
type?: KvValueType;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Minimal projection of Cloudflare's `KVNamespace`. Declared structurally so
|
|
22
|
-
* unit tests can pass a plain `Map`-backed double; the real binding satisfies
|
|
23
|
-
* the same shape. Mirrors `R2BucketLike` in `@lunora/storage`.
|
|
24
|
-
*/
|
|
21
|
+
* Minimal projection of Cloudflare's `KVNamespace`. Declared structurally so
|
|
22
|
+
* unit tests can pass a plain `Map`-backed double; the real binding satisfies
|
|
23
|
+
* the same shape. Mirrors `R2BucketLike` in `@lunora/storage`.
|
|
24
|
+
*/
|
|
25
25
|
interface KVNamespaceLike {
|
|
26
26
|
/** Delete a key. No-op if the key is absent. */
|
|
27
27
|
delete: (key: string) => Promise<void>;
|
|
28
28
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
* Read a value. The real binding overloads on `options.type`; declared here
|
|
30
|
+
* as the broad union so a structural double need only return the value (or
|
|
31
|
+
* `null` when absent).
|
|
32
|
+
*/
|
|
33
33
|
get: (key: string, options?: KvGetOptions | KvValueType) => Promise<unknown>;
|
|
34
34
|
/**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
* Read a value together with its associated metadata. Returns
|
|
36
|
+
* `{ value: null, metadata: null }` when the key is absent.
|
|
37
|
+
*/
|
|
38
38
|
getWithMetadata: (key: string, options?: KvGetOptions | KvValueType) => Promise<{
|
|
39
39
|
metadata: unknown;
|
|
40
40
|
value: unknown;
|
|
@@ -80,11 +80,11 @@ type KvNamespaceListResult<Metadata = unknown> = {
|
|
|
80
80
|
/** Construction options for the `createKv` factory. */
|
|
81
81
|
interface LunoraKvOptions {
|
|
82
82
|
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
* Optional per-instance key prefix applied to every operation (get/put/
|
|
84
|
+
* delete/list). Use for multi-tenant key namespacing — equivalent to
|
|
85
|
+
* calling the `scopeKey` helper on every key. Combined via `scopeKey`, so a
|
|
86
|
+
* `..` or NUL in the prefix is rejected.
|
|
87
|
+
*/
|
|
88
88
|
keyPrefix?: string;
|
|
89
89
|
/** The bound KV namespace (`env.<BINDING>`). */
|
|
90
90
|
namespace: KVNamespaceLike;
|
|
@@ -98,9 +98,9 @@ interface KvPutOptions {
|
|
|
98
98
|
/** Arbitrary metadata stored alongside the value (returned by `getWithMetadata`/`list`). */
|
|
99
99
|
metadata?: unknown;
|
|
100
100
|
/**
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
* When true, write `value` to KV verbatim (no `JSON.stringify`). `value`
|
|
102
|
+
* must already be a KV-writable type (string/ArrayBuffer/stream).
|
|
103
|
+
*/
|
|
104
104
|
raw?: boolean;
|
|
105
105
|
}
|
|
106
106
|
/** Options for {@link Kv.list}. */
|
|
@@ -117,9 +117,9 @@ interface KvListResult<Metadata = unknown> {
|
|
|
117
117
|
/** Cursor for the next page; `undefined` when the listing is complete. */
|
|
118
118
|
cursor?: string;
|
|
119
119
|
/**
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
* The key names, with any instance `keyPrefix` stripped back off so callers
|
|
121
|
+
* see the same keys they wrote.
|
|
122
|
+
*/
|
|
123
123
|
keys: KvListKey<Metadata>[];
|
|
124
124
|
/** True when this is the final page (no further `cursor`). */
|
|
125
125
|
listComplete: boolean;
|
|
@@ -132,46 +132,140 @@ interface KvValueWithMetadata<Value, Metadata> {
|
|
|
132
132
|
value: Value | null;
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
135
|
-
* The typed Workers KV client bound to `ctx.kv`. JSON-decodes/encodes by
|
|
136
|
-
* default; a raw escape hatch ({@link Kv.getRaw} / `put(..., { raw: true })`)
|
|
137
|
-
* handles text/binary/stream values.
|
|
138
|
-
*/
|
|
135
|
+
* The typed Workers KV client bound to `ctx.kv`. JSON-decodes/encodes by
|
|
136
|
+
* default; a raw escape hatch ({@link Kv.getRaw} / `put(..., { raw: true })`)
|
|
137
|
+
* handles text/binary/stream values.
|
|
138
|
+
*/
|
|
139
139
|
interface Kv {
|
|
140
140
|
/** Delete a key. No-op if absent. */
|
|
141
141
|
delete: (key: string) => Promise<void>;
|
|
142
142
|
/**
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
* Read a key and `JSON.parse` it into `T`. Returns `null` when the key is
|
|
144
|
+
* absent. Throws if the stored value isn't valid JSON — use
|
|
145
|
+
* {@link Kv.getRaw} for non-JSON values.
|
|
146
|
+
*/
|
|
147
147
|
get: <T = unknown>(key: string, options?: {
|
|
148
148
|
cacheTtl?: number;
|
|
149
149
|
}) => Promise<T | null>;
|
|
150
150
|
/** Read a raw value with an explicit decode `type` (default `"text"`). Returns `null` when absent. */
|
|
151
151
|
getRaw: <T = string>(key: string, options?: KvGetOptions) => Promise<T | null>;
|
|
152
152
|
/**
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
* Read a key's JSON value together with its metadata. Returns
|
|
154
|
+
* `{ value: null, metadata: null }` when the key is absent.
|
|
155
|
+
*/
|
|
156
156
|
getWithMetadata: <T = unknown, M = unknown>(key: string, options?: {
|
|
157
157
|
cacheTtl?: number;
|
|
158
158
|
}) => Promise<KvValueWithMetadata<T, M>>;
|
|
159
159
|
/** List keys (optionally `prefix`-filtered, paginated via `cursor`). */
|
|
160
160
|
list: <M = unknown>(options?: KvListOptions) => Promise<KvListResult<M>>;
|
|
161
161
|
/**
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
162
|
+
* Write `value` to `key`. JSON-stringifies `value` unless `options.raw` is
|
|
163
|
+
* set (in which case `value` must be a KV-writable type). Forwards
|
|
164
|
+
* `expirationTtl`/`expiration`/`metadata` to the binding.
|
|
165
|
+
*/
|
|
166
166
|
put: <T = unknown>(key: string, value: T, options?: KvPutOptions) => Promise<void>;
|
|
167
167
|
}
|
|
168
168
|
/**
|
|
169
|
-
* Compose a per-tenant key from a scope prefix and a caller-supplied key. Both
|
|
170
|
-
* halves are validated — the prefix may not contain `..` or NUL either, and the
|
|
171
|
-
* resulting key must stay under KV's length ceiling. Recommended for any
|
|
172
|
-
* multi-tenant deployment so client-supplied keys can't address peer data.
|
|
173
|
-
* Mirrors `scopeKey` from `@lunora/storage`.
|
|
174
|
-
*/
|
|
169
|
+
* Compose a per-tenant key from a scope prefix and a caller-supplied key. Both
|
|
170
|
+
* halves are validated — the prefix may not contain `..` or NUL either, and the
|
|
171
|
+
* resulting key must stay under KV's length ceiling. Recommended for any
|
|
172
|
+
* multi-tenant deployment so client-supplied keys can't address peer data.
|
|
173
|
+
* Mirrors `scopeKey` from `@lunora/storage`.
|
|
174
|
+
*/
|
|
175
175
|
declare const scopeKey: (prefix: string, key: string) => string;
|
|
176
176
|
declare const createKv: (options: LunoraKvOptions) => Kv;
|
|
177
|
-
|
|
177
|
+
/** One KV namespace as the studio's KV browser surfaces it (mirrors the runtime's KvNamespaceSummary). */
|
|
178
|
+
interface KvNamespaceSummaryLike {
|
|
179
|
+
binding: string;
|
|
180
|
+
}
|
|
181
|
+
/** One key entry as surfaced by the KV admin browser (mirrors the runtime's KvKeyEntry). */
|
|
182
|
+
interface KvKeyEntryLike {
|
|
183
|
+
expiration?: number;
|
|
184
|
+
metadata?: unknown;
|
|
185
|
+
name: string;
|
|
186
|
+
}
|
|
187
|
+
/** A paginated page of KV keys (mirrors the runtime's KvKeyListResult). */
|
|
188
|
+
interface KvKeyListResultLike {
|
|
189
|
+
cursor?: string;
|
|
190
|
+
keys: KvKeyEntryLike[];
|
|
191
|
+
listComplete: boolean;
|
|
192
|
+
}
|
|
193
|
+
/** A value together with its metadata (mirrors the runtime's KvValueResult). */
|
|
194
|
+
interface KvValueResultLike {
|
|
195
|
+
metadata: unknown;
|
|
196
|
+
value: null | string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The structural shape of a KV introspector — mirrors `KvIntrospector` from
|
|
200
|
+
* `@lunora/runtime` without importing it, keeping the dependency graph clean.
|
|
201
|
+
*/
|
|
202
|
+
interface KvIntrospectorLike {
|
|
203
|
+
deleteKey: (options: {
|
|
204
|
+
key: string;
|
|
205
|
+
namespace: string;
|
|
206
|
+
}) => Promise<void>;
|
|
207
|
+
getValue: (options: {
|
|
208
|
+
key: string;
|
|
209
|
+
namespace: string;
|
|
210
|
+
}) => Promise<KvValueResultLike>;
|
|
211
|
+
listKeys: (options: {
|
|
212
|
+
cursor?: string;
|
|
213
|
+
limit?: number;
|
|
214
|
+
namespace: string;
|
|
215
|
+
prefix?: string;
|
|
216
|
+
}) => Promise<KvKeyListResultLike>;
|
|
217
|
+
listNamespaces: () => Promise<KvNamespaceSummaryLike[]>;
|
|
218
|
+
putValue: (options: {
|
|
219
|
+
expiration?: number;
|
|
220
|
+
expirationTtl?: number;
|
|
221
|
+
key: string;
|
|
222
|
+
metadata?: unknown;
|
|
223
|
+
namespace: string;
|
|
224
|
+
value: string;
|
|
225
|
+
}) => Promise<void>;
|
|
226
|
+
}
|
|
227
|
+
/** Construction options for {@link createKvIntrospector}. */
|
|
228
|
+
interface CreateKvIntrospectorOptions {
|
|
229
|
+
/**
|
|
230
|
+
* Map of binding name → bound KV namespace. Each entry becomes one
|
|
231
|
+
* namespace the studio can browse. Example:
|
|
232
|
+
* ```ts
|
|
233
|
+
* createKvIntrospector({ namespaces: { MY_KV: env.MY_KV } })
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
namespaces: Record<string, KVNamespaceLike>;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Build a `KvIntrospector`-compatible object from a map of bound KV namespaces.
|
|
240
|
+
* Pass the result as `kvIntrospector` on `WorkerOptions` to enable the studio's
|
|
241
|
+
* KV browser (`/_lunora/admin/kv/*` endpoints).
|
|
242
|
+
* @example
|
|
243
|
+
* ```ts
|
|
244
|
+
* createWorker({
|
|
245
|
+
* // …
|
|
246
|
+
* kvIntrospector: createKvIntrospector({ namespaces: { MY_KV: env.MY_KV } }),
|
|
247
|
+
* });
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
declare const createKvIntrospector: (options: CreateKvIntrospectorOptions) => KvIntrospectorLike;
|
|
251
|
+
/**
|
|
252
|
+
* Zero-config KV introspector: scan a worker `env` for every bound Workers KV
|
|
253
|
+
* namespace and register each under its binding name. Every `kv_namespaces` entry
|
|
254
|
+
* in `wrangler.jsonc` then appears in the studio's KV browser automatically — no
|
|
255
|
+
* hand-written `createKvIntrospector({ namespaces: … })` call, and any binding
|
|
256
|
+
* name (not just `KV`) and any number of namespaces light up. Non-KV bindings
|
|
257
|
+
* (R2, Durable Objects, queues, secrets, …) are skipped via {@link isKvNamespace}.
|
|
258
|
+
*
|
|
259
|
+
* Returns an introspector even when `env` holds no KV namespaces — its
|
|
260
|
+
* `listNamespaces()` resolves to `[]`, so the studio renders an empty state
|
|
261
|
+
* rather than a "not configured" error.
|
|
262
|
+
* @example
|
|
263
|
+
* ```ts
|
|
264
|
+
* createWorker({
|
|
265
|
+
* // …
|
|
266
|
+
* kvIntrospector: createKvIntrospectorFromEnv(env),
|
|
267
|
+
* });
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
declare const createKvIntrospectorFromEnv: (env: unknown) => KvIntrospectorLike;
|
|
271
|
+
export { type CreateKvIntrospectorOptions, type KVNamespaceLike, type Kv, type KvGetOptions, type KvIntrospectorLike, type KvListKey, type KvListOptions, type KvListResult, type KvNamespaceListResult, type KvNamespacePutOptions, type KvPutOptions, type KvValue, type KvValueType, type KvValueWithMetadata, type LunoraKvOptions, createKv, createKvIntrospector, createKvIntrospectorFromEnv, scopeKey };
|
package/dist/kv/index.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The value types Workers KV can store / return. Mirrors Cloudflare's
|
|
3
|
-
* `KVNamespace` `get`/`put` body unions; declared here so the package stays
|
|
4
|
-
* runtime-agnostic and the `*Like` interfaces don't pull in
|
|
5
|
-
* `@cloudflare/workers-types` at runtime.
|
|
6
|
-
*/
|
|
2
|
+
* The value types Workers KV can store / return. Mirrors Cloudflare's
|
|
3
|
+
* `KVNamespace` `get`/`put` body unions; declared here so the package stays
|
|
4
|
+
* runtime-agnostic and the `*Like` interfaces don't pull in
|
|
5
|
+
* `@cloudflare/workers-types` at runtime.
|
|
6
|
+
*/
|
|
7
7
|
type KvValue = ReadableStream | ArrayBuffer | ArrayBufferView | string;
|
|
8
8
|
/** How a raw KV read should decode the stored value. Mirrors KV's `type` option. */
|
|
9
9
|
type KvValueType = "text" | "json" | "arrayBuffer" | "stream";
|
|
10
10
|
/**
|
|
11
|
-
* Per-read options forwarded to the binding. `cacheTtl` is KV's edge-cache TTL
|
|
12
|
-
* (seconds, min 60); `type` selects the decode mode for {@link Kv.getRaw}.
|
|
13
|
-
*/
|
|
11
|
+
* Per-read options forwarded to the binding. `cacheTtl` is KV's edge-cache TTL
|
|
12
|
+
* (seconds, min 60); `type` selects the decode mode for {@link Kv.getRaw}.
|
|
13
|
+
*/
|
|
14
14
|
interface KvGetOptions {
|
|
15
15
|
/** KV edge-cache TTL in seconds (minimum 60). Forwarded verbatim. */
|
|
16
16
|
cacheTtl?: number;
|
|
@@ -18,23 +18,23 @@ interface KvGetOptions {
|
|
|
18
18
|
type?: KvValueType;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Minimal projection of Cloudflare's `KVNamespace`. Declared structurally so
|
|
22
|
-
* unit tests can pass a plain `Map`-backed double; the real binding satisfies
|
|
23
|
-
* the same shape. Mirrors `R2BucketLike` in `@lunora/storage`.
|
|
24
|
-
*/
|
|
21
|
+
* Minimal projection of Cloudflare's `KVNamespace`. Declared structurally so
|
|
22
|
+
* unit tests can pass a plain `Map`-backed double; the real binding satisfies
|
|
23
|
+
* the same shape. Mirrors `R2BucketLike` in `@lunora/storage`.
|
|
24
|
+
*/
|
|
25
25
|
interface KVNamespaceLike {
|
|
26
26
|
/** Delete a key. No-op if the key is absent. */
|
|
27
27
|
delete: (key: string) => Promise<void>;
|
|
28
28
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
* Read a value. The real binding overloads on `options.type`; declared here
|
|
30
|
+
* as the broad union so a structural double need only return the value (or
|
|
31
|
+
* `null` when absent).
|
|
32
|
+
*/
|
|
33
33
|
get: (key: string, options?: KvGetOptions | KvValueType) => Promise<unknown>;
|
|
34
34
|
/**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
* Read a value together with its associated metadata. Returns
|
|
36
|
+
* `{ value: null, metadata: null }` when the key is absent.
|
|
37
|
+
*/
|
|
38
38
|
getWithMetadata: (key: string, options?: KvGetOptions | KvValueType) => Promise<{
|
|
39
39
|
metadata: unknown;
|
|
40
40
|
value: unknown;
|
|
@@ -80,11 +80,11 @@ type KvNamespaceListResult<Metadata = unknown> = {
|
|
|
80
80
|
/** Construction options for the `createKv` factory. */
|
|
81
81
|
interface LunoraKvOptions {
|
|
82
82
|
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
* Optional per-instance key prefix applied to every operation (get/put/
|
|
84
|
+
* delete/list). Use for multi-tenant key namespacing — equivalent to
|
|
85
|
+
* calling the `scopeKey` helper on every key. Combined via `scopeKey`, so a
|
|
86
|
+
* `..` or NUL in the prefix is rejected.
|
|
87
|
+
*/
|
|
88
88
|
keyPrefix?: string;
|
|
89
89
|
/** The bound KV namespace (`env.<BINDING>`). */
|
|
90
90
|
namespace: KVNamespaceLike;
|
|
@@ -98,9 +98,9 @@ interface KvPutOptions {
|
|
|
98
98
|
/** Arbitrary metadata stored alongside the value (returned by `getWithMetadata`/`list`). */
|
|
99
99
|
metadata?: unknown;
|
|
100
100
|
/**
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
* When true, write `value` to KV verbatim (no `JSON.stringify`). `value`
|
|
102
|
+
* must already be a KV-writable type (string/ArrayBuffer/stream).
|
|
103
|
+
*/
|
|
104
104
|
raw?: boolean;
|
|
105
105
|
}
|
|
106
106
|
/** Options for {@link Kv.list}. */
|
|
@@ -117,9 +117,9 @@ interface KvListResult<Metadata = unknown> {
|
|
|
117
117
|
/** Cursor for the next page; `undefined` when the listing is complete. */
|
|
118
118
|
cursor?: string;
|
|
119
119
|
/**
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
* The key names, with any instance `keyPrefix` stripped back off so callers
|
|
121
|
+
* see the same keys they wrote.
|
|
122
|
+
*/
|
|
123
123
|
keys: KvListKey<Metadata>[];
|
|
124
124
|
/** True when this is the final page (no further `cursor`). */
|
|
125
125
|
listComplete: boolean;
|
|
@@ -132,46 +132,140 @@ interface KvValueWithMetadata<Value, Metadata> {
|
|
|
132
132
|
value: Value | null;
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
135
|
-
* The typed Workers KV client bound to `ctx.kv`. JSON-decodes/encodes by
|
|
136
|
-
* default; a raw escape hatch ({@link Kv.getRaw} / `put(..., { raw: true })`)
|
|
137
|
-
* handles text/binary/stream values.
|
|
138
|
-
*/
|
|
135
|
+
* The typed Workers KV client bound to `ctx.kv`. JSON-decodes/encodes by
|
|
136
|
+
* default; a raw escape hatch ({@link Kv.getRaw} / `put(..., { raw: true })`)
|
|
137
|
+
* handles text/binary/stream values.
|
|
138
|
+
*/
|
|
139
139
|
interface Kv {
|
|
140
140
|
/** Delete a key. No-op if absent. */
|
|
141
141
|
delete: (key: string) => Promise<void>;
|
|
142
142
|
/**
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
* Read a key and `JSON.parse` it into `T`. Returns `null` when the key is
|
|
144
|
+
* absent. Throws if the stored value isn't valid JSON — use
|
|
145
|
+
* {@link Kv.getRaw} for non-JSON values.
|
|
146
|
+
*/
|
|
147
147
|
get: <T = unknown>(key: string, options?: {
|
|
148
148
|
cacheTtl?: number;
|
|
149
149
|
}) => Promise<T | null>;
|
|
150
150
|
/** Read a raw value with an explicit decode `type` (default `"text"`). Returns `null` when absent. */
|
|
151
151
|
getRaw: <T = string>(key: string, options?: KvGetOptions) => Promise<T | null>;
|
|
152
152
|
/**
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
* Read a key's JSON value together with its metadata. Returns
|
|
154
|
+
* `{ value: null, metadata: null }` when the key is absent.
|
|
155
|
+
*/
|
|
156
156
|
getWithMetadata: <T = unknown, M = unknown>(key: string, options?: {
|
|
157
157
|
cacheTtl?: number;
|
|
158
158
|
}) => Promise<KvValueWithMetadata<T, M>>;
|
|
159
159
|
/** List keys (optionally `prefix`-filtered, paginated via `cursor`). */
|
|
160
160
|
list: <M = unknown>(options?: KvListOptions) => Promise<KvListResult<M>>;
|
|
161
161
|
/**
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
162
|
+
* Write `value` to `key`. JSON-stringifies `value` unless `options.raw` is
|
|
163
|
+
* set (in which case `value` must be a KV-writable type). Forwards
|
|
164
|
+
* `expirationTtl`/`expiration`/`metadata` to the binding.
|
|
165
|
+
*/
|
|
166
166
|
put: <T = unknown>(key: string, value: T, options?: KvPutOptions) => Promise<void>;
|
|
167
167
|
}
|
|
168
168
|
/**
|
|
169
|
-
* Compose a per-tenant key from a scope prefix and a caller-supplied key. Both
|
|
170
|
-
* halves are validated — the prefix may not contain `..` or NUL either, and the
|
|
171
|
-
* resulting key must stay under KV's length ceiling. Recommended for any
|
|
172
|
-
* multi-tenant deployment so client-supplied keys can't address peer data.
|
|
173
|
-
* Mirrors `scopeKey` from `@lunora/storage`.
|
|
174
|
-
*/
|
|
169
|
+
* Compose a per-tenant key from a scope prefix and a caller-supplied key. Both
|
|
170
|
+
* halves are validated — the prefix may not contain `..` or NUL either, and the
|
|
171
|
+
* resulting key must stay under KV's length ceiling. Recommended for any
|
|
172
|
+
* multi-tenant deployment so client-supplied keys can't address peer data.
|
|
173
|
+
* Mirrors `scopeKey` from `@lunora/storage`.
|
|
174
|
+
*/
|
|
175
175
|
declare const scopeKey: (prefix: string, key: string) => string;
|
|
176
176
|
declare const createKv: (options: LunoraKvOptions) => Kv;
|
|
177
|
-
|
|
177
|
+
/** One KV namespace as the studio's KV browser surfaces it (mirrors the runtime's KvNamespaceSummary). */
|
|
178
|
+
interface KvNamespaceSummaryLike {
|
|
179
|
+
binding: string;
|
|
180
|
+
}
|
|
181
|
+
/** One key entry as surfaced by the KV admin browser (mirrors the runtime's KvKeyEntry). */
|
|
182
|
+
interface KvKeyEntryLike {
|
|
183
|
+
expiration?: number;
|
|
184
|
+
metadata?: unknown;
|
|
185
|
+
name: string;
|
|
186
|
+
}
|
|
187
|
+
/** A paginated page of KV keys (mirrors the runtime's KvKeyListResult). */
|
|
188
|
+
interface KvKeyListResultLike {
|
|
189
|
+
cursor?: string;
|
|
190
|
+
keys: KvKeyEntryLike[];
|
|
191
|
+
listComplete: boolean;
|
|
192
|
+
}
|
|
193
|
+
/** A value together with its metadata (mirrors the runtime's KvValueResult). */
|
|
194
|
+
interface KvValueResultLike {
|
|
195
|
+
metadata: unknown;
|
|
196
|
+
value: null | string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The structural shape of a KV introspector — mirrors `KvIntrospector` from
|
|
200
|
+
* `@lunora/runtime` without importing it, keeping the dependency graph clean.
|
|
201
|
+
*/
|
|
202
|
+
interface KvIntrospectorLike {
|
|
203
|
+
deleteKey: (options: {
|
|
204
|
+
key: string;
|
|
205
|
+
namespace: string;
|
|
206
|
+
}) => Promise<void>;
|
|
207
|
+
getValue: (options: {
|
|
208
|
+
key: string;
|
|
209
|
+
namespace: string;
|
|
210
|
+
}) => Promise<KvValueResultLike>;
|
|
211
|
+
listKeys: (options: {
|
|
212
|
+
cursor?: string;
|
|
213
|
+
limit?: number;
|
|
214
|
+
namespace: string;
|
|
215
|
+
prefix?: string;
|
|
216
|
+
}) => Promise<KvKeyListResultLike>;
|
|
217
|
+
listNamespaces: () => Promise<KvNamespaceSummaryLike[]>;
|
|
218
|
+
putValue: (options: {
|
|
219
|
+
expiration?: number;
|
|
220
|
+
expirationTtl?: number;
|
|
221
|
+
key: string;
|
|
222
|
+
metadata?: unknown;
|
|
223
|
+
namespace: string;
|
|
224
|
+
value: string;
|
|
225
|
+
}) => Promise<void>;
|
|
226
|
+
}
|
|
227
|
+
/** Construction options for {@link createKvIntrospector}. */
|
|
228
|
+
interface CreateKvIntrospectorOptions {
|
|
229
|
+
/**
|
|
230
|
+
* Map of binding name → bound KV namespace. Each entry becomes one
|
|
231
|
+
* namespace the studio can browse. Example:
|
|
232
|
+
* ```ts
|
|
233
|
+
* createKvIntrospector({ namespaces: { MY_KV: env.MY_KV } })
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
namespaces: Record<string, KVNamespaceLike>;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Build a `KvIntrospector`-compatible object from a map of bound KV namespaces.
|
|
240
|
+
* Pass the result as `kvIntrospector` on `WorkerOptions` to enable the studio's
|
|
241
|
+
* KV browser (`/_lunora/admin/kv/*` endpoints).
|
|
242
|
+
* @example
|
|
243
|
+
* ```ts
|
|
244
|
+
* createWorker({
|
|
245
|
+
* // …
|
|
246
|
+
* kvIntrospector: createKvIntrospector({ namespaces: { MY_KV: env.MY_KV } }),
|
|
247
|
+
* });
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
declare const createKvIntrospector: (options: CreateKvIntrospectorOptions) => KvIntrospectorLike;
|
|
251
|
+
/**
|
|
252
|
+
* Zero-config KV introspector: scan a worker `env` for every bound Workers KV
|
|
253
|
+
* namespace and register each under its binding name. Every `kv_namespaces` entry
|
|
254
|
+
* in `wrangler.jsonc` then appears in the studio's KV browser automatically — no
|
|
255
|
+
* hand-written `createKvIntrospector({ namespaces: … })` call, and any binding
|
|
256
|
+
* name (not just `KV`) and any number of namespaces light up. Non-KV bindings
|
|
257
|
+
* (R2, Durable Objects, queues, secrets, …) are skipped via {@link isKvNamespace}.
|
|
258
|
+
*
|
|
259
|
+
* Returns an introspector even when `env` holds no KV namespaces — its
|
|
260
|
+
* `listNamespaces()` resolves to `[]`, so the studio renders an empty state
|
|
261
|
+
* rather than a "not configured" error.
|
|
262
|
+
* @example
|
|
263
|
+
* ```ts
|
|
264
|
+
* createWorker({
|
|
265
|
+
* // …
|
|
266
|
+
* kvIntrospector: createKvIntrospectorFromEnv(env),
|
|
267
|
+
* });
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
declare const createKvIntrospectorFromEnv: (env: unknown) => KvIntrospectorLike;
|
|
271
|
+
export { type CreateKvIntrospectorOptions, type KVNamespaceLike, type Kv, type KvGetOptions, type KvIntrospectorLike, type KvListKey, type KvListOptions, type KvListResult, type KvNamespaceListResult, type KvNamespacePutOptions, type KvPutOptions, type KvValue, type KvValueType, type KvValueWithMetadata, type LunoraKvOptions, createKv, createKvIntrospector, createKvIntrospectorFromEnv, scopeKey };
|
package/dist/kv/index.mjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { createKv, scopeKey } from '../packem_shared/createKv-
|
|
1
|
+
export { createKv, scopeKey } from '../packem_shared/createKv-C8Iyu5hD.mjs';
|
|
2
|
+
export { createKvIntrospector, createKvIntrospectorFromEnv } from '../packem_shared/createKvIntrospector-Byk4GfsY.mjs';
|
package/dist/packem_shared/{AnalyticsSqlError-CGTdsi4H.mjs → AnalyticsSqlError-C2nz3jpH.mjs}
RENAMED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
|
|
1
3
|
const SQL_API_BASE = "https://api.cloudflare.com/client/v4/accounts";
|
|
2
|
-
class AnalyticsSqlError extends
|
|
3
|
-
status;
|
|
4
|
+
class AnalyticsSqlError extends LunoraError {
|
|
4
5
|
constructor(status, body) {
|
|
5
|
-
super(`Analytics Engine SQL API returned ${String(status)}: ${body}
|
|
6
|
-
this.name = "AnalyticsSqlError";
|
|
7
|
-
this.status = status;
|
|
6
|
+
super("ANALYTICS_SQL_ERROR", `Analytics Engine SQL API returned ${String(status)}: ${body}`, { name: "AnalyticsSqlError", status });
|
|
8
7
|
}
|
|
9
8
|
}
|
|
10
9
|
const createAnalyticsSqlClient = (config) => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
import SelectBuilder from './SelectBuilder-BOqJQHEv.mjs';
|
|
3
|
+
import { ident, toText } from './Sql-B3zq2YGx.mjs';
|
|
3
4
|
|
|
4
5
|
const API_BASE = "https://api.sql.cloudflarestorage.com/api/v1/accounts";
|
|
5
6
|
const inferColumns = (rows) => {
|
|
@@ -10,12 +11,9 @@ const inferColumns = (rows) => {
|
|
|
10
11
|
return { name };
|
|
11
12
|
});
|
|
12
13
|
};
|
|
13
|
-
class R2SqlError extends
|
|
14
|
-
status;
|
|
14
|
+
class R2SqlError extends LunoraError {
|
|
15
15
|
constructor(status, body) {
|
|
16
|
-
super(`R2 SQL query failed (${String(status)}): ${body}
|
|
17
|
-
this.name = "R2SqlError";
|
|
18
|
-
this.status = status;
|
|
16
|
+
super("R2_SQL_ERROR", `R2 SQL query failed (${String(status)}): ${body}`, { name: "R2SqlError", status });
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
19
|
const createR2Sql = (config) => {
|
|
@@ -53,12 +51,14 @@ const createR2Sql = (config) => {
|
|
|
53
51
|
};
|
|
54
52
|
};
|
|
55
53
|
return {
|
|
56
|
-
describe: async (table) => exec(`DESCRIBE ${table}`),
|
|
54
|
+
describe: async (table) => exec(`DESCRIBE ${ident(table)}`),
|
|
57
55
|
explain: async (statement, options) => exec(`EXPLAIN ${options?.format === "json" ? "FORMAT JSON " : ""}${toText(statement)}`),
|
|
56
|
+
// `SelectBuilder`'s constructor validates the table reference (allowing an
|
|
57
|
+
// optional `[AS] alias`), so no pre-validation here.
|
|
58
58
|
from: (table) => new SelectBuilder(exec, table),
|
|
59
59
|
query: async (statement) => exec(toText(statement)),
|
|
60
60
|
showDatabases: async () => exec("SHOW DATABASES"),
|
|
61
|
-
showTables: async (namespace) => exec(`SHOW TABLES IN ${namespace}`)
|
|
61
|
+
showTables: async (namespace) => exec(`SHOW TABLES IN ${ident(namespace)}`)
|
|
62
62
|
};
|
|
63
63
|
};
|
|
64
64
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { renderOrderTerm } from './asc-
|
|
2
|
-
import SetOperation from './SetOperation-
|
|
3
|
-
import { toText, lit } from './Sql-
|
|
1
|
+
import { renderOrderTerm } from './asc-DZbQCxh1.mjs';
|
|
2
|
+
import SetOperation from './SetOperation-DmPgUL8W.mjs';
|
|
3
|
+
import { tableRef, toText, assertLimit, lit } from './Sql-B3zq2YGx.mjs';
|
|
4
4
|
|
|
5
5
|
const JOIN_KEYWORDS = {
|
|
6
6
|
cross: "CROSS JOIN",
|
|
@@ -24,7 +24,7 @@ class SelectBuilder {
|
|
|
24
24
|
limitValue;
|
|
25
25
|
constructor(exec, table) {
|
|
26
26
|
this.exec = exec;
|
|
27
|
-
this.table = table;
|
|
27
|
+
this.table = tableRef(table);
|
|
28
28
|
}
|
|
29
29
|
/** The `SELECT` list. Omit/empty for `SELECT *`. Items are columns, expressions, or aliased window fragments (`fn.rowNumber().over(...).as("rk")`). */
|
|
30
30
|
select(...items) {
|
|
@@ -91,6 +91,7 @@ class SelectBuilder {
|
|
|
91
91
|
}
|
|
92
92
|
/** `LIMIT n` (R2 SQL: 1–10,000, default 500). */
|
|
93
93
|
limit(n) {
|
|
94
|
+
assertLimit(n);
|
|
94
95
|
this.limitValue = n;
|
|
95
96
|
return this;
|
|
96
97
|
}
|
|
@@ -156,7 +157,7 @@ class SelectBuilder {
|
|
|
156
157
|
return this.distinctFlag ? "SELECT DISTINCT" : "SELECT";
|
|
157
158
|
}
|
|
158
159
|
addJoin(kind, table, on) {
|
|
159
|
-
this.joins.push({ kind, on, table });
|
|
160
|
+
this.joins.push({ kind, on, table: tableRef(table) });
|
|
160
161
|
return this;
|
|
161
162
|
}
|
|
162
163
|
setOperation(operator, other) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { renderOrderTerm } from './asc-
|
|
2
|
-
import { lit } from './Sql-
|
|
1
|
+
import { renderOrderTerm } from './asc-DZbQCxh1.mjs';
|
|
2
|
+
import { assertLimit, lit } from './Sql-B3zq2YGx.mjs';
|
|
3
3
|
|
|
4
4
|
const renderMember = (query) => {
|
|
5
5
|
const text = query.toSQL();
|
|
@@ -44,6 +44,7 @@ class SetOperation {
|
|
|
44
44
|
}
|
|
45
45
|
/** `LIMIT` applied to the combined result. */
|
|
46
46
|
limit(n) {
|
|
47
|
+
assertLimit(n);
|
|
47
48
|
this.limitValue = n;
|
|
48
49
|
return this;
|
|
49
50
|
}
|