1#!/usr/bin/env node
2
3import { Framework } from "@alchemy.run/frontend-frameworks/core";
4import * as Effect from "effect/Effect";
5import * as Command from "effect/cli/Command";
6import * as Flag from "effect/cli/Flag";
7import * as Options from "./Options.ts";
8import * as Runtime from "./Runtime.ts";
9import * as Server from "./Server.ts";
10
11const build = Command.make(
12 "build",
13 {},
14 Effect.fn(function* () {
15 // Build, then persist the BuildOutput to dist/build.json (the harness's
16 // E2E persistence mechanism — `e2e preview` serves from it).
17 yield* Server.buildAndPersist;
18 }),
19);
20
21const dev = Command.make(
22 "dev",
23 {
24 port: Flag.Int("port").pipe(Flag.optional),
25 },
26 Effect.fn(function* ({ port }) {
27 const framework = yield* Framework;
28 // Thread the fixture's project root (Options.root) into Framework.dev,
29 // mirroring what Server/buildAndPersist do for `live`/`build`.
30 const root = yield* Options.load().pipe(
31 Effect.flatMap(Options.resolveRoot),
32 );
33 const { url } = yield* framework.dev({ port: port.valueOrUndefined, root });
34 yield* Effect.log(`Dev server running at ${url}`);
35 yield* Effect.never;
36 }),
37);
38
39const preview = Command.make(
40 "preview",
41 {},
42 Effect.fn(function* () {
43 const server = yield* Server.Server;
44 const instance = yield* server.live();
45 yield* Effect.log("Previewing on", instance.url.toString());
46 yield* Effect.never;
47 }),
48);
49
50Command.make("e2e").pipe(
51 Command.withSubcommands([build, dev, preview]),
52 Command.run({ version: "0.0.0" }),
53 Effect.provide(Runtime.layer),
54 Runtime.runMain,
55);