1import * as Alchemy from "alchemy";
2import * as Cloudflare from "alchemy/Cloudflare";
3import * as Effect from "effect/Effect";
4import { resolve } from "node:path";
5
6export default Alchemy.Stack(
7 "CloudflareWebsiteServiceBindingsExample",
8 { providers: Cloudflare.providers(), state: Alchemy.localState() },
9 Effect.gen(function* () {
10 const root = resolve(import.meta.dirname, "apps");
11 const props = {
12 workersDev: false,
13 cache: { enabled: true },
14 dev: { port: 0 },
15 };
16 const websites = yield* Effect.all({
17 sveltekit: Cloudflare.Website.SvelteKit("sveltekit", {
18 ...props,
19 rootDir: resolve(root, "sveltekit"),
20 }),
21 nuxt: Cloudflare.Website.Nuxt("nuxt", {
22 ...props,
23 rootDir: resolve(root, "nuxt"),
24 }),
25 nextjs: Cloudflare.Website.Nextjs("nextjs", {
26 ...props,
27 rootDir: resolve(root, "nextjs"),
28 dev: { port: 0, mode: "hmr" },
29 }),
30 "nextjs-preview": Cloudflare.Website.Nextjs("nextjs-preview", {
31 ...props,
32 rootDir: resolve(root, "nextjs-preview"),
33 dev: { port: 0, mode: "preview" },
34 }),
35 octane: Cloudflare.Website.Octane("octane", {
36 ...props,
37 rootDir: resolve(root, "octane"),
38 }),
39 astro: Cloudflare.Website.Astro("astro", {
40 ...props,
41 rootDir: resolve(root, "astro"),
42 }),
43 waku: Cloudflare.Website.Waku("waku", {
44 ...props,
45 rootDir: resolve(root, "waku"),
46 }),
47 vocs: Cloudflare.Website.Vocs("vocs", {
48 ...props,
49 rootDir: resolve(root, "vocs"),
50 }),
51 vinext: Cloudflare.Website.Vinext("vinext", {
52 ...props,
53 rootDir: resolve(root, "vinext"),
54 }),
55 });
56
57 const gateways = yield* Effect.forEach(
58 Object.entries(websites),
59 ([name, website]) =>
60 Effect.gen(function* () {
61 const gateway = yield* Cloudflare.Worker(`${name}Gateway`, {
62 main: "./gateway.ts",
63 cache: { enabled: false },
64 dev: { port: 0 },
65 env: { WEBSITE: website },
66 });
67 return [
68 name,
69 { websiteUrl: website.url, gatewayUrl: gateway.url },
70 ] as const;
71 }),
72 );
73 return Object.fromEntries(gateways);
74 }),
75);