import os from "node:os"; import { assert, expect, it } from "@effect/vitest";import { ConfigProvider, Effect, FileSystem, Layer, Option, Path } from "effect"; import { NetService } from "@t3tools/shared/Net";import * as NodeServices from "@effect/platform-node/NodeServices";import { deriveServerPaths } from "./config";import { resolveServerConfig } from "./cli"; it.layer(NodeServices.layer)("cli config resolution", (it) => { const openBootstrapFd = Effect.fn(function* (payload: Record<string, unknown>) { const fs = yield* FileSystem.FileSystem; const filePath = yield* fs.makeTempFileScoped({ prefix: "t3-bootstrap-", suffix: ".ndjson" }); yield* fs.writeFileString(filePath, `${JSON.stringify(payload)}\n`); const { fd } = yield* fs.open(filePath, { flag: "r" }); return fd; }); it.effect("falls back to effect/config values when flags are omitted", () => Effect.gen(function* () { const { join } = yield* Path.Path; const baseDir = join(os.tmpdir(), "t3-cli-config-env-base"); const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:5173")); const resolved = yield* resolveServerConfig( { mode: Option.none(), port: Option.none(), host: Option.none(), baseDir: Option.none(), devUrl: Option.none(), noBrowser: Option.none(), authToken: Option.none(), bootstrapFd: Option.none(), autoBootstrapProjectFromCwd: Option.none(), logWebSocketEvents: Option.none(), }, Option.none(), ).pipe( Effect.provide( Layer.mergeAll( ConfigProvider.layer( ConfigProvider.fromEnv({ env: { T3CODE_LOG_LEVEL: "Warn", T3CODE_MODE: "desktop", T3CODE_PORT: "4001", T3CODE_HOST: "0.0.0.0", T3CODE_HOME: baseDir, VITE_DEV_SERVER_URL: "http://127.0.0.1:5173", T3CODE_NO_BROWSER: "true", T3CODE_AUTH_TOKEN: "env-token", T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD: "false", T3CODE_LOG_WS_EVENTS: "true", }, }), ), NetService.layer, ), ), ); expect(resolved).toEqual({ logLevel: "Warn", mode: "desktop", port: 4001, cwd: process.cwd(), baseDir, ...derivedPaths, host: "0.0.0.0", staticDir: undefined, devUrl: new URL("http://127.0.0.1:5173"), noBrowser: true, authToken: "env-token", autoBootstrapProjectFromCwd: false, logWebSocketEvents: true, }); }), ); it.effect("uses CLI flags when provided", () => Effect.gen(function* () { const { join } = yield* Path.Path; const baseDir = join(os.tmpdir(), "t3-cli-config-flags-base"); const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:4173")); const resolved = yield* resolveServerConfig( { mode: Option.some("web"), port: Option.some(8788), host: Option.some("127.0.0.1"), baseDir: Option.some(baseDir), devUrl: Option.some(new URL("http://127.0.0.1:4173")), noBrowser: Option.some(true), authToken: Option.some("flag-token"), bootstrapFd: Option.none(), autoBootstrapProjectFromCwd: Option.some(true), logWebSocketEvents: Option.some(true), }, Option.some("Debug"), ).pipe( Effect.provide( Layer.mergeAll( ConfigProvider.layer( ConfigProvider.fromEnv({ env: { T3CODE_LOG_LEVEL: "Warn", T3CODE_MODE: "desktop", T3CODE_PORT: "4001", T3CODE_HOST: "0.0.0.0", T3CODE_HOME: join(os.tmpdir(), "ignored-base"), VITE_DEV_SERVER_URL: "http://127.0.0.1:5173", T3CODE_NO_BROWSER: "false", T3CODE_AUTH_TOKEN: "ignored-token", T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD: "false", T3CODE_LOG_WS_EVENTS: "false", }, }), ), NetService.layer, ), ), ); expect(resolved).toEqual({ logLevel: "Debug", mode: "web", port: 8788, cwd: process.cwd(), baseDir, ...derivedPaths, host: "127.0.0.1", staticDir: undefined, devUrl: new URL("http://127.0.0.1:4173"), noBrowser: true, authToken: "flag-token", autoBootstrapProjectFromCwd: true, logWebSocketEvents: true, }); }), ); it.effect("uses bootstrap envelope values as fallbacks when flags and env are absent", () => Effect.gen(function* () { const { join } = yield* Path.Path; const baseDir = "/tmp/t3-bootstrap-home"; const fd = yield* openBootstrapFd({ mode: "desktop", port: 4888, host: "127.0.0.2", t3Home: baseDir, devUrl: "http://127.0.0.1:5173", noBrowser: true, authToken: "bootstrap-token", autoBootstrapProjectFromCwd: false, logWebSocketEvents: true, }); const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:5173")); const resolved = yield* resolveServerConfig( { mode: Option.none(), port: Option.none(), host: Option.none(), baseDir: Option.none(), devUrl: Option.none(), noBrowser: Option.none(), authToken: Option.none(), bootstrapFd: Option.none(), autoBootstrapProjectFromCwd: Option.none(), logWebSocketEvents: Option.none(), }, Option.none(), ).pipe( Effect.provide( Layer.mergeAll( ConfigProvider.layer( ConfigProvider.fromEnv({ env: { T3CODE_BOOTSTRAP_FD: String(fd), }, }), ), NetService.layer, ), ), ); expect(resolved).toEqual({ logLevel: "Info", mode: "desktop", port: 4888, cwd: process.cwd(), baseDir, ...derivedPaths, host: "127.0.0.2", staticDir: undefined, devUrl: new URL("http://127.0.0.1:5173"), noBrowser: true, authToken: "bootstrap-token", autoBootstrapProjectFromCwd: false, logWebSocketEvents: true, }); assert.equal(join(baseDir, "dev"), resolved.stateDir); }), ); it.effect("creates derived runtime directories during config resolution", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-cli-config-dirs-" }); const resolved = yield* resolveServerConfig( { mode: Option.some("desktop"), port: Option.some(4888), host: Option.none(), baseDir: Option.some(baseDir), devUrl: Option.some(new URL("http://127.0.0.1:5173")), noBrowser: Option.none(), authToken: Option.none(), bootstrapFd: Option.none(), autoBootstrapProjectFromCwd: Option.none(), logWebSocketEvents: Option.none(), }, Option.none(), ).pipe( Effect.provide( Layer.mergeAll( ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })), NetService.layer, ), ), ); for (const directory of [ resolved.stateDir, resolved.logsDir, resolved.providerLogsDir, resolved.terminalLogsDir, resolved.attachmentsDir, resolved.worktreesDir, path.dirname(resolved.serverLogPath), ]) { expect(yield* fs.exists(directory)).toBe(true); } }), ); it.effect("applies flag then env precedence over bootstrap envelope values", () => Effect.gen(function* () { const { join } = yield* Path.Path; const baseDir = join(os.tmpdir(), "t3-cli-config-env-wins"); const fd = yield* openBootstrapFd({ mode: "desktop", port: 4888, host: "127.0.0.2", t3Home: "/tmp/t3-bootstrap-home", devUrl: "http://127.0.0.1:5173", noBrowser: false, authToken: "bootstrap-token", autoBootstrapProjectFromCwd: false, logWebSocketEvents: false, }); const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:4173")); const resolved = yield* resolveServerConfig( { mode: Option.none(), port: Option.some(8788), host: Option.some("127.0.0.1"), baseDir: Option.none(), devUrl: Option.some(new URL("http://127.0.0.1:4173")), noBrowser: Option.none(), authToken: Option.some("flag-token"), bootstrapFd: Option.none(), autoBootstrapProjectFromCwd: Option.none(), logWebSocketEvents: Option.none(), }, Option.some("Debug"), ).pipe( Effect.provide( Layer.mergeAll( ConfigProvider.layer( ConfigProvider.fromEnv({ env: { T3CODE_MODE: "web", T3CODE_BOOTSTRAP_FD: String(fd), T3CODE_HOME: baseDir, T3CODE_NO_BROWSER: "true", T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD: "true", T3CODE_LOG_WS_EVENTS: "true", }, }), ), NetService.layer, ), ), ); expect(resolved).toEqual({ logLevel: "Debug", mode: "web", port: 8788, cwd: process.cwd(), baseDir, ...derivedPaths, host: "127.0.0.1", staticDir: undefined, devUrl: new URL("http://127.0.0.1:4173"), noBrowser: true, authToken: "flag-token", autoBootstrapProjectFromCwd: true, logWebSocketEvents: true, }); }), );});
import os from "node:os";
import { assert, expect, it } from "@effect/vitest";
import { ConfigProvider, Effect, FileSystem, Layer, Option, Path } from "effect";
import { NetService } from "@t3tools/shared/Net";
import * as NodeServices from "@effect/platform-node/NodeServices";
import { deriveServerPaths } from "./config";
import { resolveServerConfig } from "./cli";
it.layer(NodeServices.layer)("cli config resolution", (it) => {
const openBootstrapFd = Effect.fn(function* (payload: Record<string, unknown>) {
const fs = yield* FileSystem.FileSystem;
const filePath = yield* fs.makeTempFileScoped({ prefix: "t3-bootstrap-", suffix: ".ndjson" });
yield* fs.writeFileString(filePath, `${JSON.stringify(payload)}\n`);
const { fd } = yield* fs.open(filePath, { flag: "r" });
return fd;
});
it.effect("falls back to effect/config values when flags are omitted", () =>
Effect.gen(function* () {
const { join } = yield* Path.Path;
const baseDir = join(os.tmpdir(), "t3-cli-config-env-base");
const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:5173"));
const resolved = yield* resolveServerConfig(
{
mode: Option.none(),
port: Option.none(),
host: Option.none(),
baseDir: Option.none(),
devUrl: Option.none(),
noBrowser: Option.none(),
authToken: Option.none(),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.none(),
logWebSocketEvents: Option.none(),
},
Option.none(),
).pipe(
Effect.provide(
Layer.mergeAll(
ConfigProvider.layer(
ConfigProvider.fromEnv({
env: {
T3CODE_LOG_LEVEL: "Warn",
T3CODE_MODE: "desktop",
T3CODE_PORT: "4001",
T3CODE_HOST: "0.0.0.0",
T3CODE_HOME: baseDir,
VITE_DEV_SERVER_URL: "http://127.0.0.1:5173",
T3CODE_NO_BROWSER: "true",
T3CODE_AUTH_TOKEN: "env-token",
T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD: "false",
T3CODE_LOG_WS_EVENTS: "true",
},
}),
),
NetService.layer,
),
),
);
expect(resolved).toEqual({
logLevel: "Warn",
mode: "desktop",
port: 4001,
cwd: process.cwd(),
baseDir,
...derivedPaths,
host: "0.0.0.0",
staticDir: undefined,
devUrl: new URL("http://127.0.0.1:5173"),
noBrowser: true,
authToken: "env-token",
autoBootstrapProjectFromCwd: false,
logWebSocketEvents: true,
});
}),
);
it.effect("uses CLI flags when provided", () =>
Effect.gen(function* () {
const { join } = yield* Path.Path;
const baseDir = join(os.tmpdir(), "t3-cli-config-flags-base");
const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:4173"));
const resolved = yield* resolveServerConfig(
{
mode: Option.some("web"),
port: Option.some(8788),
host: Option.some("127.0.0.1"),
baseDir: Option.some(baseDir),
devUrl: Option.some(new URL("http://127.0.0.1:4173")),
noBrowser: Option.some(true),
authToken: Option.some("flag-token"),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.some(true),
logWebSocketEvents: Option.some(true),
},
Option.some("Debug"),
).pipe(
Effect.provide(
Layer.mergeAll(
ConfigProvider.layer(
ConfigProvider.fromEnv({
env: {
T3CODE_LOG_LEVEL: "Warn",
T3CODE_MODE: "desktop",
T3CODE_PORT: "4001",
T3CODE_HOST: "0.0.0.0",
T3CODE_HOME: join(os.tmpdir(), "ignored-base"),
VITE_DEV_SERVER_URL: "http://127.0.0.1:5173",
T3CODE_NO_BROWSER: "false",
T3CODE_AUTH_TOKEN: "ignored-token",
T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD: "false",
T3CODE_LOG_WS_EVENTS: "false",
},
}),
),
NetService.layer,
),
),
);
expect(resolved).toEqual({
logLevel: "Debug",
mode: "web",
port: 8788,
cwd: process.cwd(),
baseDir,
...derivedPaths,
host: "127.0.0.1",
staticDir: undefined,
devUrl: new URL("http://127.0.0.1:4173"),
noBrowser: true,
authToken: "flag-token",
autoBootstrapProjectFromCwd: true,
logWebSocketEvents: true,
});
}),
);
it.effect("uses bootstrap envelope values as fallbacks when flags and env are absent", () =>
Effect.gen(function* () {
const { join } = yield* Path.Path;
const baseDir = "/tmp/t3-bootstrap-home";
const fd = yield* openBootstrapFd({
mode: "desktop",
port: 4888,
host: "127.0.0.2",
t3Home: baseDir,
devUrl: "http://127.0.0.1:5173",
noBrowser: true,
authToken: "bootstrap-token",
autoBootstrapProjectFromCwd: false,
logWebSocketEvents: true,
});
const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:5173"));
const resolved = yield* resolveServerConfig(
{
mode: Option.none(),
port: Option.none(),
host: Option.none(),
baseDir: Option.none(),
devUrl: Option.none(),
noBrowser: Option.none(),
authToken: Option.none(),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.none(),
logWebSocketEvents: Option.none(),
},
Option.none(),
).pipe(
Effect.provide(
Layer.mergeAll(
ConfigProvider.layer(
ConfigProvider.fromEnv({
env: {
T3CODE_BOOTSTRAP_FD: String(fd),
},
}),
),
NetService.layer,
),
),
);
expect(resolved).toEqual({
logLevel: "Info",
mode: "desktop",
port: 4888,
cwd: process.cwd(),
baseDir,
...derivedPaths,
host: "127.0.0.2",
staticDir: undefined,
devUrl: new URL("http://127.0.0.1:5173"),
noBrowser: true,
authToken: "bootstrap-token",
autoBootstrapProjectFromCwd: false,
logWebSocketEvents: true,
});
assert.equal(join(baseDir, "dev"), resolved.stateDir);
}),
);
it.effect("creates derived runtime directories during config resolution", () =>
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-cli-config-dirs-" });
const resolved = yield* resolveServerConfig(
{
mode: Option.some("desktop"),
port: Option.some(4888),
host: Option.none(),
baseDir: Option.some(baseDir),
devUrl: Option.some(new URL("http://127.0.0.1:5173")),
noBrowser: Option.none(),
authToken: Option.none(),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.none(),
logWebSocketEvents: Option.none(),
},
Option.none(),
).pipe(
Effect.provide(
Layer.mergeAll(
ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })),
NetService.layer,
),
),
);
for (const directory of [
resolved.stateDir,
resolved.logsDir,
resolved.providerLogsDir,
resolved.terminalLogsDir,
resolved.attachmentsDir,
resolved.worktreesDir,
path.dirname(resolved.serverLogPath),
]) {
expect(yield* fs.exists(directory)).toBe(true);
}
}),
);
it.effect("applies flag then env precedence over bootstrap envelope values", () =>
Effect.gen(function* () {
const { join } = yield* Path.Path;
const baseDir = join(os.tmpdir(), "t3-cli-config-env-wins");
const fd = yield* openBootstrapFd({
mode: "desktop",
port: 4888,
host: "127.0.0.2",
t3Home: "/tmp/t3-bootstrap-home",
devUrl: "http://127.0.0.1:5173",
noBrowser: false,
authToken: "bootstrap-token",
autoBootstrapProjectFromCwd: false,
logWebSocketEvents: false,
});
const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:4173"));
const resolved = yield* resolveServerConfig(
{
mode: Option.none(),
port: Option.some(8788),
host: Option.some("127.0.0.1"),
baseDir: Option.none(),
devUrl: Option.some(new URL("http://127.0.0.1:4173")),
noBrowser: Option.none(),
authToken: Option.some("flag-token"),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.none(),
logWebSocketEvents: Option.none(),
},
Option.some("Debug"),
).pipe(
Effect.provide(
Layer.mergeAll(
ConfigProvider.layer(
ConfigProvider.fromEnv({
env: {
T3CODE_MODE: "web",
T3CODE_BOOTSTRAP_FD: String(fd),
T3CODE_HOME: baseDir,
T3CODE_NO_BROWSER: "true",
T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD: "true",
T3CODE_LOG_WS_EVENTS: "true",
},
}),
),
NetService.layer,
),
),
);
expect(resolved).toEqual({
logLevel: "Debug",
mode: "web",
port: 8788,
cwd: process.cwd(),
baseDir,
...derivedPaths,
host: "127.0.0.1",
staticDir: undefined,
devUrl: new URL("http://127.0.0.1:4173"),
noBrowser: true,
authToken: "flag-token",
autoBootstrapProjectFromCwd: true,
logWebSocketEvents: true,
});
}),
);
});