alchemy 2.0.0-beta.35 → 2.0.0-beta.36
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/bin/exec.js +27 -0
- package/bin/exec.js.map +1 -1
- package/lib/Cli/main.d.ts.map +1 -1
- package/lib/Cli/main.js +2 -0
- package/lib/Cli/main.js.map +1 -1
- package/lib/Cloudflare/Images/Images.d.ts +103 -0
- package/lib/Cloudflare/Images/Images.d.ts.map +1 -0
- package/lib/Cloudflare/Images/Images.js +82 -0
- package/lib/Cloudflare/Images/Images.js.map +1 -0
- package/lib/Cloudflare/Images/ImagesBinding.d.ts +73 -0
- package/lib/Cloudflare/Images/ImagesBinding.d.ts.map +1 -0
- package/lib/Cloudflare/Images/ImagesBinding.js +83 -0
- package/lib/Cloudflare/Images/ImagesBinding.js.map +1 -0
- package/lib/Cloudflare/Images/index.d.ts +3 -0
- package/lib/Cloudflare/Images/index.d.ts.map +1 -0
- package/lib/Cloudflare/Images/index.js +3 -0
- package/lib/Cloudflare/Images/index.js.map +1 -0
- package/lib/Cloudflare/Providers.d.ts.map +1 -1
- package/lib/Cloudflare/Providers.js +3 -1
- package/lib/Cloudflare/Providers.js.map +1 -1
- package/lib/Cloudflare/R2/R2Bucket.d.ts +135 -0
- package/lib/Cloudflare/R2/R2Bucket.d.ts.map +1 -1
- package/lib/Cloudflare/R2/R2Bucket.js +130 -7
- package/lib/Cloudflare/R2/R2Bucket.js.map +1 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts +1 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.d.ts +5 -5
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +34 -23
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/index.d.ts +1 -0
- package/lib/Cloudflare/index.d.ts.map +1 -1
- package/lib/Cloudflare/index.js +1 -0
- package/lib/Cloudflare/index.js.map +1 -1
- package/lib/Test/Vitest.d.ts.map +1 -1
- package/lib/Test/Vitest.js +2 -0
- package/lib/Test/Vitest.js.map +1 -1
- package/lib/Util/LocalhostDns.d.ts +19 -0
- package/lib/Util/LocalhostDns.d.ts.map +1 -0
- package/lib/Util/LocalhostDns.js +55 -0
- package/lib/Util/LocalhostDns.js.map +1 -0
- package/lib/Util/PlatformServices.d.ts.map +1 -1
- package/lib/Util/PlatformServices.js +2 -0
- package/lib/Util/PlatformServices.js.map +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/src/Cli/main.ts +3 -0
- package/src/Cloudflare/Images/Images.ts +121 -0
- package/src/Cloudflare/Images/ImagesBinding.ts +192 -0
- package/src/Cloudflare/Images/index.ts +2 -0
- package/src/Cloudflare/Providers.ts +3 -0
- package/src/Cloudflare/R2/R2Bucket.ts +240 -7
- package/src/Cloudflare/Workers/InferEnv.ts +7 -3
- package/src/Cloudflare/Workers/Worker.ts +47 -28
- package/src/Cloudflare/index.ts +1 -0
- package/src/Test/Vitest.ts +3 -0
- package/src/Util/LocalhostDns.ts +58 -0
- package/src/Util/PlatformServices.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.36",
|
|
4
4
|
"homepage": "https://alchemy.run",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Sam Goodwin <sam@alchemy.run>",
|
|
@@ -309,6 +309,7 @@
|
|
|
309
309
|
"react": "^19.2.0",
|
|
310
310
|
"rolldown": "1.0.0-rc.17",
|
|
311
311
|
"sonda": "^0.11.1",
|
|
312
|
+
"undici": "^7.16.0",
|
|
312
313
|
"web-tree-sitter": "0.25.10",
|
|
313
314
|
"yaml": "^2.0.0"
|
|
314
315
|
},
|
package/src/Cli/main.ts
CHANGED
|
@@ -8,9 +8,12 @@ import { AlchemyContextLive } from "alchemy/AlchemyContext";
|
|
|
8
8
|
import { CredentialsStoreLive } from "alchemy/Auth/Credentials";
|
|
9
9
|
import { ProfileLive } from "alchemy/Auth/Profile";
|
|
10
10
|
import { TelemetryLive } from "alchemy/Telemetry/Layer";
|
|
11
|
+
import { installLocalhostDns } from "alchemy/Util/LocalhostDns";
|
|
11
12
|
import { PlatformServices } from "alchemy/Util/PlatformServices";
|
|
12
13
|
import packageJson from "../../package.json" with { type: "json" };
|
|
13
14
|
|
|
15
|
+
installLocalhostDns();
|
|
16
|
+
|
|
14
17
|
import { checkLatestVersion } from "./checkVersion.ts";
|
|
15
18
|
import { handleCancellation } from "./commands/_shared.ts";
|
|
16
19
|
import { awsCommand } from "./commands/aws.ts";
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { ImagesBinding } from "./ImagesBinding.ts";
|
|
3
|
+
|
|
4
|
+
type ImagesTypeId = typeof ImagesTypeId;
|
|
5
|
+
const ImagesTypeId = "Cloudflare.Images" as const;
|
|
6
|
+
|
|
7
|
+
export type ImagesProps = {
|
|
8
|
+
/**
|
|
9
|
+
* Binding name used when `Cloudflare.Images.bind(images)` attaches Images
|
|
10
|
+
* from inside a Worker init phase. When Images is passed through
|
|
11
|
+
* `Worker({ bindings: { ... } })`, the object key remains the binding name.
|
|
12
|
+
*
|
|
13
|
+
* @default "IMAGES"
|
|
14
|
+
*/
|
|
15
|
+
name?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Marker for a Cloudflare Images binding.
|
|
20
|
+
*
|
|
21
|
+
* Images bindings are configured directly on Workers and do not have a
|
|
22
|
+
* standalone provisioning API. The Worker provider sees this object in
|
|
23
|
+
* `bindings: { ... }` and emits the corresponding `{ type: "images" }`
|
|
24
|
+
* metadata binding to the script.
|
|
25
|
+
*/
|
|
26
|
+
export type Images = {
|
|
27
|
+
kind: ImagesTypeId;
|
|
28
|
+
name: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const isImages = (value: unknown): value is Images =>
|
|
32
|
+
typeof value === "object" &&
|
|
33
|
+
value !== null &&
|
|
34
|
+
"kind" in value &&
|
|
35
|
+
(value as Images).kind === ImagesTypeId;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A Cloudflare Images binding for image transformation and manipulation inside
|
|
39
|
+
* Workers.
|
|
40
|
+
*
|
|
41
|
+
* The Effect-native interface (`Cloudflare.Images.bind(...)`) returns an
|
|
42
|
+
* `ImagesClient` whose methods take Effect `Stream.Stream<Uint8Array>`
|
|
43
|
+
* inputs and return `Effect`s — `info`, `input(...).transform(...)
|
|
44
|
+
* .draw(...).output(...)`. The runtime conversion to Cloudflare's
|
|
45
|
+
* `ReadableStream` is handled internally.
|
|
46
|
+
*
|
|
47
|
+
* @section Declaring Images
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const Pipeline = yield* Cloudflare.Images({ name: "PIPELINE" });
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @section Effect-style Worker (recommended)
|
|
54
|
+
* @example Read image format and dimensions from the request body
|
|
55
|
+
* ```typescript
|
|
56
|
+
* import { HttpServerRequest } from "effect/unstable/http/HttpServerRequest";
|
|
57
|
+
*
|
|
58
|
+
* Cloudflare.Worker("ImageWorker", { main: import.meta.filename },
|
|
59
|
+
* Effect.gen(function* () {
|
|
60
|
+
* const pipeline = yield* Pipeline;
|
|
61
|
+
* const images = yield* Cloudflare.Images.bind(pipeline);
|
|
62
|
+
* return {
|
|
63
|
+
* fetch: Effect.gen(function* () {
|
|
64
|
+
* const request = yield* HttpServerRequest;
|
|
65
|
+
* // request.stream is Stream.Stream<Uint8Array>
|
|
66
|
+
* const info = yield* images.info(request.stream);
|
|
67
|
+
* return yield* HttpServerResponse.json(info);
|
|
68
|
+
* }),
|
|
69
|
+
* };
|
|
70
|
+
* }).pipe(Effect.provide(Cloudflare.ImagesBindingLive)),
|
|
71
|
+
* );
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @example Transform an image — chainable pipeline, single Effect at the end
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const result = yield* (yield* images.input(request.stream))
|
|
77
|
+
* .transform({ width: 128 })
|
|
78
|
+
* .output({ format: "image/jpeg" });
|
|
79
|
+
*
|
|
80
|
+
* const response = yield* result.response;
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @section Binding to a Worker (declarative)
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* export const Worker = Cloudflare.Worker("Worker", {
|
|
87
|
+
* main: "./src/worker.ts",
|
|
88
|
+
* bindings: { MEDIA: Pipeline },
|
|
89
|
+
* });
|
|
90
|
+
*
|
|
91
|
+
* export type WorkerEnv = Cloudflare.InferEnv<typeof Worker>;
|
|
92
|
+
* // { MEDIA: ImagesBinding }
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* Inside the Worker, the raw Cloudflare runtime binding is reachable via
|
|
96
|
+
* `client.raw` if you need to call `info()` / `input()` directly with
|
|
97
|
+
* `async`/`await`. The Effect-native interface is preferred — it returns
|
|
98
|
+
* tagged `ImagesError`s, threads `WorkerEnvironment`, and lets you stream
|
|
99
|
+
* Effect `Stream<Uint8Array>` sources without manual conversion.
|
|
100
|
+
*
|
|
101
|
+
* @see https://developers.cloudflare.com/images/transform-images/bindings/
|
|
102
|
+
*/
|
|
103
|
+
export const Images: {
|
|
104
|
+
(props?: ImagesProps): Effect.Effect<Images>;
|
|
105
|
+
/**
|
|
106
|
+
* Bind Cloudflare Images to the surrounding Worker, returning an
|
|
107
|
+
* Effect-native client with access to the native Workers runtime binding.
|
|
108
|
+
*/
|
|
109
|
+
bind: typeof ImagesBinding.bind;
|
|
110
|
+
} = Object.assign(
|
|
111
|
+
Effect.fn(function* (props?: ImagesProps) {
|
|
112
|
+
return {
|
|
113
|
+
kind: ImagesTypeId,
|
|
114
|
+
name: props?.name ?? "IMAGES",
|
|
115
|
+
} satisfies Images;
|
|
116
|
+
}),
|
|
117
|
+
{
|
|
118
|
+
bind: (...args: Parameters<typeof ImagesBinding.bind>) =>
|
|
119
|
+
ImagesBinding.bind(...args),
|
|
120
|
+
},
|
|
121
|
+
);
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type * as cf from "@cloudflare/workers-types";
|
|
2
|
+
import * as Data from "effect/Data";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import * as Stream from "effect/Stream";
|
|
6
|
+
import * as Binding from "../../Binding.ts";
|
|
7
|
+
import type { ResourceLike } from "../../Resource.ts";
|
|
8
|
+
import { isWorker, WorkerEnvironment } from "../Workers/Worker.ts";
|
|
9
|
+
import { type Images as ImagesLike } from "./Images.ts";
|
|
10
|
+
|
|
11
|
+
export class ImagesError extends Data.TaggedError("ImagesError")<{
|
|
12
|
+
message: string;
|
|
13
|
+
code?: number;
|
|
14
|
+
cause: unknown;
|
|
15
|
+
}> {}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Effect-native handle to the result of `input(...).output(...)`.
|
|
19
|
+
* Mirrors the runtime `ImageTransformationResult` but exposes side
|
|
20
|
+
* effects (response/image/contentType reads) as plain sync effects.
|
|
21
|
+
*/
|
|
22
|
+
export interface ImageTransformationResultClient {
|
|
23
|
+
raw: cf.ImageTransformationResult;
|
|
24
|
+
response: Effect.Effect<cf.Response>;
|
|
25
|
+
contentType: Effect.Effect<string>;
|
|
26
|
+
image(
|
|
27
|
+
options?: cf.ImageTransformationOutputOptions,
|
|
28
|
+
): Effect.Effect<cf.ReadableStream<Uint8Array>>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Effect-native chainable transformer. `transform`/`draw` are pure
|
|
33
|
+
* (return a new client wrapping the next runtime transformer);
|
|
34
|
+
* `output` is the only step that crosses into Cloudflare's runtime
|
|
35
|
+
* and therefore returns an Effect.
|
|
36
|
+
*/
|
|
37
|
+
export interface ImageTransformerClient {
|
|
38
|
+
raw: cf.ImageTransformer;
|
|
39
|
+
transform(transform: cf.ImageTransform): ImageTransformerClient;
|
|
40
|
+
draw<E = never, R = never>(
|
|
41
|
+
image: Stream.Stream<Uint8Array, E, R> | ImageTransformerClient,
|
|
42
|
+
options?: cf.ImageDrawOptions,
|
|
43
|
+
): Effect.Effect<ImageTransformerClient, never, R>;
|
|
44
|
+
output(
|
|
45
|
+
options: cf.ImageOutputOptions,
|
|
46
|
+
): Effect.Effect<ImageTransformationResultClient, ImagesError>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Effect-native client for a Cloudflare Images binding.
|
|
51
|
+
*
|
|
52
|
+
* Wraps the runtime {@link cf.ImagesBinding} so each method returns
|
|
53
|
+
* an Effect tagged with {@link ImagesError}. Use
|
|
54
|
+
* `Cloudflare.Images.bind(images)` inside a Worker's init phase.
|
|
55
|
+
*/
|
|
56
|
+
export interface ImagesClient {
|
|
57
|
+
/** Effect resolving to the raw Cloudflare runtime binding. */
|
|
58
|
+
raw: Effect.Effect<cf.ImagesBinding, never, WorkerEnvironment>;
|
|
59
|
+
/**
|
|
60
|
+
* Read image format and dimensions from a stream of bytes.
|
|
61
|
+
* Fails with {@link ImagesError} (code 9412) if the input is not
|
|
62
|
+
* a recognized image.
|
|
63
|
+
*/
|
|
64
|
+
info<E = never, R = never>(
|
|
65
|
+
stream: Stream.Stream<Uint8Array, E, R>,
|
|
66
|
+
options?: cf.ImageInputOptions,
|
|
67
|
+
): Effect.Effect<cf.ImageInfoResponse, ImagesError, WorkerEnvironment | R>;
|
|
68
|
+
/**
|
|
69
|
+
* Begin a transformation pipeline. Subsequent `.transform()` /
|
|
70
|
+
* `.draw()` calls are pure; `.output(opts)` runs the pipeline.
|
|
71
|
+
*/
|
|
72
|
+
input<E = never, R = never>(
|
|
73
|
+
stream: Stream.Stream<Uint8Array, E, R>,
|
|
74
|
+
options?: cf.ImageInputOptions,
|
|
75
|
+
): Effect.Effect<ImageTransformerClient, never, WorkerEnvironment | R>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export class ImagesBinding extends Binding.Service<
|
|
79
|
+
ImagesBinding,
|
|
80
|
+
(images: ImagesLike) => Effect.Effect<ImagesClient>
|
|
81
|
+
>()("Cloudflare.Images.Binding") {}
|
|
82
|
+
|
|
83
|
+
export const ImagesBindingLive = Layer.effect(
|
|
84
|
+
ImagesBinding,
|
|
85
|
+
Effect.gen(function* () {
|
|
86
|
+
const Policy = yield* ImagesBindingPolicy;
|
|
87
|
+
|
|
88
|
+
return Effect.fn(function* (images: ImagesLike) {
|
|
89
|
+
yield* Policy(images);
|
|
90
|
+
const env = WorkerEnvironment.asEffect();
|
|
91
|
+
const raw = env.pipe(
|
|
92
|
+
Effect.map(
|
|
93
|
+
(env) => (env as Record<string, cf.ImagesBinding>)[images.name]!,
|
|
94
|
+
),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
raw,
|
|
99
|
+
info: (stream, options) =>
|
|
100
|
+
Effect.gen(function* () {
|
|
101
|
+
const binding = yield* raw;
|
|
102
|
+
const readable = yield* toCfReadable(stream);
|
|
103
|
+
return yield* tryPromise(() => binding.info(readable, options));
|
|
104
|
+
}),
|
|
105
|
+
input: (stream, options) =>
|
|
106
|
+
Effect.gen(function* () {
|
|
107
|
+
const binding = yield* raw;
|
|
108
|
+
const readable = yield* toCfReadable(stream);
|
|
109
|
+
return wrapTransformer(binding.input(readable, options));
|
|
110
|
+
}),
|
|
111
|
+
} satisfies ImagesClient;
|
|
112
|
+
});
|
|
113
|
+
}),
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
export class ImagesBindingPolicy extends Binding.Policy<
|
|
117
|
+
ImagesBindingPolicy,
|
|
118
|
+
(images: ImagesLike) => Effect.Effect<void>
|
|
119
|
+
>()("Cloudflare.Images.Binding") {}
|
|
120
|
+
|
|
121
|
+
export const ImagesBindingPolicyLive = ImagesBindingPolicy.layer.succeed(
|
|
122
|
+
Effect.fn(function* (host: ResourceLike, images: ImagesLike) {
|
|
123
|
+
if (isWorker(host)) {
|
|
124
|
+
yield* host.bind(images.name, {
|
|
125
|
+
bindings: [
|
|
126
|
+
{
|
|
127
|
+
type: "images",
|
|
128
|
+
name: images.name,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
});
|
|
132
|
+
} else {
|
|
133
|
+
return yield* Effect.die(
|
|
134
|
+
new Error(`ImagesBinding does not support runtime '${host.Type}'`),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const tryPromise = <T>(fn: () => Promise<T>): Effect.Effect<T, ImagesError> =>
|
|
141
|
+
Effect.tryPromise({
|
|
142
|
+
try: fn,
|
|
143
|
+
catch: (error: any) =>
|
|
144
|
+
new ImagesError({
|
|
145
|
+
message: error?.message ?? "Unknown error",
|
|
146
|
+
code: typeof error?.code === "number" ? error.code : undefined,
|
|
147
|
+
cause: error,
|
|
148
|
+
}),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Convert an Effect `Stream<Uint8Array>` into the `cf.ReadableStream<Uint8Array>`
|
|
153
|
+
* shape that the Cloudflare Images runtime binding expects. The two
|
|
154
|
+
* `ReadableStream` types only differ at the type level; at runtime they
|
|
155
|
+
* are the same Web Streams API.
|
|
156
|
+
*/
|
|
157
|
+
const toCfReadable = <E, R>(
|
|
158
|
+
stream: Stream.Stream<Uint8Array, E, R>,
|
|
159
|
+
): Effect.Effect<cf.ReadableStream<Uint8Array>, never, R> =>
|
|
160
|
+
Stream.toReadableStreamEffect(stream).pipe(
|
|
161
|
+
Effect.map((s) => s as unknown as cf.ReadableStream<Uint8Array>),
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const isTransformerClient = (image: unknown): image is ImageTransformerClient =>
|
|
165
|
+
typeof image === "object" && image !== null && "raw" in image;
|
|
166
|
+
|
|
167
|
+
const wrapTransformer = (raw: cf.ImageTransformer): ImageTransformerClient => ({
|
|
168
|
+
raw,
|
|
169
|
+
transform: (transform) => wrapTransformer(raw.transform(transform)),
|
|
170
|
+
draw: <E, R>(
|
|
171
|
+
image: Stream.Stream<Uint8Array, E, R> | ImageTransformerClient,
|
|
172
|
+
options?: cf.ImageDrawOptions,
|
|
173
|
+
): Effect.Effect<ImageTransformerClient, never, R> => {
|
|
174
|
+
if (isTransformerClient(image)) {
|
|
175
|
+
return Effect.succeed(wrapTransformer(raw.draw(image.raw, options)));
|
|
176
|
+
}
|
|
177
|
+
return toCfReadable(image).pipe(
|
|
178
|
+
Effect.map((readable) => wrapTransformer(raw.draw(readable, options))),
|
|
179
|
+
);
|
|
180
|
+
},
|
|
181
|
+
output: (options) =>
|
|
182
|
+
tryPromise(() => raw.output(options)).pipe(Effect.map(wrapResult)),
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const wrapResult = (
|
|
186
|
+
raw: cf.ImageTransformationResult,
|
|
187
|
+
): ImageTransformationResultClient => ({
|
|
188
|
+
raw,
|
|
189
|
+
response: Effect.sync(() => raw.response()),
|
|
190
|
+
contentType: Effect.sync(() => raw.contentType()),
|
|
191
|
+
image: (options) => Effect.sync(() => raw.image(options)),
|
|
192
|
+
});
|
|
@@ -21,6 +21,7 @@ import * as Containers from "./Container/index.ts";
|
|
|
21
21
|
import * as Credentials from "./Credentials.ts";
|
|
22
22
|
import * as D1 from "./D1/index.ts";
|
|
23
23
|
import * as Hyperdrive from "./Hyperdrive/index.ts";
|
|
24
|
+
import * as Images from "./Images/index.ts";
|
|
24
25
|
import * as KV from "./KV/index.ts";
|
|
25
26
|
import * as Queue from "./Queue/index.ts";
|
|
26
27
|
import * as R2 from "./R2/index.ts";
|
|
@@ -56,6 +57,7 @@ export const providers = () =>
|
|
|
56
57
|
D1.D1Database,
|
|
57
58
|
Hyperdrive.Hyperdrive,
|
|
58
59
|
Hyperdrive.HyperdriveBindingPolicy,
|
|
60
|
+
Images.ImagesBindingPolicy,
|
|
59
61
|
KV.KVNamespace,
|
|
60
62
|
KV.KVNamespaceBindingPolicy,
|
|
61
63
|
Queue.Queue,
|
|
@@ -88,6 +90,7 @@ export const providers = () =>
|
|
|
88
90
|
D1.DatabaseProvider(),
|
|
89
91
|
Hyperdrive.HyperdriveBindingPolicyLive,
|
|
90
92
|
Hyperdrive.HyperdriveProvider(),
|
|
93
|
+
Images.ImagesBindingPolicyLive,
|
|
91
94
|
KV.KVNamespaceBindingPolicyLive,
|
|
92
95
|
KV.KVNamespaceProvider(),
|
|
93
96
|
Queue.QueueBindingPolicyLive,
|