| 1 | import * as Alchemy from "alchemy"; |
| 2 | import * as Cloudflare from "alchemy/Cloudflare"; |
| 3 | import * as Effect from "effect/Effect"; |
| 4 | |
| 5 | import { Gateway } from "./src/AiGateway.ts"; |
| 6 | import Api from "./src/Api.ts"; |
| 7 | import { Bucket } from "./src/Bucket.ts"; |
| 8 | import SandboxLive from "./src/Sandbox.ts"; |
| 9 | import SecondaryApiLive, { SecondaryApi } from "./src/SecondaryApi.ts"; |
| 10 | import WorkerTagLive, { WorkerTag } from "./src/WorkerTag.ts"; |
| 11 | |
| 12 | // Demo Action — runs at deploy time when its input (the resolved deployed |
| 13 | // URL) changes. Logs the new URL and returns a tiny manifest used as the |
| 14 | // stack output. Re-deploys with no changes skip the body. |
| 15 | const AnnounceDeploy = Alchemy.Action( |
| 16 | "AnnounceDeploy", |
| 17 | (input: { url: string; bucket: string }) => |
| 18 | Effect.gen(function* () { |
| 19 | yield* Effect.log(`Deployed ${input.url} (bucket: ${input.bucket})`); |
| 20 | return { deployedAt: new Date().toISOString(), url: input.url }; |
| 21 | }), |
| 22 | ); |
| 23 | |
| 24 | export default Alchemy.Stack( |
| 25 | "CloudflareWorkerExample", |
| 26 | { |
| 27 | providers: Cloudflare.providers(), |
| 28 | state: Cloudflare.state(), |
| 29 | }, |
| 30 | Effect.gen(function* () { |
| 31 | const api = yield* Api; |
| 32 | const bucket = yield* Bucket; |
| 33 | const gateway = yield* Gateway; |
| 34 | const workerTag = yield* WorkerTag; |
| 35 | // Two Workers binding the same Agent DO triggers the regression where |
| 36 | // a single Container DO namespace appears in multiple bindings on the |
| 37 | // Sandbox ContainerApplication. See SecondaryApi.ts for details. |
| 38 | const secondaryApi = yield* SecondaryApi; |
| 39 | // The Queue consumer is wired automatically by |
| 40 | // `Cloudflare.Queues.consumeQueueMessages(Queue, handler)` inside src/Api.ts — |
| 41 | // no explicit `Cloudflare.Queues.Consumer(...)` is needed here. |
| 42 | |
| 43 | const announcement = yield* AnnounceDeploy({ |
| 44 | url: api.url.as<string>(), |
| 45 | bucket: bucket.bucketName, |
| 46 | }); |
| 47 | |
| 48 | return { |
| 49 | url: api.url.as<string>(), |
| 50 | bucket: bucket.bucketName, |
| 51 | gatewayId: gateway.gatewayId, |
| 52 | workerTagUrl: workerTag.url.as<string>(), |
| 53 | secondaryApiUrl: secondaryApi.url.as<string>(), |
| 54 | deployedAt: announcement.deployedAt, |
| 55 | }; |
| 56 | }).pipe(Effect.provide([WorkerTagLive, SecondaryApiLive, SandboxLive])), |
| 57 | ); |