1import * as Cloudflare from "@/Cloudflare/index.ts";
2import * as Test from "@/Test/Alchemy";
3import * as Effect from "effect/Effect";
4import { expectUrlContains } from "../Utils/Http.ts";
5
6const { test } = Test.make({ providers: Cloudflare.providers() });
7
8const script = `export default {
9 async fetch(request, env) {
10 await env.KV.put("ref-binding-key", "bound-through-ref");
11 const value = await env.KV.get("ref-binding-key");
12 return new Response(value ?? "missing");
13 },
14};`;
15
16/**
17 * A `Resource.ref(...)` in a Worker's `env` must produce the native
18 * binding, exactly like a locally-declared resource. A ref used to
19 * silently degrade to a plain JSON env var: the worker deployed
20 * "successfully" and `env.KV.put` blew up at runtime — so the live KV
21 * roundtrip through the deployed worker is the airtight assertion.
22 */
23test.provider(
24 "a KV namespace ref in worker env produces a working native binding",
25 (stack) =>
26 Effect.gen(function* () {
27 yield* stack.destroy();
28
29 // Phase 1: the target must already be in state for the ref to
30 // resolve (a ghost ref fails the plan).
31 yield* stack.deploy(
32 Effect.gen(function* () {
33 return yield* Cloudflare.KV.Namespace("RefNamespace");
34 }),
35 );
36
37 // Phase 2: bind the namespace via `Namespace.ref(...)` and prove
38 // the binding works end-to-end.
39 const deployed = yield* stack.deploy(
40 Effect.gen(function* () {
41 const namespace = yield* Cloudflare.KV.Namespace("RefNamespace");
42 const worker = yield* Cloudflare.Worker("ref-binding-worker", {
43 script,
44 workersDev: true,
45 env: {
46 KV: yield* Cloudflare.KV.Namespace.ref("RefNamespace"),
47 },
48 });
49 return { namespace, worker };
50 }),
51 );
52
53 yield* expectUrlContains(deployed.worker.url!, "bound-through-ref", {
54 label: "ref-bound KV worker",
55 });
56
57 yield* stack.destroy();
58 }),
59 {
60 tags: [
61 "provider:cloudflare",
62 "provider:cloudflare:kv",
63 "provider:cloudflare:worker",
64 "live",
65 ],
66 timeout: 240_000,
67 },
68);