History

wire embedded web UI back into CLI for compiled binaries

Rhys Sullivan committed 7 months ago

Commit ce52c6d1 parent 756a9042 files · +35 −3Browse files

Unified · Split

2 files
  1. apps/cli/src/main.ts +6 −1
  2. apps/local/src/serve.ts +29 −2
apps/cli/src/main.ts+6−1
@@ -30,6 +30,9 @@ import * as Cause from "effect/Cause"; · 29 unmodified lines
3030 import { ExecutorApi } from "@executor/api";
3131 import { startServer, runMcpStdioServer, getExecutor } from "@executor/local";
3232
33+// Embedded web UI — baked into compiled binaries via `with { type: "file" }`
34+import embeddedWebUI from "./embedded-web-ui.gen";
35+
3336 // ---------------------------------------------------------------------------
3437 // Constants
3538 // ---------------------------------------------------------------------------
@@ -115,7 +118,9 @@ const makeApiClient = (baseUrl: string) => · 79 unmodified lines
115118
116119 const runForegroundSession = (input: { port: number }) =>
117120 Effect.gen(function* () {
118− const server = yield* Effect.promise(() => startServer({ port: input.port }));
121+ const server = yield* Effect.promise(() =>
122+ startServer({ port: input.port, embeddedWebUI }),
123+ );
119124
120125 const baseUrl = `http://localhost:${server.port}`;
121126 console.log(`Executor is ready.`);
apps/local/src/serve.ts+29−2
@@ -44,13 +44,30 @@ function collectStaticRoutes(dir: string, prefix = ""): Record<string, ReturnTyp · 43 unmodified lines
4444 return routes;
4545 }
4646
47+/**
48+ * Convert an embedded web UI map (path → bunfs path) into Bun.serve routes.
49+ * The embedded map is generated by the CLI build step using `with { type: "file" }`.
50+ */
51+function embeddedToStaticRoutes(
52+ embedded: Record<string, string>,
53+): Record<string, ReturnType<typeof Bun.file>> {
54+ const routes: Record<string, ReturnType<typeof Bun.file>> = {};
55+ for (const [key, bunfsPath] of Object.entries(embedded)) {
56+ routes[`/${key}`] = Bun.file(bunfsPath);
57+ }
58+ return routes;
59+}
60+
4761 // ---------------------------------------------------------------------------
4862 // Server
4963 // ---------------------------------------------------------------------------
5064
5165 export interface StartServerOptions {
5266 port?: number;
67+ /** Directory containing built client assets (for dev/disk serving). */
5368 clientDir?: string;
69+ /** Embedded web UI map from compiled binary (path → bunfs path). Overrides clientDir. */
70+ embeddedWebUI?: Record<string, string> | null;
5471 }
5572
5673 export interface ServerInstance {
@@ -63,8 +80,18 @@ export async function startServer(opts: StartServerOptions = {}): Promise<Server · 6 unmodified lines
6380 const clientDir = opts.clientDir ?? resolve(import.meta.dirname, "../dist");
6481
6582 const handlers = await getServerHandlers();
66− const staticRoutes = collectStaticRoutes(clientDir);
67− const indexHtml = Bun.file(join(clientDir, "index.html"));
83+
84+ // Build static routes from either embedded assets or disk
85+ let staticRoutes: Record<string, ReturnType<typeof Bun.file>>;
86+ let indexHtml: ReturnType<typeof Bun.file>;
87+
88+ if (opts.embeddedWebUI) {
89+ staticRoutes = embeddedToStaticRoutes(opts.embeddedWebUI);
90+ indexHtml = staticRoutes["/index.html"] ?? Bun.file(join(clientDir, "index.html"));
91+ } else {
92+ staticRoutes = collectStaticRoutes(clientDir);
93+ indexHtml = Bun.file(join(clientDir, "index.html"));
94+ }
6895
6996 const server = Bun.serve({
7097 port,