1import { Query } from "@distilled.cloud/core/query";
2import { Railway as RailwayApi } from "@distilled.cloud/railway";
3import * as Railway from "@/Railway";
4import { suitePartition } from "../suiteProject.ts";
5import * as Test from "@/Test/Alchemy";
6import { expect } from "alchemy-test";
7import * as Effect from "effect/Effect";
8import { MinimumLogLevel } from "effect/References";
9import * as Schedule from "effect/Schedule";
10import * as pathe from "pathe";
11import { cloneFixture } from "../../Cloudflare/Utils/Fixture.ts";
12import { expectUrlContains } from "../../Cloudflare/Utils/Http.ts";
13
14const { test } = Test.make({ providers: Railway.providers() });
15
16const logLevel = Effect.provideService(
17 MinimumLogLevel,
18 process.env.DEBUG ? "Debug" : "Info",
19);
20
21const fixtureDir = pathe.resolve(
22 import.meta.dirname,
23 "../../Cloudflare/Website/foldkit-fixture",
24);
25const tempRoot = pathe.resolve(import.meta.dirname, "../../../.tmp");
26const fixtureEntries = ["index.html", "package.json", "vite.config.ts", "src"];
27
28const readService = Query.fn((id: string) => ({
29 deletedAt: RailwayApi.service({ id }).deletedAt,
30}));
31
32const waitUntilGone = (serviceId: string) =>
33 readService(serviceId).pipe(
34 Effect.map((service) =>
35 service.deletedAt != null ? ("gone" as const) : ("found" as const),
36 ),
37 Effect.catchTag("RailwayNotFound", () => Effect.succeed("gone" as const)),
38 Effect.repeat({
39 schedule: Schedule.spaced("1 second"),
40 until: (status) => status === "gone",
41 times: 10,
42 }),
43 );
44
45// foldkit@0.148.2 requires SchemaTransformation.transformOrFail, absent in Effect rc.115.
46test.provider.skip(
47 "Foldkit: deploy, GET /, destroy, gone",
48 (stack) =>
49 Effect.gen(function* () {
50 yield* stack.destroy();
51
52 const rootDir = yield* cloneFixture(fixtureDir, {
53 prefix: "alchemy-foldkit-railway-",
54 tempRoot,
55 entries: fixtureEntries,
56 });
57
58 const deployed = yield* stack.deploy(
59 Effect.gen(function* () {
60 const { project, environment } = yield* suitePartition;
61 const site = yield* Railway.Website.Foldkit("Web", {
62 project,
63 environment,
64 rootDir,
65 memo: {
66 include: [
67 "index.html",
68 "src/**",
69 "package.json",
70 "vite.config.ts",
71 ],
72 },
73 });
74 return { site };
75 }),
76 );
77
78 const url = deployed.site.url;
79 expect(url).toBeDefined();
80 expect(url).toMatch(/^https:\/\//);
81 expect(deployed.site.service).toBeDefined();
82 expect(deployed.site.project).toBeDefined();
83
84 yield* expectUrlContains(`${url!}/`, "Foldkit Fixture", {
85 timeout: "90 seconds",
86 label: "home page",
87 });
88 yield* expectUrlContains(`${url!}/counter/42`, "Foldkit Fixture", {
89 timeout: "30 seconds",
90 label: "spa fallback",
91 });
92
93 const serviceId = deployed.site.service!.serviceId;
94 yield* stack.destroy();
95 const gone = yield* waitUntilGone(serviceId);
96 expect(gone).toEqual("gone");
97 }).pipe(logLevel),
98 {
99 tags: [
100 "provider:railway",
101 "provider:railway:project",
102 "provider:railway:projectenvironment",
103 "provider:railway:service",
104 "provider:railway:website",
105 "live",
106 ],
107 timeout: 120_000,
108 },
109);