594 lines · 19.6 KB · TypeScript
RawDownload
import * as NodeServices from "@effect/platform-node/NodeServices";import * as NodeOS from "node:os";import * as NetService from "@t3tools/shared/Net";import { HostProcessPlatform } from "@t3tools/shared/hostProcess";import { assert, describe, it } from "@effect/vitest";import * as ConfigProvider from "effect/ConfigProvider";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Path from "effect/Path";import * as PlatformError from "effect/PlatformError";import * as Sink from "effect/Sink";import * as Stream from "effect/Stream";import { ChildProcessSpawner } from "effect/unstable/process"; import {  checkPortAvailabilityOnHosts,  createDevRunnerEnv,  findFirstAvailableOffset,  getDevRunnerModeArgs,  resolveModePortOffsets,  resolveOffset,  runDevRunnerWithInput,} from "./dev-runner.ts"; const emptyConfigLayer = ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} }));const netServiceLayer = Layer.succeed(NetService.NetService, {  canListenOnHost: () => Effect.succeed(true),  isPortAvailableOnLoopback: () => Effect.succeed(true),  reserveLoopbackPort: () => Effect.succeed(49_152),  findAvailablePort: (port) => Effect.succeed(port),}); function mockProcess(exit: number | PlatformError.PlatformError) {  return ChildProcessSpawner.makeHandle({    pid: ChildProcessSpawner.ProcessId(1),    exitCode:      typeof exit === "number"        ? Effect.succeed(ChildProcessSpawner.ExitCode(exit))        : Effect.fail(exit),    isRunning: Effect.succeed(false),    kill: () => Effect.void,    unref: Effect.succeed(Effect.void),    stdin: Sink.drain,    stdout: Stream.empty,    stderr: Stream.empty,    all: Stream.empty,    getInputFd: () => Sink.drain,    getOutputFd: () => Stream.empty,  });} const devServerInput = {  mode: "dev:server",  t3Home: "/tmp/t3code-dev-runner",  noBrowser: undefined,  autoBootstrapProjectFromCwd: undefined,  logWebSocketEvents: undefined,  host: undefined,  port: 13_773,  devUrl: undefined,  dryRun: false,  runArgs: ["--inspect", "secret-token-value"],} as const; it.layer(NodeServices.layer)("dev-runner", (it) => {  describe("getDevRunnerModeArgs", () => {    it.effect("lets Vite+ honor the desktop dev task graph", () =>      Effect.sync(() => {        assert.deepStrictEqual(getDevRunnerModeArgs("dev:desktop"), [          "run",          "--filter=@t3tools/desktop",          "--filter=@t3tools/web",          "dev",        ]);      }),    );     it.effect("places Vite+ run flags before the task name", () =>      Effect.sync(() => {        assert.deepStrictEqual(getDevRunnerModeArgs("dev"), [          "run",          "--filter=@t3tools/contracts",          "--filter=@t3tools/web",          "--filter=t3",          "--parallel",          "dev",        ]);      }),    );  });   describe("resolveOffset", () => {    it.effect("uses explicit T3CODE_PORT_OFFSET when provided", () =>      Effect.gen(function* () {        const result = yield* resolveOffset({ portOffset: 12, devInstance: undefined });        assert.deepStrictEqual(result, {          offset: 12,          source: "T3CODE_PORT_OFFSET=12",        });      }),    );     it.effect("hashes non-numeric instance values", () =>      Effect.gen(function* () {        const result = yield* resolveOffset({          portOffset: undefined,          devInstance: "feature-branch",        });        assert.ok(result.offset >= 1);        assert.ok(result.offset <= 3000);      }),    );     it.effect("returns structured context for a negative port offset", () =>      Effect.gen(function* () {        const error = yield* resolveOffset({ portOffset: -1, devInstance: undefined }).pipe(          Effect.flip,        );         assert.equal(error._tag, "DevRunnerInvalidPortOffsetError");        assert.equal(error.configKey, "T3CODE_PORT_OFFSET");        assert.equal(error.portOffset, -1);        assert.equal(error.minimum, 0);        assert.ok(!("cause" in error));      }),    );  });   describe("createDevRunnerEnv", () => {    it.effect("defaults T3CODE_HOME to ~/.t3 when not provided", () =>      Effect.gen(function* () {        const path = yield* Path.Path;        const env = yield* createDevRunnerEnv({          mode: "dev",          baseEnv: {},          serverOffset: 0,          webOffset: 0,          t3Home: undefined,          noBrowser: undefined,          autoBootstrapProjectFromCwd: undefined,          logWebSocketEvents: undefined,          host: undefined,          port: undefined,          devUrl: undefined,        });         assert.equal(env.T3CODE_HOME, path.resolve(NodeOS.homedir(), ".t3"));      }),    );     it.effect("supports explicit typed overrides", () =>      Effect.gen(function* () {        const path = yield* Path.Path;        const env = yield* createDevRunnerEnv({          mode: "dev:server",          baseEnv: {},          serverOffset: 0,          webOffset: 0,          t3Home: "/tmp/custom-t3",          noBrowser: true,          autoBootstrapProjectFromCwd: false,          logWebSocketEvents: true,          host: "0.0.0.0",          port: 4222,          devUrl: new URL("http://localhost:7331"),        });         assert.equal(env.T3CODE_HOME, path.resolve("/tmp/custom-t3"));        assert.equal(env.T3CODE_PORT, "4222");        assert.equal(env.VITE_HTTP_URL, "http://localhost:4222");        assert.equal(env.VITE_WS_URL, "ws://localhost:4222");        assert.equal(env.T3CODE_NO_BROWSER, "1");        assert.equal(env.T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD, "0");        assert.equal(env.T3CODE_LOG_WS_EVENTS, "1");        assert.equal(env.T3CODE_HOST, "0.0.0.0");        assert.equal(env.VITE_DEV_SERVER_URL, "http://localhost:7331/");      }),    );     it.effect("does not force websocket logging on in dev mode when unset", () =>      Effect.gen(function* () {        const env = yield* createDevRunnerEnv({          mode: "dev",          baseEnv: {            T3CODE_LOG_WS_EVENTS: "keep-me-out",          },          serverOffset: 0,          webOffset: 0,          t3Home: undefined,          noBrowser: undefined,          autoBootstrapProjectFromCwd: undefined,          logWebSocketEvents: undefined,          host: undefined,          port: undefined,          devUrl: undefined,        });         assert.equal(env.T3CODE_MODE, "web");        assert.equal(env.T3CODE_LOG_WS_EVENTS, undefined);      }),    );     it.effect("forwards explicit websocket logging false without coercing it away", () =>      Effect.gen(function* () {        const env = yield* createDevRunnerEnv({          mode: "dev",          baseEnv: {            T3CODE_LOG_WS_EVENTS: "1",          },          serverOffset: 0,          webOffset: 0,          t3Home: undefined,          noBrowser: undefined,          autoBootstrapProjectFromCwd: undefined,          logWebSocketEvents: false,          host: undefined,          port: undefined,          devUrl: undefined,        });         assert.equal(env.T3CODE_LOG_WS_EVENTS, "0");      }),    );     it.effect("uses custom t3Home when provided", () =>      Effect.gen(function* () {        const path = yield* Path.Path;        const env = yield* createDevRunnerEnv({          mode: "dev",          baseEnv: {},          serverOffset: 0,          webOffset: 0,          t3Home: "/tmp/my-t3",          noBrowser: undefined,          autoBootstrapProjectFromCwd: undefined,          logWebSocketEvents: undefined,          host: undefined,          port: undefined,          devUrl: undefined,        });         assert.equal(env.T3CODE_HOME, path.resolve("/tmp/my-t3"));      }),    );     it.effect("pins desktop dev to a stable backend port and websocket url", () =>      Effect.gen(function* () {        const path = yield* Path.Path;        const env = yield* createDevRunnerEnv({          mode: "dev:desktop",          baseEnv: {            T3CODE_PORT: "13773",            T3CODE_MODE: "web",            T3CODE_NO_BROWSER: "0",            T3CODE_HOST: "0.0.0.0",            VITE_DEV_SERVER_URL: "http://127.0.0.1:8526",            VITE_WS_URL: "ws://localhost:13773",          },          serverOffset: 0,          webOffset: 0,          t3Home: "/tmp/my-t3",          noBrowser: true,          autoBootstrapProjectFromCwd: undefined,          logWebSocketEvents: undefined,          host: "127.0.0.1",          port: 4222,          devUrl: undefined,        });         assert.equal(env.T3CODE_HOME, path.resolve("/tmp/my-t3"));        assert.equal(env.PORT, "5733");        assert.equal(env.VITE_DEV_SERVER_URL, "http://127.0.0.1:5733");        assert.equal(env.HOST, "127.0.0.1");        assert.equal(env.T3CODE_PORT, "4222");        assert.equal(env.VITE_HTTP_URL, "http://127.0.0.1:4222");        assert.equal(env.T3CODE_MODE, undefined);        assert.equal(env.T3CODE_NO_BROWSER, undefined);        assert.equal(env.T3CODE_HOST, undefined);        assert.equal(env.VITE_WS_URL, "ws://127.0.0.1:4222");      }),    );     it.effect("defaults dev server mode to the higher backend port range", () =>      Effect.gen(function* () {        const env = yield* createDevRunnerEnv({          mode: "dev",          baseEnv: {},          serverOffset: 0,          webOffset: 0,          t3Home: undefined,          noBrowser: undefined,          autoBootstrapProjectFromCwd: undefined,          logWebSocketEvents: undefined,          host: undefined,          port: undefined,          devUrl: undefined,        });         assert.equal(env.T3CODE_PORT, "13773");        assert.equal(env.VITE_HTTP_URL, "http://localhost:13773");        assert.equal(env.VITE_WS_URL, "ws://localhost:13773");      }),    );  });   describe("findFirstAvailableOffset", () => {    it.effect("returns the starting offset when required ports are available", () =>      Effect.gen(function* () {        const offset = yield* findFirstAvailableOffset({          startOffset: 0,          requireServerPort: true,          requireWebPort: true,          checkPortAvailability: () => Effect.succeed(true),        });         assert.equal(offset, 0);      }),    );     it.effect("advances until all required ports are available", () =>      Effect.gen(function* () {        const taken = new Set([13773, 5733, 13774, 5734]);        const offset = yield* findFirstAvailableOffset({          startOffset: 0,          requireServerPort: true,          requireWebPort: true,          checkPortAvailability: (port) => Effect.succeed(!taken.has(port)),        });         assert.equal(offset, 2);      }),    );     it.effect("allows offsets where the non-required server port exceeds max", () =>      Effect.gen(function* () {        const offset = yield* findFirstAvailableOffset({          startOffset: 59_802,          requireServerPort: false,          requireWebPort: true,          checkPortAvailability: () => Effect.succeed(true),        });         assert.equal(offset, 59_802);      }),    );     it.effect("reports the exhausted range and required port set", () =>      Effect.gen(function* () {        const error = yield* findFirstAvailableOffset({          startOffset: 51_763,          requireServerPort: true,          requireWebPort: false,          checkPortAvailability: () => Effect.succeed(true),        }).pipe(Effect.flip);         if (error._tag !== "DevRunnerPortExhaustedError") {          assert.fail(`Unexpected error: ${error._tag}`);        }        assert.equal(error.startOffset, 51_763);        assert.equal(error.requireServerPort, true);        assert.equal(error.requireWebPort, false);        assert.equal(error.baseServerPort, 13_773);        assert.equal(error.baseWebPort, 5_733);        assert.equal(error.maximumPort, 65_535);        assert.ok(!("cause" in error));      }),    );  });   describe("checkPortAvailabilityOnHosts", () => {    it.effect("checks overlapping hosts sequentially to avoid self-interference", () =>      Effect.gen(function* () {        let inFlightCount = 0;        const calls: Array<[number, string]> = [];         const available = yield* checkPortAvailabilityOnHosts(          13_773,          ["127.0.0.1", "0.0.0.0", "::"],          (port, host) =>            Effect.promise(async () => {              calls.push([port, host]);              inFlightCount += 1;              const overlapped = inFlightCount > 1;              await Promise.resolve();              inFlightCount -= 1;              return !overlapped;            }),        );         assert.equal(available, true);        assert.deepStrictEqual(calls, [          [13_773, "127.0.0.1"],          [13_773, "0.0.0.0"],          [13_773, "::"],        ]);      }),    );  });   describe("resolveModePortOffsets", () => {    it.effect("uses a shared fallback offset for dev mode", () =>      Effect.gen(function* () {        const taken = new Set([13773, 5733]);        const offsets = yield* resolveModePortOffsets({          mode: "dev",          startOffset: 0,          hasExplicitServerPort: false,          hasExplicitDevUrl: false,          checkPortAvailability: (port) => Effect.succeed(!taken.has(port)),        });         assert.deepStrictEqual(offsets, { serverOffset: 1, webOffset: 1 });      }),    );     it.effect("keeps server offset stable for dev:web and only shifts web offset", () =>      Effect.gen(function* () {        const taken = new Set([5733]);        const offsets = yield* resolveModePortOffsets({          mode: "dev:web",          startOffset: 0,          hasExplicitServerPort: false,          hasExplicitDevUrl: false,          checkPortAvailability: (port) => Effect.succeed(!taken.has(port)),        });         assert.deepStrictEqual(offsets, { serverOffset: 0, webOffset: 1 });      }),    );     it.effect("shifts only server offset for dev:server", () =>      Effect.gen(function* () {        const taken = new Set([13773]);        const offsets = yield* resolveModePortOffsets({          mode: "dev:server",          startOffset: 0,          hasExplicitServerPort: false,          hasExplicitDevUrl: false,          checkPortAvailability: (port) => Effect.succeed(!taken.has(port)),        });         assert.deepStrictEqual(offsets, { serverOffset: 1, webOffset: 1 });      }),    );     it.effect("respects explicit dev-url override for dev:web", () =>      Effect.gen(function* () {        const offsets = yield* resolveModePortOffsets({          mode: "dev:web",          startOffset: 0,          hasExplicitServerPort: false,          hasExplicitDevUrl: true,          checkPortAvailability: () => Effect.succeed(false),        });         assert.deepStrictEqual(offsets, { serverOffset: 0, webOffset: 0 });      }),    );     it.effect("respects explicit server port override for dev:server", () =>      Effect.gen(function* () {        const offsets = yield* resolveModePortOffsets({          mode: "dev:server",          startOffset: 0,          hasExplicitServerPort: true,          hasExplicitDevUrl: false,          checkPortAvailability: () => Effect.succeed(false),        });         assert.deepStrictEqual(offsets, { serverOffset: 0, webOffset: 0 });      }),    );  });   describe("runDevRunnerWithInput", () => {    it.effect("preserves invalid configuration as the exact cause", () =>      Effect.gen(function* () {        const error = yield* runDevRunnerWithInput({ ...devServerInput, dryRun: true }).pipe(          Effect.provide(            Layer.merge(              netServiceLayer,              ConfigProvider.layer(                ConfigProvider.fromEnv({ env: { T3CODE_PORT_OFFSET: "not-an-integer" } }),              ),            ),          ),          Effect.flip,        );         if (error._tag !== "DevRunnerConfigurationError") {          assert.fail(`Unexpected error: ${error._tag}`);        }        assert.deepStrictEqual(error.configKeys, ["T3CODE_PORT_OFFSET", "T3CODE_DEV_INSTANCE"]);        assert.ok(error.cause !== undefined);        assert.ok(!error.message.includes(String((error.cause as Error).message)));      }),    );     it.effect("preserves process spawn context and the exact platform cause", () => {      const cause = PlatformError.systemError({

Lines 1–500 of 594.