import { describe, expect, it } from "@effect/vitest";import { createServer } from "node:net";import * as Effect from "effect/Effect"; import { buildDaemonSpawnSpec, canAutoStartLocalDaemonForHost, chooseDaemonPort, isDevCliEntrypoint, parseDaemonBaseUrl,} from "../apps/cli/src/daemon"; describe("daemon bootstrap helpers", () => { it("parses default port when none is provided", () => { const parsed = parseDaemonBaseUrl("http://localhost", 4788); expect(parsed).toEqual({ hostname: "localhost", port: 4788 }); }); it("parses explicit port from base url", () => { const parsed = parseDaemonBaseUrl("http://127.0.0.1:9001", 4788); expect(parsed).toEqual({ hostname: "127.0.0.1", port: 9001 }); }); it("rejects non-http schemes for auto-start", () => { expect(() => parseDaemonBaseUrl("https://localhost:4788", 4788)).toThrow( "Only http:// base URLs are supported", ); }); it("only auto-starts for local hosts", () => { expect(canAutoStartLocalDaemonForHost("localhost")).toBe(true); expect(canAutoStartLocalDaemonForHost("127.0.0.1")).toBe(true); expect(canAutoStartLocalDaemonForHost("::1")).toBe(true); expect(canAutoStartLocalDaemonForHost("api.example.com")).toBe(false); }); it("treats source entrypoints as dev mode but excludes bun embedded paths", () => { expect(isDevCliEntrypoint("/repo/apps/cli/src/main.ts")).toBe(true); expect(isDevCliEntrypoint("/repo/apps/cli/src/main.js")).toBe(true); expect(isDevCliEntrypoint("/$bunfs/root/main.js")).toBe(false); expect(isDevCliEntrypoint("/usr/local/bin/executor")).toBe(false); expect(isDevCliEntrypoint(undefined)).toBe(false); }); it("builds bun-run spec in dev mode", () => { const spec = buildDaemonSpawnSpec({ port: 4788, hostname: "localhost", isDevMode: true, scriptPath: "/repo/apps/cli/src/main.ts", executablePath: "/ignored", }); expect(spec.command).toBe("bun"); expect(spec.args).toEqual([ "run", "/repo/apps/cli/src/main.ts", "daemon", "run", "--port", "4788", "--hostname", "localhost", "--foreground", ]); }); it("builds executable spec outside dev mode", () => { const spec = buildDaemonSpawnSpec({ port: 5000, hostname: "127.0.0.1", isDevMode: false, scriptPath: undefined, executablePath: "/usr/local/bin/executor", }); expect(spec.command).toBe("/usr/local/bin/executor"); expect(spec.args).toEqual([ "daemon", "run", "--port", "5000", "--hostname", "127.0.0.1", "--foreground", ]); }); it("propagates allowed hosts as repeated flags", () => { const spec = buildDaemonSpawnSpec({ port: 4788, hostname: "0.0.0.0", isDevMode: false, scriptPath: undefined, executablePath: "/usr/local/bin/executor", allowedHosts: ["my.box", "other.host"], }); expect(spec.args).toEqual([ "daemon", "run", "--port", "4788", "--hostname", "0.0.0.0", "--foreground", "--allowed-host", "my.box", "--allowed-host", "other.host", ]); }); it("fails in dev mode when script path is missing", () => { expect(() => buildDaemonSpawnSpec({ port: 4788, hostname: "localhost", isDevMode: true, scriptPath: undefined, executablePath: "/usr/local/bin/executor", }), ).toThrow("Cannot auto-start daemon in dev mode"); }); it("falls back when preferred daemon port is occupied", async () => { const blocker = createServer(); await Effect.runPromise( Effect.scoped( Effect.gen(function* () { yield* Effect.acquireRelease( Effect.callback<void, Error>((resume) => { blocker.once("error", (error) => resume(Effect.fail(error))); blocker.listen({ port: 0, host: "127.0.0.1" }, () => resume(Effect.succeed(undefined)), ); }), () => Effect.promise( () => new Promise<void>((resolve) => { blocker.close(() => resolve()); }), ), ); const occupied = (() => { const address = blocker.address(); return typeof address === "object" && address !== null ? address.port : 0; })(); const picked = yield* chooseDaemonPort({ preferredPort: occupied, hostname: "127.0.0.1", }); expect(picked).not.toBe(occupied); }), ), ); });});
import { describe, expect, it } from "@effect/vitest";
import { createServer } from "node:net";
import * as Effect from "effect/Effect";
import {
buildDaemonSpawnSpec,
canAutoStartLocalDaemonForHost,
chooseDaemonPort,
isDevCliEntrypoint,
parseDaemonBaseUrl,
} from "../apps/cli/src/daemon";
describe("daemon bootstrap helpers", () => {
it("parses default port when none is provided", () => {
const parsed = parseDaemonBaseUrl("http://localhost", 4788);
expect(parsed).toEqual({ hostname: "localhost", port: 4788 });
});
it("parses explicit port from base url", () => {
const parsed = parseDaemonBaseUrl("http://127.0.0.1:9001", 4788);
expect(parsed).toEqual({ hostname: "127.0.0.1", port: 9001 });
});
it("rejects non-http schemes for auto-start", () => {
expect(() => parseDaemonBaseUrl("https://localhost:4788", 4788)).toThrow(
"Only http:// base URLs are supported",
);
});
it("only auto-starts for local hosts", () => {
expect(canAutoStartLocalDaemonForHost("localhost")).toBe(true);
expect(canAutoStartLocalDaemonForHost("127.0.0.1")).toBe(true);
expect(canAutoStartLocalDaemonForHost("::1")).toBe(true);
expect(canAutoStartLocalDaemonForHost("api.example.com")).toBe(false);
});
it("treats source entrypoints as dev mode but excludes bun embedded paths", () => {
expect(isDevCliEntrypoint("/repo/apps/cli/src/main.ts")).toBe(true);
expect(isDevCliEntrypoint("/repo/apps/cli/src/main.js")).toBe(true);
expect(isDevCliEntrypoint("/$bunfs/root/main.js")).toBe(false);
expect(isDevCliEntrypoint("/usr/local/bin/executor")).toBe(false);
expect(isDevCliEntrypoint(undefined)).toBe(false);
});
it("builds bun-run spec in dev mode", () => {
const spec = buildDaemonSpawnSpec({
port: 4788,
hostname: "localhost",
isDevMode: true,
scriptPath: "/repo/apps/cli/src/main.ts",
executablePath: "/ignored",
});
expect(spec.command).toBe("bun");
expect(spec.args).toEqual([
"run",
"/repo/apps/cli/src/main.ts",
"daemon",
"run",
"--port",
"4788",
"--hostname",
"localhost",
"--foreground",
]);
});
it("builds executable spec outside dev mode", () => {
const spec = buildDaemonSpawnSpec({
port: 5000,
hostname: "127.0.0.1",
isDevMode: false,
scriptPath: undefined,
executablePath: "/usr/local/bin/executor",
});
expect(spec.command).toBe("/usr/local/bin/executor");
expect(spec.args).toEqual([
"daemon",
"run",
"--port",
"5000",
"--hostname",
"127.0.0.1",
"--foreground",
]);
});
it("propagates allowed hosts as repeated flags", () => {
const spec = buildDaemonSpawnSpec({
port: 4788,
hostname: "0.0.0.0",
isDevMode: false,
scriptPath: undefined,
executablePath: "/usr/local/bin/executor",
allowedHosts: ["my.box", "other.host"],
});
expect(spec.args).toEqual([
"daemon",
"run",
"--port",
"4788",
"--hostname",
"0.0.0.0",
"--foreground",
"--allowed-host",
"my.box",
"--allowed-host",
"other.host",
]);
});
it("fails in dev mode when script path is missing", () => {
expect(() =>
buildDaemonSpawnSpec({
port: 4788,
hostname: "localhost",
isDevMode: true,
scriptPath: undefined,
executablePath: "/usr/local/bin/executor",
}),
).toThrow("Cannot auto-start daemon in dev mode");
});
it("falls back when preferred daemon port is occupied", async () => {
const blocker = createServer();
await Effect.runPromise(
Effect.scoped(
Effect.gen(function* () {
yield* Effect.acquireRelease(
Effect.callback<void, Error>((resume) => {
blocker.once("error", (error) => resume(Effect.fail(error)));
blocker.listen({ port: 0, host: "127.0.0.1" }, () =>
resume(Effect.succeed(undefined)),
);
}),
() =>
Effect.promise(
() =>
new Promise<void>((resolve) => {
blocker.close(() => resolve());
}),
),
);
const occupied = (() => {
const address = blocker.address();
return typeof address === "object" && address !== null ? address.port : 0;
})();
const picked = yield* chooseDaemonPort({
preferredPort: occupied,
hostname: "127.0.0.1",
});
expect(picked).not.toBe(occupied);
}),
),
);
});
});