1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import { expect } from "alchemy-test";
4import * as Effect from "effect/Effect";
5import * as pathe from "pathe";
6import { expectUrlContains } from "../../Cloudflare/Utils/Http.ts";
7import { dockerAvailable } from "../bindingHost.ts";
8import {
9 assertSiteGone,
10 cloudRunUrl,
11 liveOptions,
12 logLevel,
13 serviceIdentity,
14} from "./site.ts";
15
16const { test } = Test.make({ providers: GCP.providers() });
17
18// Built in place: vinext and its RSC toolchain resolve only from the
19// example's own node_modules (build output is gitignored there).
20const rootDir = pathe.resolve(
21 import.meta.dirname,
22 "../../../../../examples/fly-website-vinext",
23);
24
25test.provider.skipIf(!dockerAvailable)(
26 "Vinext: deploy, GET page and env-backed API route, destroy, gone",
27 (stack) =>
28 Effect.gen(function* () {
29 yield* stack.destroy();
30
31 const deployed = yield* stack.deploy(
32 Effect.gen(function* () {
33 const site = yield* GCP.Website.Vinext("Web", {
34 rootDir,
35 memo: {
36 include: [
37 "app/**",
38 "public/**",
39 "package.json",
40 "vite.config.ts",
41 "tsconfig.json",
42 ],
43 },
44 env: { GREETING: "Hello from vinext on Cloud Run!" },
45 });
46 return { site };
47 }),
48 );
49
50 const url = deployed.site.url as string;
51 expect(url).toMatch(cloudRunUrl);
52 const service = serviceIdentity(deployed.site.service!);
53 yield* expectUrlContains(`${url}/`, "Hello from vinext on Fly!", {
54 timeout: "180 seconds",
55 label: "vinext page",
56 });
57 yield* expectUrlContains(
58 `${url}/api/hello?name=Alchemy`,
59 "Hello from vinext on Cloud Run!",
60 { timeout: "30 seconds", label: "vinext api env" },
61 );
62
63 yield* stack.destroy();
64 yield* assertSiteGone(service);
65 }).pipe(logLevel),
66 liveOptions(1_200_000),
67);