@moku-labs/worker 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -9
- package/dist/cli-Dc0q0hIy.cjs +2988 -0
- package/dist/cli-DgZv5A0G.mjs +2888 -0
- package/dist/cli.cjs +3 -1900
- package/dist/cli.d.cts +1 -270
- package/dist/cli.d.mts +1 -270
- package/dist/cli.mjs +1 -1875
- package/dist/index-VZ99IAMv.d.cts +353 -0
- package/dist/index-VZ99IAMv.d.mts +353 -0
- package/dist/index.cjs +61 -63
- package/dist/index.d.cts +8 -4
- package/dist/index.d.mts +8 -4
- package/dist/index.mjs +49 -53
- package/package.json +1 -1
- package/dist/config-BYPJvEbl.d.cts +0 -88
- package/dist/config-BYPJvEbl.d.mts +0 -88
- package/dist/storage-COo-F38H.mjs +0 -884
- package/dist/storage-CgXl-dUA.cjs +0 -949
|
@@ -1,949 +0,0 @@
|
|
|
1
|
-
let _moku_labs_common = require("@moku-labs/common");
|
|
2
|
-
let _moku_labs_core = require("@moku-labs/core");
|
|
3
|
-
/**
|
|
4
|
-
* stage core plugin — deployment-stage / dev-mode detection, flat-injected on
|
|
5
|
-
* every regular plugin's context as `ctx.stage` (spec/02 §6). No state, no
|
|
6
|
-
* events, no depends, no lifecycle hooks.
|
|
7
|
-
*
|
|
8
|
-
* @see README.md
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* // Inside any regular plugin's api factory:
|
|
12
|
-
* api: (ctx) => ({
|
|
13
|
-
* errorBody: (e: Error) =>
|
|
14
|
-
* ctx.stage.isDev() ? e.stack ?? e.message : "Internal Error",
|
|
15
|
-
* })
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
const stagePlugin = (0, _moku_labs_core.createCorePlugin)("stage", {
|
|
19
|
-
config: { stage: "production" },
|
|
20
|
-
/**
|
|
21
|
-
* Builds the stage accessor surface from the resolved stage.
|
|
22
|
-
*
|
|
23
|
-
* @param ctx - Core plugin context (spec/02 §6 — `{ config, state }` only;
|
|
24
|
-
* no `global`, `emit`, or `require`). `state` is unused by this plugin.
|
|
25
|
-
* @param ctx.config - The resolved plugin config containing the deployment stage.
|
|
26
|
-
* @returns The `ctx.stage` API: `isDev`, `isProduction`, `current`.
|
|
27
|
-
* @example
|
|
28
|
-
* ```typescript
|
|
29
|
-
* const api = stagePlugin.spec.api({ config: { stage: "development" }, state: {} });
|
|
30
|
-
* api.isDev(); // true
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
api: ({ config }) => ({
|
|
34
|
-
/**
|
|
35
|
-
* Whether this Worker runs in the development stage.
|
|
36
|
-
*
|
|
37
|
-
* @returns True iff `stage === "development"`.
|
|
38
|
-
* @example
|
|
39
|
-
* ```typescript
|
|
40
|
-
* if (ctx.stage.isDev()) return Response.json({ stack: err.stack });
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
isDev: () => config.stage === "development",
|
|
44
|
-
/**
|
|
45
|
-
* Whether this Worker runs in the production stage. Note: false in "test".
|
|
46
|
-
*
|
|
47
|
-
* @returns True iff `stage === "production"`.
|
|
48
|
-
* @example
|
|
49
|
-
* ```typescript
|
|
50
|
-
* const cc = ctx.stage.isProduction() ? "public, max-age=31536000" : "no-store";
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
|
-
isProduction: () => config.stage === "production",
|
|
54
|
-
/**
|
|
55
|
-
* The raw deployment stage, as the literal union (not `string`).
|
|
56
|
-
*
|
|
57
|
-
* @returns The resolved stage.
|
|
58
|
-
* @example
|
|
59
|
-
* ```typescript
|
|
60
|
-
* ctx.log.info("startup", { stage: ctx.stage.current() });
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
current: () => config.stage
|
|
64
|
-
})
|
|
65
|
-
});
|
|
66
|
-
const coreConfig = (0, _moku_labs_core.createCoreConfig)("moku-worker", {
|
|
67
|
-
config: {
|
|
68
|
-
stage: "production",
|
|
69
|
-
name: "moku-worker",
|
|
70
|
-
compatibilityDate: ""
|
|
71
|
-
},
|
|
72
|
-
plugins: [
|
|
73
|
-
_moku_labs_common.logPlugin,
|
|
74
|
-
_moku_labs_common.envPlugin,
|
|
75
|
-
stagePlugin
|
|
76
|
-
]
|
|
77
|
-
});
|
|
78
|
-
const { createPlugin, createCore } = coreConfig;
|
|
79
|
-
//#endregion
|
|
80
|
-
//#region src/plugins/bindings/api.ts
|
|
81
|
-
/**
|
|
82
|
-
* Checks whether a value read from an env object is nullish (null or undefined).
|
|
83
|
-
* Cloudflare supplies either form when a binding is absent, so both must be caught.
|
|
84
|
-
*
|
|
85
|
-
* @param value - The value read from the env object.
|
|
86
|
-
* @returns True when the value is null or undefined.
|
|
87
|
-
* @example
|
|
88
|
-
* ```typescript
|
|
89
|
-
* isNullish(undefined); // true
|
|
90
|
-
* isNullish(0); // false — falsy but bound
|
|
91
|
-
* ```
|
|
92
|
-
*/
|
|
93
|
-
const isNullish = (value) => value === void 0 || value === null;
|
|
94
|
-
/**
|
|
95
|
-
* Resolves binding `name` off a request-supplied env object, narrowed to T.
|
|
96
|
-
* Throws a `[moku-worker]`-prefixed error when the binding is nullish.
|
|
97
|
-
* The env argument is read but never retained.
|
|
98
|
-
*
|
|
99
|
-
* @param env - The Cloudflare request env object passed to fetch/scheduled/queue.
|
|
100
|
-
* @param name - The binding name to resolve.
|
|
101
|
-
* @returns The binding value narrowed to T.
|
|
102
|
-
* @throws {Error} With a `[moku-worker]` prefix when the binding is null or undefined.
|
|
103
|
-
* @example
|
|
104
|
-
* ```typescript
|
|
105
|
-
* const kv = requireBinding<KVNamespace>(env, "MY_KV");
|
|
106
|
-
* ```
|
|
107
|
-
*/
|
|
108
|
-
const requireBinding = (env, name) => {
|
|
109
|
-
const value = env[name];
|
|
110
|
-
if (isNullish(value)) throw new Error(`[moku-worker] binding "${name}" is not bound.\n Declare it in wrangler config and pass it in via the request env.`);
|
|
111
|
-
return value;
|
|
112
|
-
};
|
|
113
|
-
/**
|
|
114
|
-
* Returns true when `name` resolves to a non-nullish value on the request env.
|
|
115
|
-
* Never throws. Use for optional-binding branching without forcing an error.
|
|
116
|
-
*
|
|
117
|
-
* @param env - The Cloudflare request env object passed to fetch/scheduled/queue.
|
|
118
|
-
* @param name - The binding name to check.
|
|
119
|
-
* @returns Whether the binding is present and non-nullish.
|
|
120
|
-
* @example
|
|
121
|
-
* ```typescript
|
|
122
|
-
* const ok = hasBinding(env, "DB"); // false if DB is not bound
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
const hasBinding = (env, name) => !isNullish(env[name]);
|
|
126
|
-
/**
|
|
127
|
-
* Builds the app.bindings API surface. The factory receives a context but does
|
|
128
|
-
* not use it — bindings holds no state (F4) and all resolution is argument-local.
|
|
129
|
-
*
|
|
130
|
-
* @param _ctx - Plugin context (unused; bindings is stateless — F4).
|
|
131
|
-
* @returns BindingsApi with `require` and `has` methods.
|
|
132
|
-
* @example
|
|
133
|
-
* ```typescript
|
|
134
|
-
* const api = createBindingsApi(ctx);
|
|
135
|
-
* const kv = api.require<KVNamespace>(env, "MY_KV");
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
|
-
const createBindingsApi = (_ctx) => ({
|
|
139
|
-
require: requireBinding,
|
|
140
|
-
has: hasBinding
|
|
141
|
-
});
|
|
142
|
-
/**
|
|
143
|
-
* Standard-tier stateless resolver — the binding-family dependency root.
|
|
144
|
-
*
|
|
145
|
-
* Exposes `require<T>(env, name)` and `has(env, name)` off a per-request env
|
|
146
|
-
* object. Regular plugin so downstream binding plugins can declare
|
|
147
|
-
* `depends: [bindingsPlugin]` and reach it via `ctx.require(bindingsPlugin)`.
|
|
148
|
-
*
|
|
149
|
-
* @see README.md
|
|
150
|
-
*/
|
|
151
|
-
const bindingsPlugin = createPlugin("bindings", {
|
|
152
|
-
config: { required: [] },
|
|
153
|
-
api: createBindingsApi
|
|
154
|
-
});
|
|
155
|
-
//#endregion
|
|
156
|
-
//#region src/plugins/d1/api.ts
|
|
157
|
-
/**
|
|
158
|
-
* Create the d1 api. Each method resolves the D1Database off the request
|
|
159
|
-
* `env` via the bindings plugin, then forwards to the native D1 call. The
|
|
160
|
-
* binding is never cached, so concurrent requests stay isolated (SB4).
|
|
161
|
-
*
|
|
162
|
-
* The return is intentionally NOT annotated `: Api`. Annotating it would
|
|
163
|
-
* collapse the per-method call-site generic `<T>` on `query`/`first` to
|
|
164
|
-
* `unknown`; instead the implementation forwards `<T>` to `all<T>()` /
|
|
165
|
-
* `first<T>()` and `types.ts#Api` remains the public-surface source of truth.
|
|
166
|
-
*
|
|
167
|
-
* @param {D1Ctx} ctx - Plugin context (own config + require).
|
|
168
|
-
* @returns {object} The d1 public api (query, first, run, batch, prepare, deployManifest).
|
|
169
|
-
* @example
|
|
170
|
-
* ```typescript
|
|
171
|
-
* const api = createD1Api(ctx);
|
|
172
|
-
* const { results } = await api.query<Product>(env, "SELECT * FROM products");
|
|
173
|
-
* ```
|
|
174
|
-
*/
|
|
175
|
-
const createD1Api = (ctx) => {
|
|
176
|
-
const db = (env) => ctx.require(bindingsPlugin).require(env, ctx.config.binding);
|
|
177
|
-
return {
|
|
178
|
-
/**
|
|
179
|
-
* Run a statement and return all rows. Forwards the call-site generic to
|
|
180
|
-
* `all<T>()` so the result type is not widened to `unknown`.
|
|
181
|
-
*
|
|
182
|
-
* @param {WorkerEnv} env - Per-request Cloudflare bindings object.
|
|
183
|
-
* @param {string} sql - SQL text with `?` placeholders.
|
|
184
|
-
* @param {unknown[]} params - Bind parameters, in placeholder order.
|
|
185
|
-
* @returns {Promise<D1Result<T>>} All rows (`.results` is `T[]`).
|
|
186
|
-
* @example
|
|
187
|
-
* ```typescript
|
|
188
|
-
* const { results } = await api.query<Product>(env, "SELECT * FROM products WHERE active = ?", 1);
|
|
189
|
-
* ```
|
|
190
|
-
*/
|
|
191
|
-
query: (env, sql, ...params) => db(env).prepare(sql).bind(...params).all(),
|
|
192
|
-
/**
|
|
193
|
-
* Run a statement and return the first row, or `null` if there are none.
|
|
194
|
-
* Forwards the call-site generic to `first<T>()`.
|
|
195
|
-
*
|
|
196
|
-
* @param {WorkerEnv} env - Per-request Cloudflare bindings object.
|
|
197
|
-
* @param {string} sql - SQL text with `?` placeholders.
|
|
198
|
-
* @param {unknown[]} params - Bind parameters, in placeholder order.
|
|
199
|
-
* @returns {Promise<T | null>} The first row, or `null` if none matched.
|
|
200
|
-
* @example
|
|
201
|
-
* ```typescript
|
|
202
|
-
* const row = await api.first<Product>(env, "SELECT * FROM products WHERE id = ?", id);
|
|
203
|
-
* ```
|
|
204
|
-
*/
|
|
205
|
-
first: (env, sql, ...params) => db(env).prepare(sql).bind(...params).first(),
|
|
206
|
-
/**
|
|
207
|
-
* Run a write/DDL statement (INSERT/UPDATE/DELETE/DDL) and return the
|
|
208
|
-
* D1 result carrying `.meta` (e.g. `rows_written`, `last_row_id`).
|
|
209
|
-
*
|
|
210
|
-
* @param {WorkerEnv} env - Per-request Cloudflare bindings object.
|
|
211
|
-
* @param {string} sql - SQL text with `?` placeholders.
|
|
212
|
-
* @param {unknown[]} params - Bind parameters, in placeholder order.
|
|
213
|
-
* @returns {Promise<D1Result>} Result carrying `.meta`.
|
|
214
|
-
* @example
|
|
215
|
-
* ```typescript
|
|
216
|
-
* const res = await api.run(env, "INSERT INTO products (name) VALUES (?)", name);
|
|
217
|
-
* const id = res.meta.last_row_id;
|
|
218
|
-
* ```
|
|
219
|
-
*/
|
|
220
|
-
run: (env, sql, ...params) => db(env).prepare(sql).bind(...params).run(),
|
|
221
|
-
/**
|
|
222
|
-
* Execute caller-built prepared statements atomically in one round-trip,
|
|
223
|
-
* returning one result per statement in order.
|
|
224
|
-
*
|
|
225
|
-
* @param {WorkerEnv} env - Per-request Cloudflare bindings object.
|
|
226
|
-
* @param {D1PreparedStatement[]} stmts - Statements built from prepare(env).
|
|
227
|
-
* @returns {Promise<D1Result[]>} One result per statement, order preserved.
|
|
228
|
-
* @example
|
|
229
|
-
* ```typescript
|
|
230
|
-
* const handle = api.prepare(env);
|
|
231
|
-
* await api.batch(env, [handle.prepare("INSERT INTO a VALUES (1)").bind()]);
|
|
232
|
-
* ```
|
|
233
|
-
*/
|
|
234
|
-
batch: (env, stmts) => db(env).batch(stmts),
|
|
235
|
-
/**
|
|
236
|
-
* Resolve the request-scoped D1Database so callers can build prepared
|
|
237
|
-
* statements for batch(). Issues no query itself.
|
|
238
|
-
*
|
|
239
|
-
* @param {WorkerEnv} env - Per-request Cloudflare bindings object.
|
|
240
|
-
* @returns {D1Database} The request-resolved database handle.
|
|
241
|
-
* @example
|
|
242
|
-
* ```typescript
|
|
243
|
-
* const handle = api.prepare(env);
|
|
244
|
-
* const stmt = handle.prepare("SELECT * FROM t").bind();
|
|
245
|
-
* ```
|
|
246
|
-
*/
|
|
247
|
-
prepare: (env) => db(env),
|
|
248
|
-
/**
|
|
249
|
-
* Return this plugin's deploy metadata for the deploy plugin to read.
|
|
250
|
-
* Build-time only — takes no `env`. The return is typed `DeployManifest`
|
|
251
|
-
* (from types.ts), which pins `kind` to the literal `"d1"` without an
|
|
252
|
-
* inline `as` assertion.
|
|
253
|
-
*
|
|
254
|
-
* @returns {DeployManifest} Deploy manifest entry `{ kind: "d1", binding, migrations }`.
|
|
255
|
-
* @example
|
|
256
|
-
* ```typescript
|
|
257
|
-
* const m = api.deployManifest();
|
|
258
|
-
* // => { kind: "d1", binding: "DB", migrations: "./migrations" }
|
|
259
|
-
* ```
|
|
260
|
-
*/
|
|
261
|
-
deployManifest: () => ({
|
|
262
|
-
kind: "d1",
|
|
263
|
-
binding: ctx.config.binding,
|
|
264
|
-
migrations: ctx.config.migrations
|
|
265
|
-
})
|
|
266
|
-
};
|
|
267
|
-
};
|
|
268
|
-
/**
|
|
269
|
-
* Standard tier — Cloudflare D1 SQL access (thin typed wrappers, not an ORM).
|
|
270
|
-
*
|
|
271
|
-
* Exposes `query`, `first`, `run`, `batch`, `prepare`, and `deployManifest`.
|
|
272
|
-
* Resolves the D1 binding off the per-request `env` via the bindings plugin.
|
|
273
|
-
* No state, no events, no lifecycle hooks (request-scoped, spec/06 §3).
|
|
274
|
-
*
|
|
275
|
-
* @see README.md
|
|
276
|
-
*/
|
|
277
|
-
const d1Plugin = createPlugin("d1", {
|
|
278
|
-
depends: [bindingsPlugin],
|
|
279
|
-
config: {
|
|
280
|
-
binding: "DB",
|
|
281
|
-
migrations: ""
|
|
282
|
-
},
|
|
283
|
-
api: (ctx) => createD1Api(ctx)
|
|
284
|
-
});
|
|
285
|
-
//#endregion
|
|
286
|
-
//#region src/plugins/durable-objects/api.ts
|
|
287
|
-
/**
|
|
288
|
-
* Builds the `app.durableObjects` API surface — `get` and `deployManifest`.
|
|
289
|
-
*
|
|
290
|
-
* All namespace resolution uses the per-call `env` argument: `env` is threaded, never
|
|
291
|
-
* stored (SB4 / design §1a). The config bindings map is frozen and read-only. No state
|
|
292
|
-
* is held on the plugin between calls (stateless — `Record<string, never>`).
|
|
293
|
-
*
|
|
294
|
-
* @param ctx - Plugin context with `config.bindings`, `require(bindingsPlugin)`, and core APIs.
|
|
295
|
-
* @returns The durableObjects API: `{ get, deployManifest }`.
|
|
296
|
-
* @example
|
|
297
|
-
* ```typescript
|
|
298
|
-
* const api = createDoApi(ctx);
|
|
299
|
-
* const stub = api.get(env, "counter", "room-42");
|
|
300
|
-
* const manifest = api.deployManifest(); // { kind: "do", bindings: { counter: "COUNTER" } }
|
|
301
|
-
* ```
|
|
302
|
-
*/
|
|
303
|
-
const createDoApi = (ctx) => ({
|
|
304
|
-
/**
|
|
305
|
-
* Resolves a `DurableObjectStub` off the per-request env.
|
|
306
|
-
*
|
|
307
|
-
* Maps `logicalName` → `config.bindings[logicalName]` (falling back to `logicalName`
|
|
308
|
-
* itself when unmapped), derives a deterministic id via `namespace.idFromName(idName)`,
|
|
309
|
-
* and returns the addressed stub. Synchronous — returns a stub, not a Promise.
|
|
310
|
-
* Throws (via the bindings resolver) when the binding is not present on `env`.
|
|
311
|
-
*
|
|
312
|
-
* @param env - Per-request Cloudflare bindings object (Worker fetch/queue/scheduled env).
|
|
313
|
-
* @param logicalName - Logical DO name used in code (e.g. `"counter"`).
|
|
314
|
-
* @param idName - Stable id name passed to `idFromName` (e.g. `"room-42"`).
|
|
315
|
-
* @returns The addressed `DurableObjectStub`.
|
|
316
|
-
* @throws {Error} With `[moku-worker]` prefix when the binding is not bound on `env`.
|
|
317
|
-
* @example
|
|
318
|
-
* ```typescript
|
|
319
|
-
* const stub = app.durableObjects.get(env, "counter", "room-42");
|
|
320
|
-
* const res = await stub.fetch("https://do/increment");
|
|
321
|
-
* ```
|
|
322
|
-
*/
|
|
323
|
-
get: (env, logicalName, idName) => {
|
|
324
|
-
const binding = ctx.config.bindings[logicalName] ?? logicalName;
|
|
325
|
-
const ns = ctx.require(bindingsPlugin).require(env, binding);
|
|
326
|
-
return ns.get(ns.idFromName(idName));
|
|
327
|
-
},
|
|
328
|
-
/**
|
|
329
|
-
* Returns this plugin's deploy metadata — read by the `deploy` plugin via
|
|
330
|
-
* `ctx.require(durableObjectsPlugin)`. Never reads sibling `pluginConfigs` (F6;
|
|
331
|
-
* spec/08 §5, §7). Pure synchronous read of `ctx.config.bindings`.
|
|
332
|
-
*
|
|
333
|
-
* @returns `{ kind: "do", bindings }` reflecting the frozen plugin config.
|
|
334
|
-
* @example
|
|
335
|
-
* ```typescript
|
|
336
|
-
* const manifest = app.durableObjects.deployManifest();
|
|
337
|
-
* // → { kind: "do", bindings: { counter: "COUNTER" } }
|
|
338
|
-
* ```
|
|
339
|
-
*/
|
|
340
|
-
deployManifest: () => ({
|
|
341
|
-
kind: "do",
|
|
342
|
-
bindings: ctx.config.bindings
|
|
343
|
-
})
|
|
344
|
-
});
|
|
345
|
-
//#endregion
|
|
346
|
-
//#region src/plugins/durable-objects/helpers.ts
|
|
347
|
-
/**
|
|
348
|
-
* Returns a base class the consumer extends and exports from `worker.ts`.
|
|
349
|
-
*
|
|
350
|
-
* PURE (spec/03 §1): takes no `ctx`, has no side effects, and may be called before
|
|
351
|
-
* `createApp`. The static `doName` property captures `name` for diagnostics and
|
|
352
|
-
* binding correlation. The constructor stores `(state, env)` as `this.ctx` / `this.env`,
|
|
353
|
-
* satisfying the Cloudflare Durable Object constructor contract. The plugin NEVER
|
|
354
|
-
* generates the final exported class — the consumer owns that class.
|
|
355
|
-
*
|
|
356
|
-
* @param name - Logical DO name; captured as `static doName` for diagnostics.
|
|
357
|
-
* @returns A base class (constructor) the consumer extends.
|
|
358
|
-
* @example
|
|
359
|
-
* ```typescript
|
|
360
|
-
* // src/counter.ts
|
|
361
|
-
* import { defineDurableObject } from "@moku-labs/worker";
|
|
362
|
-
*
|
|
363
|
-
* export class Counter extends defineDurableObject("Counter") {
|
|
364
|
-
* async fetch(): Promise<Response> {
|
|
365
|
-
* const n = ((await this.ctx.storage.get<number>("n")) ?? 0) + 1;
|
|
366
|
-
* await this.ctx.storage.put("n", n);
|
|
367
|
-
* return Response.json({ n });
|
|
368
|
-
* }
|
|
369
|
-
* }
|
|
370
|
-
* ```
|
|
371
|
-
*/
|
|
372
|
-
const defineDurableObject = (name) => {
|
|
373
|
-
/**
|
|
374
|
-
* Base implementation of the Cloudflare Durable Object constructor contract.
|
|
375
|
-
* Stores `(ctx, env)` as readonly properties for consumer subclasses to use.
|
|
376
|
-
*/
|
|
377
|
-
class DurableObjectBaseImpl {
|
|
378
|
-
/**
|
|
379
|
-
* Cloudflare per-object storage/alarm context (DurableObjectState).
|
|
380
|
-
* Use `this.ctx.storage` to read/write durable storage and `this.ctx.id` to inspect the DO id.
|
|
381
|
-
*/
|
|
382
|
-
ctx;
|
|
383
|
-
/**
|
|
384
|
-
* Per-object Cloudflare bindings (per-request WorkerEnv).
|
|
385
|
-
* Mirrors the env passed at construction time; never cached across requests.
|
|
386
|
-
*/
|
|
387
|
-
env;
|
|
388
|
-
/**
|
|
389
|
-
* Logical DO name captured from `defineDurableObject(name)`.
|
|
390
|
-
* Used for diagnostics and binding correlation.
|
|
391
|
-
*/
|
|
392
|
-
static doName = name;
|
|
393
|
-
/**
|
|
394
|
-
* Constructs the base Durable Object with Cloudflare's required signature.
|
|
395
|
-
*
|
|
396
|
-
* @param ctx - Cloudflare DurableObjectState (storage, id, blockConcurrencyWhile, …).
|
|
397
|
-
* @param env - Per-request Cloudflare bindings object (WorkerEnv).
|
|
398
|
-
* @example
|
|
399
|
-
* ```typescript
|
|
400
|
-
* class Counter extends Base {
|
|
401
|
-
* constructor(ctx: DurableObjectState, env: WorkerEnv) { super(ctx, env); }
|
|
402
|
-
* }
|
|
403
|
-
* ```
|
|
404
|
-
*/
|
|
405
|
-
constructor(ctx, env) {
|
|
406
|
-
this.ctx = ctx;
|
|
407
|
-
this.env = env;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return DurableObjectBaseImpl;
|
|
411
|
-
};
|
|
412
|
-
/**
|
|
413
|
-
* Cloudflare Durable Objects plugin — Standard tier.
|
|
414
|
-
*
|
|
415
|
-
* Exposes `get(env, logicalName, idName)` (synchronous stub accessor, threaded env) and
|
|
416
|
-
* `deployManifest()` (build-time metadata). Depends on `bindingsPlugin` for namespace
|
|
417
|
-
* resolution. The `defineDurableObject` helper is mounted under `helpers` and re-exported
|
|
418
|
-
* at the top level for consumer use.
|
|
419
|
-
*
|
|
420
|
-
* @example
|
|
421
|
-
* ```typescript
|
|
422
|
-
* // Consumer endpoint handler:
|
|
423
|
-
* const stub = app.durableObjects.get(env, "counter", params.room!);
|
|
424
|
-
* const res = await stub.fetch("https://do/increment");
|
|
425
|
-
* // Consumer DO class:
|
|
426
|
-
* export class Counter extends defineDurableObject("Counter") {
|
|
427
|
-
* async fetch(): Promise<Response> { return new Response("ok"); }
|
|
428
|
-
* }
|
|
429
|
-
* ```
|
|
430
|
-
* @see README.md
|
|
431
|
-
*/
|
|
432
|
-
const durableObjectsPlugin = createPlugin("durableObjects", {
|
|
433
|
-
depends: [bindingsPlugin],
|
|
434
|
-
config: { bindings: {} },
|
|
435
|
-
api: createDoApi,
|
|
436
|
-
helpers: { defineDurableObject }
|
|
437
|
-
});
|
|
438
|
-
//#endregion
|
|
439
|
-
//#region src/plugins/kv/api.ts
|
|
440
|
-
/**
|
|
441
|
-
* Builds the app.kv.* api. Resolves the KV namespace off the REQUEST-SUPPLIED env
|
|
442
|
-
* on every call — env is threaded, never stored (design §1a / SB4).
|
|
443
|
-
*
|
|
444
|
-
* @param ctx - The kv plugin context (own config + merged events).
|
|
445
|
-
* @returns The app.kv api: get / put / delete / list / deployManifest.
|
|
446
|
-
* @example
|
|
447
|
-
* ```typescript
|
|
448
|
-
* const api = createKvApi(ctx);
|
|
449
|
-
* const value = await api.get(env, "key");
|
|
450
|
-
* ```
|
|
451
|
-
*/
|
|
452
|
-
const createKvApi = (ctx) => {
|
|
453
|
-
const ns = (env) => ctx.require(bindingsPlugin).require(env, ctx.config.binding);
|
|
454
|
-
return {
|
|
455
|
-
/**
|
|
456
|
-
* Reads a value by key from the KV namespace. Returns null when absent.
|
|
457
|
-
*
|
|
458
|
-
* @param env - The per-request Cloudflare env (threaded, never stored).
|
|
459
|
-
* @param key - The key to read.
|
|
460
|
-
* @returns The stored value, or null when absent.
|
|
461
|
-
* @example
|
|
462
|
-
* ```typescript
|
|
463
|
-
* const value = await api.get(env, "feature-flags");
|
|
464
|
-
* ```
|
|
465
|
-
*/
|
|
466
|
-
get: async (env, key) => ns(env).get(key),
|
|
467
|
-
/**
|
|
468
|
-
* Writes a string value under a key, optionally with KV put options.
|
|
469
|
-
*
|
|
470
|
-
* @param env - The per-request Cloudflare env.
|
|
471
|
-
* @param key - The key to write.
|
|
472
|
-
* @param value - The string value to store.
|
|
473
|
-
* @param opts - Optional expiration / metadata.
|
|
474
|
-
* @returns Resolves once the write is acknowledged.
|
|
475
|
-
* @example
|
|
476
|
-
* ```typescript
|
|
477
|
-
* await api.put(env, "session:1", "data", { expirationTtl: 3600 });
|
|
478
|
-
* ```
|
|
479
|
-
*/
|
|
480
|
-
put: async (env, key, value, opts) => ns(env).put(key, value, opts),
|
|
481
|
-
/**
|
|
482
|
-
* Removes a key from the namespace (no-op if absent).
|
|
483
|
-
*
|
|
484
|
-
* @param env - The per-request Cloudflare env.
|
|
485
|
-
* @param key - The key to delete.
|
|
486
|
-
* @returns Resolves once the delete is acknowledged.
|
|
487
|
-
* @example
|
|
488
|
-
* ```typescript
|
|
489
|
-
* await api.delete(env, "session:expired");
|
|
490
|
-
* ```
|
|
491
|
-
*/
|
|
492
|
-
delete: async (env, key) => ns(env).delete(key),
|
|
493
|
-
/**
|
|
494
|
-
* Lists keys in the namespace, optionally filtered/paginated via opts.
|
|
495
|
-
*
|
|
496
|
-
* @param env - The per-request Cloudflare env.
|
|
497
|
-
* @param opts - Optional prefix / cursor / limit.
|
|
498
|
-
* @returns The list result from the KV namespace.
|
|
499
|
-
* @example
|
|
500
|
-
* ```typescript
|
|
501
|
-
* const { keys } = await api.list(env, { prefix: "session:" });
|
|
502
|
-
* ```
|
|
503
|
-
*/
|
|
504
|
-
list: async (env, opts) => ns(env).list(opts),
|
|
505
|
-
/**
|
|
506
|
-
* Returns this plugin's own deploy metadata, read by the deploy plugin via
|
|
507
|
-
* require (design §6 / F6). Build-time only — takes no env.
|
|
508
|
-
*
|
|
509
|
-
* @returns The kv deploy descriptor with kind literal and binding name.
|
|
510
|
-
* @example
|
|
511
|
-
* ```typescript
|
|
512
|
-
* const manifest = api.deployManifest(); // { kind: "kv", binding: "KV" }
|
|
513
|
-
* ```
|
|
514
|
-
*/
|
|
515
|
-
deployManifest: () => ({
|
|
516
|
-
kind: "kv",
|
|
517
|
-
binding: ctx.config.binding
|
|
518
|
-
})
|
|
519
|
-
};
|
|
520
|
-
};
|
|
521
|
-
/**
|
|
522
|
-
* Micro tier — thin env-first wrapper over a Cloudflare KV namespace.
|
|
523
|
-
*
|
|
524
|
-
* Resolves the KV namespace per request via `ctx.require(bindingsPlugin)`;
|
|
525
|
-
* never stores env in state (design §1a / SB4). No lifecycle hooks —
|
|
526
|
-
* request-scoped; nothing to open or close.
|
|
527
|
-
*
|
|
528
|
-
* @see README.md
|
|
529
|
-
*/
|
|
530
|
-
const kvPlugin = createPlugin("kv", {
|
|
531
|
-
depends: [bindingsPlugin],
|
|
532
|
-
config: { binding: "KV" },
|
|
533
|
-
api: createKvApi
|
|
534
|
-
});
|
|
535
|
-
//#endregion
|
|
536
|
-
//#region src/plugins/queues/api.ts
|
|
537
|
-
/**
|
|
538
|
-
* @file queues plugin — API factory (send, sendBatch, consume, deployManifest).
|
|
539
|
-
*
|
|
540
|
-
* All binding-resolving methods take the per-request `env` as the first argument
|
|
541
|
-
* and resolve the `Queue` via `ctx.require(bindingsPlugin).require<Queue>(env, name)`.
|
|
542
|
-
* The `env` is never stored (SB4 / design §1a) — resolved fresh on every call.
|
|
543
|
-
*/
|
|
544
|
-
/**
|
|
545
|
-
* Builds app.queues.* — read by worker.ts queue() delegation (design §1d; spec/02 §7).
|
|
546
|
-
*
|
|
547
|
-
* Resolves Queue bindings off the request env per call (never stored — SB4).
|
|
548
|
-
* Emits `queue:message` for observability after each consumed message (F8).
|
|
549
|
-
*
|
|
550
|
-
* @param ctx - Plugin context (own config + require + emit).
|
|
551
|
-
* @returns The queues API surface: send, sendBatch, consume, deployManifest.
|
|
552
|
-
* @example
|
|
553
|
-
* ```ts
|
|
554
|
-
* // Worker entry (design §1d)
|
|
555
|
-
* export default {
|
|
556
|
-
* queue: (b, e, c) => app.queues.consume(b, e, c),
|
|
557
|
-
* };
|
|
558
|
-
* ```
|
|
559
|
-
*/
|
|
560
|
-
const createQueuesApi = (ctx) => {
|
|
561
|
-
/**
|
|
562
|
-
* Resolves a named Queue binding from the per-request env.
|
|
563
|
-
* Throws a [moku-worker]-prefixed error when the binding is absent.
|
|
564
|
-
*
|
|
565
|
-
* @param env - Per-request Cloudflare bindings.
|
|
566
|
-
* @param name - Queue binding name.
|
|
567
|
-
* @returns The resolved Queue instance.
|
|
568
|
-
* @example
|
|
569
|
-
* ```ts
|
|
570
|
-
* const q = queue(env, "ORDERS");
|
|
571
|
-
* ```
|
|
572
|
-
*/
|
|
573
|
-
const queue = (env, name) => ctx.require(bindingsPlugin).require(env, name);
|
|
574
|
-
return {
|
|
575
|
-
/**
|
|
576
|
-
* Enqueue a single message onto the named queue.
|
|
577
|
-
*
|
|
578
|
-
* Resolves the Queue binding fresh from `env` on every call (SB4).
|
|
579
|
-
* Request/response work → api method, never emit (F8).
|
|
580
|
-
*
|
|
581
|
-
* @param env - Per-request Cloudflare bindings object.
|
|
582
|
-
* @param q - Target queue binding name in `env`.
|
|
583
|
-
* @param body - Message body to enqueue.
|
|
584
|
-
* @returns Resolves once the message is enqueued.
|
|
585
|
-
* @throws {Error} With a `[moku-worker]` prefix if the binding is missing.
|
|
586
|
-
* @example
|
|
587
|
-
* ```ts
|
|
588
|
-
* await app.queues.send(env, "ORDERS", { orderId: "123" });
|
|
589
|
-
* ```
|
|
590
|
-
*/
|
|
591
|
-
send: async (env, q, body) => {
|
|
592
|
-
await queue(env, q).send(body);
|
|
593
|
-
},
|
|
594
|
-
/**
|
|
595
|
-
* Enqueue many messages in one call; each element becomes one message.
|
|
596
|
-
*
|
|
597
|
-
* Maps each body to `{ body }` before calling `Queue.sendBatch` (design §4.3).
|
|
598
|
-
*
|
|
599
|
-
* @param env - Per-request Cloudflare bindings object.
|
|
600
|
-
* @param q - Target queue binding name in `env`.
|
|
601
|
-
* @param bodies - Array of message bodies; each becomes one message.
|
|
602
|
-
* @returns Resolves once all messages are enqueued.
|
|
603
|
-
* @throws {Error} With a `[moku-worker]` prefix if the binding is missing.
|
|
604
|
-
* @example
|
|
605
|
-
* ```ts
|
|
606
|
-
* await app.queues.sendBatch(env, "ORDERS", orders);
|
|
607
|
-
* ```
|
|
608
|
-
*/
|
|
609
|
-
sendBatch: async (env, q, bodies) => {
|
|
610
|
-
await queue(env, q).sendBatch(bodies.map((body) => ({ body })));
|
|
611
|
-
},
|
|
612
|
-
/**
|
|
613
|
-
* Consumer dispatch — the Worker's `queue()` export delegates here.
|
|
614
|
-
*
|
|
615
|
-
* Iterates `batch.messages`, **awaits** `config.onMessage(message, env)` per message
|
|
616
|
-
* (so Cloudflare gets a settled promise and the handler controls ack/retry; F8,
|
|
617
|
-
* spec/07 §3 — never emit for awaited work), then fire-and-forget emits `queue:message`
|
|
618
|
-
* for observability. Returns a promise the Worker **must** await so the isolate is not
|
|
619
|
-
* killed mid-batch.
|
|
620
|
-
*
|
|
621
|
-
* @param batch - The incoming message batch from Cloudflare.
|
|
622
|
-
* @param env - Per-request Cloudflare bindings object.
|
|
623
|
-
* @param _exec - waitUntil / passThroughOnException (reserved for future use).
|
|
624
|
-
* @returns Resolves after all messages in the batch are processed.
|
|
625
|
-
* @throws {Error} Re-throws any error from `config.onMessage` so Cloudflare can retry.
|
|
626
|
-
* @example
|
|
627
|
-
* ```ts
|
|
628
|
-
* // Worker entry
|
|
629
|
-
* queue: (b, e, c) => app.queues.consume(b, e, c),
|
|
630
|
-
* ```
|
|
631
|
-
*/
|
|
632
|
-
consume: async (batch, env, _exec) => {
|
|
633
|
-
for (const m of batch.messages) {
|
|
634
|
-
await ctx.config.onMessage(m, env);
|
|
635
|
-
ctx.emit("queue:message", {
|
|
636
|
-
queue: batch.queue,
|
|
637
|
-
messageId: m.id
|
|
638
|
-
});
|
|
639
|
-
}
|
|
640
|
-
},
|
|
641
|
-
/**
|
|
642
|
-
* Returns this plugin's deploy metadata, read by the deploy plugin via
|
|
643
|
-
* `ctx.require(queuesPlugin).deployManifest()` (F6 — never reads sibling config).
|
|
644
|
-
*
|
|
645
|
-
* @returns Deploy manifest entry `{ kind: "queue", producers }`.
|
|
646
|
-
* @example
|
|
647
|
-
* ```ts
|
|
648
|
-
* const manifest = ctx.require(queuesPlugin).deployManifest();
|
|
649
|
-
* // → { kind: "queue", producers: ["orders"] }
|
|
650
|
-
* ```
|
|
651
|
-
*/
|
|
652
|
-
deployManifest: () => ({
|
|
653
|
-
kind: "queue",
|
|
654
|
-
producers: ctx.config.producers
|
|
655
|
-
})
|
|
656
|
-
};
|
|
657
|
-
};
|
|
658
|
-
/**
|
|
659
|
-
* Standard tier — Cloudflare Queues producer + consumer dispatch.
|
|
660
|
-
*
|
|
661
|
-
* `events` is declared first and via `register.map<QueueEvents>` so the plugin's own events infer
|
|
662
|
-
* into the factory context; the api wiring is therefore arrow-wrapped (contextually typed).
|
|
663
|
-
*
|
|
664
|
-
* Emits the plugin-local `queue:message` event after each consumed message.
|
|
665
|
-
*
|
|
666
|
-
* @see README.md
|
|
667
|
-
*/
|
|
668
|
-
const queuesPlugin = createPlugin("queues", {
|
|
669
|
-
events: (register) => register.map({ "queue:message": "A queue message was processed" }),
|
|
670
|
-
depends: [bindingsPlugin],
|
|
671
|
-
config: {
|
|
672
|
-
producers: [],
|
|
673
|
-
onMessage: async () => {}
|
|
674
|
-
},
|
|
675
|
-
api: (ctx) => createQueuesApi(ctx)
|
|
676
|
-
});
|
|
677
|
-
//#endregion
|
|
678
|
-
//#region src/plugins/storage/providers/r2.ts
|
|
679
|
-
/**
|
|
680
|
-
* Build a StorageProvider backed by the real R2Bucket resolved off the
|
|
681
|
-
* per-request env via the bindings plugin. The bucket is resolved fresh on
|
|
682
|
-
* EVERY method call — never cached, so concurrent requests stay isolated
|
|
683
|
-
* (worker-api-design SB4; spec/08 §6).
|
|
684
|
-
*
|
|
685
|
-
* Each method is `async` so that synchronous throws from `bindings.require`
|
|
686
|
-
* (e.g. missing binding) are automatically wrapped in rejected Promises —
|
|
687
|
-
* callers can always use `await` / `.catch` instead of `try/catch`.
|
|
688
|
-
*
|
|
689
|
-
* @param bindings - The bindings plugin API (provides `require<T>`).
|
|
690
|
-
* @param env - The per-request Cloudflare bindings object.
|
|
691
|
-
* @param bucket - The R2 bucket binding name (e.g. "ASSETS").
|
|
692
|
-
* @returns {StorageProvider} A provider that delegates to the resolved R2Bucket.
|
|
693
|
-
* @example
|
|
694
|
-
* ```typescript
|
|
695
|
-
* const provider = resolveR2Provider(ctx.require(bindingsPlugin), env, ctx.config.bucket);
|
|
696
|
-
* const body = await provider.get("my-object");
|
|
697
|
-
* ```
|
|
698
|
-
*/
|
|
699
|
-
const resolveR2Provider = (bindings, env, bucket) => {
|
|
700
|
-
/**
|
|
701
|
-
* Resolve the R2Bucket for this request's env. Throws on missing binding.
|
|
702
|
-
*
|
|
703
|
-
* @returns {R2Bucket} The resolved R2Bucket binding.
|
|
704
|
-
* @example
|
|
705
|
-
* ```typescript
|
|
706
|
-
* const bucket = b();
|
|
707
|
-
* ```
|
|
708
|
-
*/
|
|
709
|
-
const b = () => bindings.require(env, bucket);
|
|
710
|
-
return {
|
|
711
|
-
/**
|
|
712
|
-
* Read an object from the bucket.
|
|
713
|
-
*
|
|
714
|
-
* @param key - The object key.
|
|
715
|
-
* @returns {Promise<R2ObjectBody | null>} The R2ObjectBody, or null if the key is absent.
|
|
716
|
-
* @example
|
|
717
|
-
* ```typescript
|
|
718
|
-
* const body = await provider.get("assets/logo.png");
|
|
719
|
-
* ```
|
|
720
|
-
*/
|
|
721
|
-
async get(key) {
|
|
722
|
-
return b().get(key);
|
|
723
|
-
},
|
|
724
|
-
/**
|
|
725
|
-
* Write an object to the bucket.
|
|
726
|
-
*
|
|
727
|
-
* @param key - The object key.
|
|
728
|
-
* @param value - The object contents (any R2-accepted type).
|
|
729
|
-
* @returns {Promise<R2Object>} The R2Object metadata for the written object.
|
|
730
|
-
* @example
|
|
731
|
-
* ```typescript
|
|
732
|
-
* const obj = await provider.put("assets/logo.png", buffer);
|
|
733
|
-
* ```
|
|
734
|
-
*/
|
|
735
|
-
async put(key, value) {
|
|
736
|
-
return b().put(key, value);
|
|
737
|
-
},
|
|
738
|
-
/**
|
|
739
|
-
* Remove one or more objects from the bucket. No-op when a key is absent.
|
|
740
|
-
*
|
|
741
|
-
* @param key - A single key or array of keys to remove.
|
|
742
|
-
* @returns {Promise<void>} Resolves once removed.
|
|
743
|
-
* @example
|
|
744
|
-
* ```typescript
|
|
745
|
-
* await provider.delete("assets/old.png");
|
|
746
|
-
* ```
|
|
747
|
-
*/
|
|
748
|
-
async delete(key) {
|
|
749
|
-
return b().delete(key);
|
|
750
|
-
},
|
|
751
|
-
/**
|
|
752
|
-
* List objects, optionally filtered by R2ListOptions.
|
|
753
|
-
*
|
|
754
|
-
* @param opts - Optional list options (prefix, limit, cursor, delimiter).
|
|
755
|
-
* @returns {Promise<R2Objects>} The R2Objects list result.
|
|
756
|
-
* @example
|
|
757
|
-
* ```typescript
|
|
758
|
-
* const { objects } = await provider.list({ prefix: "images/" });
|
|
759
|
-
* ```
|
|
760
|
-
*/
|
|
761
|
-
async list(opts) {
|
|
762
|
-
return b().list(opts);
|
|
763
|
-
}
|
|
764
|
-
};
|
|
765
|
-
};
|
|
766
|
-
//#endregion
|
|
767
|
-
//#region src/plugins/storage/api.ts
|
|
768
|
-
/**
|
|
769
|
-
* Build the env-first storage API. Each runtime method resolves the bucket
|
|
770
|
-
* provider fresh from the per-request `env` — nothing is stored, so concurrent
|
|
771
|
-
* requests stay isolated (worker-api-design SB4; spec/08 §6,§7).
|
|
772
|
-
*
|
|
773
|
-
* The `deployManifest()` method is build-time only: it reads from `ctx.config`
|
|
774
|
-
* and never touches `env` or R2.
|
|
775
|
-
*
|
|
776
|
-
* @param ctx - Plugin context (config + require for bindings resolution).
|
|
777
|
-
* @returns {StorageApi} The env-first storage API surface.
|
|
778
|
-
* @example
|
|
779
|
-
* ```typescript
|
|
780
|
-
* const api = createStorageApi(ctx);
|
|
781
|
-
* const body = await api.get(env, "my-object");
|
|
782
|
-
* ```
|
|
783
|
-
*/
|
|
784
|
-
const createStorageApi = (ctx) => {
|
|
785
|
-
/**
|
|
786
|
-
* Resolve the StorageProvider for the given per-request env. Called on every
|
|
787
|
-
* method invocation — the bucket binding is never cached across calls.
|
|
788
|
-
*
|
|
789
|
-
* @param env - The per-request Cloudflare bindings object.
|
|
790
|
-
* @returns {StorageProvider} A StorageProvider delegating to the resolved R2Bucket.
|
|
791
|
-
* @example
|
|
792
|
-
* ```typescript
|
|
793
|
-
* const p = provider(env);
|
|
794
|
-
* const body = await p.get("key");
|
|
795
|
-
* ```
|
|
796
|
-
*/
|
|
797
|
-
const provider = (env) => resolveR2Provider(ctx.require(bindingsPlugin), env, ctx.config.bucket);
|
|
798
|
-
return {
|
|
799
|
-
/**
|
|
800
|
-
* Read an object from the bucket; resolves null when the key is absent.
|
|
801
|
-
*
|
|
802
|
-
* @param env - Per-request Cloudflare bindings.
|
|
803
|
-
* @param key - Object key.
|
|
804
|
-
* @returns {Promise<R2ObjectBody | null>} The R2ObjectBody, or null.
|
|
805
|
-
* @example
|
|
806
|
-
* ```typescript
|
|
807
|
-
* const body = await api.get(env, "assets/logo.png");
|
|
808
|
-
* ```
|
|
809
|
-
*/
|
|
810
|
-
get: (env, key) => provider(env).get(key),
|
|
811
|
-
/**
|
|
812
|
-
* Write an object to the bucket.
|
|
813
|
-
*
|
|
814
|
-
* @param env - Per-request Cloudflare bindings.
|
|
815
|
-
* @param key - Object key.
|
|
816
|
-
* @param value - Object contents (ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob | null).
|
|
817
|
-
* @returns {Promise<R2Object>} The R2Object metadata for the written object.
|
|
818
|
-
* @example
|
|
819
|
-
* ```typescript
|
|
820
|
-
* const obj = await api.put(env, "assets/logo.png", buffer);
|
|
821
|
-
* ```
|
|
822
|
-
*/
|
|
823
|
-
put: (env, key, value) => provider(env).put(key, value),
|
|
824
|
-
/**
|
|
825
|
-
* Remove an object (or array of keys) from the bucket. No-op when absent.
|
|
826
|
-
*
|
|
827
|
-
* @param env - Per-request Cloudflare bindings.
|
|
828
|
-
* @param key - Object key or array of keys.
|
|
829
|
-
* @returns {Promise<void>} Resolves once removed.
|
|
830
|
-
* @example
|
|
831
|
-
* ```typescript
|
|
832
|
-
* await api.delete(env, "assets/old.png");
|
|
833
|
-
* ```
|
|
834
|
-
*/
|
|
835
|
-
delete: (env, key) => provider(env).delete(key),
|
|
836
|
-
/**
|
|
837
|
-
* List objects, optionally filtered by R2ListOptions.
|
|
838
|
-
*
|
|
839
|
-
* @param env - Per-request Cloudflare bindings.
|
|
840
|
-
* @param opts - Optional R2ListOptions (prefix, limit, cursor, delimiter).
|
|
841
|
-
* @returns {Promise<R2Objects>} The R2Objects list result.
|
|
842
|
-
* @example
|
|
843
|
-
* ```typescript
|
|
844
|
-
* const { objects } = await api.list(env, { prefix: "images/" });
|
|
845
|
-
* ```
|
|
846
|
-
*/
|
|
847
|
-
list: (env, opts) => provider(env).list(opts),
|
|
848
|
-
/**
|
|
849
|
-
* Return this plugin's deploy metadata. Build-time only — does not touch
|
|
850
|
-
* `env` or R2. The deploy plugin reads this via `ctx.require(storagePlugin).deployManifest()`.
|
|
851
|
-
*
|
|
852
|
-
* @returns {StorageManifest} Deploy manifest entry `{ kind: "r2", bucket, upload }`.
|
|
853
|
-
* @example
|
|
854
|
-
* ```typescript
|
|
855
|
-
* const manifest = api.deployManifest();
|
|
856
|
-
* // { kind: "r2", bucket: "ASSETS", upload: "./public" }
|
|
857
|
-
* ```
|
|
858
|
-
*/
|
|
859
|
-
deployManifest: () => ({
|
|
860
|
-
kind: "r2",
|
|
861
|
-
bucket: ctx.config.bucket,
|
|
862
|
-
upload: ctx.config.upload
|
|
863
|
-
})
|
|
864
|
-
};
|
|
865
|
-
};
|
|
866
|
-
/**
|
|
867
|
-
* Complex tier — Cloudflare R2 object storage behind a provider adapter seam.
|
|
868
|
-
*
|
|
869
|
-
* Exposes `get`, `put`, `delete`, `list` (all env-first) and `deployManifest()`
|
|
870
|
-
* (build-time). Depends on `bindingsPlugin` to resolve the `R2Bucket` binding
|
|
871
|
-
* per request. No state, no events, no lifecycle hooks.
|
|
872
|
-
*
|
|
873
|
-
* @see README.md
|
|
874
|
-
*/
|
|
875
|
-
const storagePlugin = createPlugin("storage", {
|
|
876
|
-
depends: [bindingsPlugin],
|
|
877
|
-
config: {
|
|
878
|
-
upload: "",
|
|
879
|
-
bucket: "ASSETS"
|
|
880
|
-
},
|
|
881
|
-
api: createStorageApi
|
|
882
|
-
});
|
|
883
|
-
//#endregion
|
|
884
|
-
Object.defineProperty(exports, "bindingsPlugin", {
|
|
885
|
-
enumerable: true,
|
|
886
|
-
get: function() {
|
|
887
|
-
return bindingsPlugin;
|
|
888
|
-
}
|
|
889
|
-
});
|
|
890
|
-
Object.defineProperty(exports, "coreConfig", {
|
|
891
|
-
enumerable: true,
|
|
892
|
-
get: function() {
|
|
893
|
-
return coreConfig;
|
|
894
|
-
}
|
|
895
|
-
});
|
|
896
|
-
Object.defineProperty(exports, "createCore", {
|
|
897
|
-
enumerable: true,
|
|
898
|
-
get: function() {
|
|
899
|
-
return createCore;
|
|
900
|
-
}
|
|
901
|
-
});
|
|
902
|
-
Object.defineProperty(exports, "createPlugin", {
|
|
903
|
-
enumerable: true,
|
|
904
|
-
get: function() {
|
|
905
|
-
return createPlugin;
|
|
906
|
-
}
|
|
907
|
-
});
|
|
908
|
-
Object.defineProperty(exports, "d1Plugin", {
|
|
909
|
-
enumerable: true,
|
|
910
|
-
get: function() {
|
|
911
|
-
return d1Plugin;
|
|
912
|
-
}
|
|
913
|
-
});
|
|
914
|
-
Object.defineProperty(exports, "defineDurableObject", {
|
|
915
|
-
enumerable: true,
|
|
916
|
-
get: function() {
|
|
917
|
-
return defineDurableObject;
|
|
918
|
-
}
|
|
919
|
-
});
|
|
920
|
-
Object.defineProperty(exports, "durableObjectsPlugin", {
|
|
921
|
-
enumerable: true,
|
|
922
|
-
get: function() {
|
|
923
|
-
return durableObjectsPlugin;
|
|
924
|
-
}
|
|
925
|
-
});
|
|
926
|
-
Object.defineProperty(exports, "kvPlugin", {
|
|
927
|
-
enumerable: true,
|
|
928
|
-
get: function() {
|
|
929
|
-
return kvPlugin;
|
|
930
|
-
}
|
|
931
|
-
});
|
|
932
|
-
Object.defineProperty(exports, "queuesPlugin", {
|
|
933
|
-
enumerable: true,
|
|
934
|
-
get: function() {
|
|
935
|
-
return queuesPlugin;
|
|
936
|
-
}
|
|
937
|
-
});
|
|
938
|
-
Object.defineProperty(exports, "stagePlugin", {
|
|
939
|
-
enumerable: true,
|
|
940
|
-
get: function() {
|
|
941
|
-
return stagePlugin;
|
|
942
|
-
}
|
|
943
|
-
});
|
|
944
|
-
Object.defineProperty(exports, "storagePlugin", {
|
|
945
|
-
enumerable: true,
|
|
946
|
-
get: function() {
|
|
947
|
-
return storagePlugin;
|
|
948
|
-
}
|
|
949
|
-
});
|