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 "../../AWS/Website/fixtures/sveltekit-app",
24);
25const tempRoot = pathe.resolve(import.meta.dirname, "../../../.tmp");
26const fixtureEntries = [".gitignore", "package.json", "src", "static"];
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
45test.provider(
46 "SvelteKit: deploy, GET /, destroy, gone",
47 (stack) =>
48 Effect.gen(function* () {
49 yield* stack.destroy();
50
51 const rootDir = yield* cloneFixture(fixtureDir, {
52 prefix: "alchemy-sveltekit-railway-",
53 tempRoot,
54 entries: fixtureEntries,
55 });
56
57 const deployed = yield* stack.deploy(
58 Effect.gen(function* () {
59 const { project, environment } = yield* suitePartition;
60 const site = yield* Railway.Website.SvelteKit("Web", {
61 project,
62 environment,
63 rootDir,
64 memo: {
65 include: ["src/**", "static/**", "package.json"],
66 },
67 });
68 return { site };
69 }),
70 );
71
72 const url = deployed.site.url;
73 expect(url).toBeDefined();
74 expect(url).toMatch(/^https:\/\//);
75 expect(deployed.site.service).toBeDefined();
76 expect(deployed.site.project).toBeDefined();
77
78 yield* expectUrlContains(`${url!}/`, "SVELTEKIT_AWS_PAGE_MARKER", {
79 timeout: "90 seconds",
80 label: "home page",
81 });
82 yield* expectUrlContains(
83 `${url!}/api/hello?echo=roundtrip`,
84 "SVELTEKIT_AWS_API_MARKER",
85 {
86 timeout: "30 seconds",
87 label: "api route",
88 },
89 );
90
91 const serviceId = deployed.site.service!.serviceId;
92 yield* stack.destroy();
93 const gone = yield* waitUntilGone(serviceId);
94 expect(gone).toEqual("gone");
95 }).pipe(logLevel),
96 {
97 tags: [
98 "provider:railway",
99 "provider:railway:project",
100 "provider:railway:projectenvironment",
101 "provider:railway:service",
102 "provider:railway:website",
103 "live",
104 ],
105 timeout: 120_000,
106 },
107);