1// Long-running driver for the hmr dev mode, spawned by test/hmr.test.ts:
2// starts `next dev` (Turbopack) with proxied Cloudflare bindings via the
3// Framework service and prints `DEV_URL <url>` when ready. Runs until
4// SIGTERM/SIGINT, then closes the scope (stopping Next, the http server,
5// and the binding proxy) and exits.
6//
7// The spec runs the server in a child process on purpose: `next dev`
8// installs its own require hooks, which collide with playwright's in-worker
9// transform (`Cannot read properties of undefined (reading '.js')`) — and a
10// child process is also how the dev server runs in real life.
11import { Text } from "@alchemy.run/cloudflare-runtime/core/bindings";
12import { Framework } from "@alchemy.run/frontend-frameworks/core";
13import nextjsFramework from "@alchemy.run/frontend-frameworks/nextjs";
14import * as NodeServices from "@effect/platform-node/NodeServices";
15import * as Exit from "effect/Exit";
16import * as Layer from "effect/Layer";
17import * as ManagedRuntime from "effect/ManagedRuntime";
18import * as Scope from "effect/Scope";
19import { fileURLToPath } from "node:url";
20
21const root = fileURLToPath(new URL("..", import.meta.url));
22
23const layer = nextjsFramework({
24 root,
25 dev: { mode: "hmr" },
26 vite: {
27 compatibilityDate: "2026-05-12",
28 compatibilityFlags: ["nodejs_compat", "global_fetch_strictly_public"],
29 worker: {
30 name: "fixtures-nextjs-hmr",
31 bindings: [Text.local("TEST_TEXT", "hello-from-binding")],
32 },
33 },
34}).pipe(Layer.provideMerge(NodeServices.layer));
35
36const runtime = ManagedRuntime.make(layer);
37const scope = Scope.makeUnsafe();
38const server = await runtime.runPromise(
39 Framework.use((f) => f.dev({ root })).pipe(Scope.provide(scope)),
40);
41console.log(`DEV_URL ${server.url}`);
42
43const shutdown = async () => {
44 await runtime
45 .runPromise(Scope.close(scope, Exit.void))
46 .catch(() => undefined);
47 await runtime.dispose().catch(() => undefined);
48 process.exit(0);
49};
50process.on("SIGTERM", shutdown);
51process.on("SIGINT", shutdown);