1// Minimal manual runner for the hmr dev mode: invokes the Framework service
2// directly (no playwright), starts `next dev` with proxied bindings, probes
3// three routes, and exits. Useful for debugging test/hmr.test.ts failures.
4// Run with: node scripts/hmr-repro.mjs
5import { Text } from "@alchemy.run/cloudflare-runtime/core/bindings";
6import { Framework } from "@alchemy.run/frontend-frameworks/core";
7import nextjsFramework from "@alchemy.run/frontend-frameworks/nextjs";
8import * as NodeServices from "@effect/platform-node/NodeServices";
9import * as Exit from "effect/Exit";
10import * as Layer from "effect/Layer";
11import * as ManagedRuntime from "effect/ManagedRuntime";
12import * as Scope from "effect/Scope";
13import { fileURLToPath } from "node:url";
14
15const root = fileURLToPath(new URL("..", import.meta.url));
16
17const layer = nextjsFramework({
18 root,
19 dev: { mode: "hmr" },
20 vite: {
21 compatibilityDate: "2026-05-12",
22 compatibilityFlags: ["nodejs_compat", "global_fetch_strictly_public"],
23 worker: {
24 name: "fixtures-nextjs-hmr",
25 bindings: [Text.local("TEST_TEXT", "hello-from-binding")],
26 },
27 },
28}).pipe(Layer.provideMerge(NodeServices.layer));
29
30const runtime = ManagedRuntime.make(layer);
31const scope = Scope.makeUnsafe();
32const server = await runtime.runPromise(
33 Framework.use((f) => f.dev({ root })).pipe(Scope.provide(scope)),
34);
35console.log("dev server:", server.url);
36for (const path of ["/", "/hmr-probe", "/api/binding"]) {
37 const res = await fetch(new URL(path, server.url));
38 const body = await res.text();
39 console.log(path, res.status, body.slice(0, 300).replace(/\n/g, " "));
40}
41await runtime.runPromise(Scope.close(scope, Exit.void));
42await runtime.dispose();
43process.exit(0);