1import * as Cloudflare from "@/Cloudflare/index.ts";
2import * as Test from "@/Test/Alchemy";
3import { expect } from "alchemy-test";
4import * as Effect from "effect/Effect";
5import * as Schedule from "effect/Schedule";
6import * as HttpClient from "effect/http/HttpClient";
7import * as pathe from "pathe";
8import Stack from "./fixtures/url-stack.ts";
9
10const { test, beforeAll, afterAll, deploy, destroy } = Test.make({
11 providers: Cloudflare.providers(),
12});
13
14const stack = beforeAll(deploy(Stack));
15afterAll.skipIf(!!process.env.NO_DESTROY)(destroy(Stack));
16
17// Fresh workers.dev URLs can briefly serve Cloudflare's placeholder page with
18// a 200, so retry until the body parses as JSON (the placeholder is HTML).
19const getJson = (url: string) =>
20 HttpClient.HttpClient.pipe(
21 Effect.flatMap((client) => client.get(url)),
22 Effect.flatMap((res) => res.json),
23 Effect.retry({
24 schedule: Schedule.exponential("1 second"),
25 times: 12,
26 }),
27 Effect.map((body) => body as Record<string, string>),
28 );
29
30test(
31 "effectful worker reads its own URL via yield* Worker.URL",
32 Effect.gen(function* () {
33 const { effectUrl } = yield* stack;
34 const body = yield* getJson(`${effectUrl}/`);
35 expect(body.url).toBe(effectUrl);
36 }),
37 {
38 tags: ["provider:cloudflare", "provider:cloudflare:worker", "live"],
39 timeout: 180_000,
40 },
41);
42
43test(
44 "async worker receives its own URL via env: { PUBLIC_URL: Worker.URL }",
45 Effect.gen(function* () {
46 const { asyncUrl } = yield* stack;
47 const body = yield* getJson(`${asyncUrl}/`);
48 expect(body.url).toBe(asyncUrl);
49 }),
50 {
51 tags: ["provider:cloudflare", "provider:cloudflare:worker", "live"],
52 timeout: 180_000,
53 },
54);
55
56// The canonical VITE_PUBLIC_URL use case: the URL is resolved before the vite
57// build, so it reaches the bundle two ways — inlined into `import.meta.env`
58// via `define` at build time, and as a plain_text env binding at deploy time.
59test.provider.skipIf(!!process.env.FAST)(
60 "vite worker inlines VITE_PUBLIC_URL at build time and binds it at runtime",
61 (stack) =>
62 Effect.gen(function* () {
63 yield* stack.destroy();
64
65 const rootDir = pathe.resolve(
66 import.meta.dirname,
67 "fixtures/vite-url-fixture",
68 );
69 const site = yield* stack.deploy(
70 Effect.gen(function* () {
71 return yield* Cloudflare.Worker("UrlViteWorker", {
72 vite: {
73 rootDir,
74 memo: {
75 include: [
76 "index.html",
77 "package.json",
78 "vite.config.ts",
79 "src/**",
80 ],
81 },
82 },
83 compatibility: {
84 date: "2024-09-23",
85 flags: ["nodejs_compat"],
86 },
87 env: {
88 VITE_PUBLIC_URL: Cloudflare.Worker.URL,
89 },
90 });
91 }),
92 );
93
94 expect(site.url).toBeDefined();
95 const body = yield* getJson(`${site.url!}/self-url`);
96 expect(body.inlined).toBe(site.url);
97 expect(body.env).toBe(site.url);
98
99 yield* stack.destroy();
100 }),
101 {
102 tags: ["provider:cloudflare", "provider:cloudflare:worker", "live"],
103 timeout: 360_000,
104 },
105);