MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / withLocalServer

Function withLocalServer

e2e/local/local-server.ts:38–137  ·  view source on GitHub ↗
(
  cli: CliSurface,
  runDir: string,
  body: (server: ServerHandle) => Effect.Effect<void>,
  options?: {
    /** Extra env merged into the `executor web` process, e.g. to force a
     *  published-version signal for the update check. */
    readonly env?: Record<string, string>;
    /** Reuse an existing data dir instead of a throwaway one (and keep it on
     *  exit) — for durability scenarios that boot the server twice against the
     *  same persisted state. The caller owns cleanup. */
    readonly dataDir?: string;
    /** Terminal cast filename (default "terminal.cast") so multi-boot
     *  scenarios keep one recording per boot. */
    readonly castName?: string;
  },
)

Source from the content-addressed store, hash-verified

36 * server.
37 */
38export const withLocalServer = (
39 cli: CliSurface,
40 runDir: string,
41 body: (server: ServerHandle) => Effect.Effect<void>,
42 options?: {
43 /** Extra env merged into the `executor web` process, e.g. to force a
44 * published-version signal for the update check. */
45 readonly env?: Record<string, string>;
46 /** Reuse an existing data dir instead of a throwaway one (and keep it on
47 * exit) — for durability scenarios that boot the server twice against the
48 * same persisted state. The caller owns cleanup. */
49 readonly dataDir?: string;
50 /** Terminal cast filename (default "terminal.cast") so multi-boot
51 * scenarios keep one recording per boot. */
52 readonly castName?: string;
53 },
54): Effect.Effect<void> =>
55 Effect.gen(function* () {
56 const ownsDataDir = options?.dataDir === undefined;
57 const dataDir = options?.dataDir ?? mkdtempSync(join(tmpdir(), "executor-local-e2e-"));
58
59 let publishUrl!: (url: string) => void;
60 const urlReady = new Promise<string>((res) => {
61 publishUrl = res;
62 });
63 let signalBodyDone!: () => void;
64 const bodyDone = new Promise<void>((res) => {
65 signalBodyDone = res;
66 });
67
68 yield* Effect.all(
69 [
70 cli.session(
71 ["bun", "run", "dev:cli", "web", "--foreground", "--port", "0"],
72 async (term) => {
73 markRecordingStart(runDir, "terminal");
74 markFocus(runDir, "terminal");
75 // Capture the latest rendered screen on every poll so a boot that
76 // never prints the URL is still diagnosable: `waitUntil` rejects
77 // with a tail-less "timed out" on its deadline, so without this the
78 // failure tells us nothing about how far boot actually got.
79 let lastText = "";
80 const snapshot = await term.screen
81 .waitUntil(
82 (current) => {
83 lastText = current.text;
84 return TOKEN_URL.test(current.text);
85 },
86 // A cold `executor web` runs vite's optimizeDeps before it prints
87 // the URL; 240s leaves headroom for isolated CI cold boots. Kept
88 // BELOW each scenario's test timeout (300s) so that on a slow or
89 // wedged boot THIS error surfaces, with the terminal tail, rather
90 // than racing vitest's generic timeout at the same deadline.
91 { timeoutMs: 240_000 },
92 )
93 .catch((cause: unknown) => {
94 throw new Error(
95 `executor web --foreground printed no ?_token URL within 240s (${String(cause)}):\n${lastText.slice(-600)}`,

Calls 6

markRecordingStartFunction · 0.90
markFocusFunction · 0.90
execMethod · 0.80
waitUntilMethod · 0.65
getMethod · 0.65
syncMethod · 0.65

Tested by

no test coverage detected