1import * as machines from "@distilled.cloud/fly-io/machines";
2import * as Fly from "@/Fly";
3import * as Test from "@/Test/Alchemy";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8import * as pathe from "pathe";
9import { cloneFixture } from "../../Cloudflare/Utils/Fixture.ts";
10import { expectUrlContains } from "../../Cloudflare/Utils/Http.ts";
11
12const { test } = Test.make({ providers: Fly.providers() });
13
14const logLevel = Effect.provideService(
15 MinimumLogLevel,
16 process.env.DEBUG ? "Debug" : "Info",
17);
18
19const fixtureDir = pathe.resolve(
20 import.meta.dirname,
21 "../../Cloudflare/Website/foldkit-fixture",
22);
23const tempRoot = pathe.resolve(import.meta.dirname, "../../../.tmp");
24const fixtureEntries = ["index.html", "package.json", "vite.config.ts", "src"];
25
26const waitUntilGone = (appName: string) =>
27 machines.getApp({ app_name: appName }).pipe(
28 Effect.as("found" as const),
29 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
30 Effect.repeat({
31 schedule: Schedule.spaced("1 second"),
32 until: (status) => status === "gone",
33 times: 10,
34 }),
35 );
36
37test.provider(
38 "Foldkit: deploy, GET /, destroy, gone",
39 (stack) =>
40 Effect.gen(function* () {
41 yield* stack.destroy();
42
43 const rootDir = yield* cloneFixture(fixtureDir, {
44 prefix: "alchemy-foldkit-fly-",
45 tempRoot,
46 entries: fixtureEntries,
47 });
48
49 const deployed = yield* stack.deploy(
50 Effect.gen(function* () {
51 const site = yield* Fly.Website.Foldkit("Web", {
52 rootDir,
53 memo: {
54 include: [
55 "index.html",
56 "src/**",
57 "package.json",
58 "vite.config.ts",
59 ],
60 },
61 });
62 return { site };
63 }),
64 );
65
66 const url = deployed.site.url;
67 expect(url).toBeDefined();
68 expect(url).toMatch(/^https:\/\//);
69 expect(deployed.site.service).toBeDefined();
70 expect(deployed.site.app).toBeDefined();
71
72 yield* expectUrlContains(`${url!}/`, "Foldkit Fixture", {
73 timeout: "90 seconds",
74 label: "home page",
75 });
76 yield* expectUrlContains(`${url!}/counter/42`, "Foldkit Fixture", {
77 timeout: "30 seconds",
78 label: "spa fallback",
79 });
80
81 const appName = deployed.site.app!.appName;
82 yield* stack.destroy();
83 const gone = yield* waitUntilGone(appName);
84 expect(gone).toEqual("gone");
85 }).pipe(logLevel),
86 {
87 tags: [
88 "provider:fly",
89 "provider:fly:machine",
90 "provider:fly:website",
91 "live",
92 ],
93 timeout: 180000,
94 },
95);