1import * as Cloudflare from "@/Cloudflare";
2import type * as runtime from "@cloudflare/workers-types";
3import * as Effect from "effect/Effect";
4import { HttpServerRequest } from "effect/http/HttpServerRequest";
5import * as HttpServerResponse from "effect/http/HttpServerResponse";
6import { ApiKey } from "./secret.ts";
7
8/**
9 * Async-binding invocation style: the `Cloudflare.SecretsStore.Secret` is
10 * declared directly on the Worker's `env` (resolved through the service's
11 * async-binding predicate) rather than via `ReadSecret`. The Worker provider
12 * must map it to a `secrets_store_secret` binding so the runtime sees a real
13 * `SecretsStoreSecret` (with `.get()`), not a JSON blob. The `/secret` route
14 * reads it back over the raw runtime binding and echoes the value in the same
15 * shape as the effect-worker route so one driver covers both styles.
16 */
17export default class AsyncSecretWorker extends Cloudflare.Worker<AsyncSecretWorker>()(
18 "AsyncSecretBindingWorker",
19 {
20 main: import.meta.url,
21 workersDev: { enabled: true, previewsEnabled: false },
22 env: {
23 MY_SECRET: ApiKey,
24 },
25 },
26 Effect.gen(function* () {
27 return {
28 fetch: Effect.gen(function* () {
29 const request = yield* HttpServerRequest;
30 const pathname = new URL(request.originalUrl, "http://x").pathname;
31 if (pathname === "/secret") {
32 const env = yield* Cloudflare.Workers.WorkerEnvironment;
33 const secret = (env as Record<string, runtime.SecretsStoreSecret>)
34 .MY_SECRET;
35 const value = yield* Effect.promise(() => secret.get());
36 return yield* HttpServerResponse.json({
37 value,
38 viaGet: value,
39 viaRaw: value,
40 });
41 }
42 return HttpServerResponse.text("Not Found", { status: 404 });
43 }),
44 };
45 }),
46) {}