diff --git a/apps/server/src/environment/ServerEnvironmentLabel.test.ts b/apps/server/src/environment/ServerEnvironmentLabel.test.ts index 6fc06b889dbc7..34b584735be80 100644 --- a/apps/server/src/environment/ServerEnvironmentLabel.test.ts +++ b/apps/server/src/environment/ServerEnvironmentLabel.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, it } from "@effect/vitest"; +import * as ConfigProvider from "effect/ConfigProvider"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; @@ -55,12 +56,53 @@ const withHostPlatform = ( Layer.succeed(HostProcessPlatform, platform), Layer.succeed(HostProcessHostname, hostname), ); +const withEnvironmentLabel = ( + layer: Layer.Layer, + platform: NodeJS.Platform, + hostname: string, + environmentLabel: string, +) => + Layer.merge( + withHostPlatform(layer, platform, hostname), + ConfigProvider.layer( + ConfigProvider.fromEnv({ env: { T3CODE_ENVIRONMENT_LABEL: environmentLabel } }), + ), + ); afterEach(() => { runMock.mockReset(); }); describe("resolveServerEnvironmentLabel", () => { + it.effect("prefers and trims a configured environment label", () => + Effect.gen(function* () { + const result = yield* ServerEnvironmentLabel.resolveServerEnvironmentLabel({ + cwdBaseName: "t3code", + }).pipe( + Effect.provide( + withEnvironmentLabel(LinuxMachineInfoLayer, "linux", "buildbox", " Build server "), + ), + ); + + expect(result).toBe("Build server"); + expect(runMock).not.toHaveBeenCalled(); + }), + ); + + it.effect("ignores empty configured environment labels", () => + Effect.gen(function* () { + for (const environmentLabel of ["", " \t "]) { + const result = yield* ServerEnvironmentLabel.resolveServerEnvironmentLabel({ + cwdBaseName: "t3code", + }).pipe( + Effect.provide(withEnvironmentLabel(TestLayer, "win32", "macbook-pro", environmentLabel)), + ); + + expect(result).toBe("macbook-pro"); + } + }), + ); + it.effect("uses hostname fallback regardless of launch mode", () => Effect.gen(function* () { const result = yield* ServerEnvironmentLabel.resolveServerEnvironmentLabel({ diff --git a/apps/server/src/environment/ServerEnvironmentLabel.ts b/apps/server/src/environment/ServerEnvironmentLabel.ts index 1d944492331af..10054afc9875c 100644 --- a/apps/server/src/environment/ServerEnvironmentLabel.ts +++ b/apps/server/src/environment/ServerEnvironmentLabel.ts @@ -1,4 +1,5 @@ import { HostProcessHostname, HostProcessPlatform } from "@t3tools/shared/hostProcess"; +import * as Config from "effect/Config"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Option from "effect/Option"; @@ -182,6 +183,13 @@ const resolveFriendlyHostLabel = Effect.fn("resolveFriendlyHostLabel")(function* export const resolveServerEnvironmentLabel = Effect.fn("resolveServerEnvironmentLabel")(function* ( input: ResolveServerEnvironmentLabelInput, ) { + const configuredLabel = normalizeLabel( + Option.getOrUndefined(yield* Config.String("T3CODE_ENVIRONMENT_LABEL").pipe(Config.option)), + ); + if (configuredLabel) { + return configuredLabel; + } + const friendlyHostLabel = yield* resolveFriendlyHostLabel(); if (friendlyHostLabel) { return friendlyHostLabel; diff --git a/docs/user/install.md b/docs/user/install.md index 2a7e7dc7e749c..86844136c9a7e 100644 --- a/docs/user/install.md +++ b/docs/user/install.md @@ -33,6 +33,15 @@ line to add. Set `T3CODE_CHANNEL=nightly` to install the nightly train, or | Move to the newest release | `t3 update` | | Remove it again | `t3 uninstall` | +Set `T3CODE_ENVIRONMENT_LABEL` in the server process environment to override the environment name +shown to connected clients: + +```sh +T3CODE_ENVIRONMENT_LABEL="Development VM" t3 serve +``` + +Empty or whitespace-only values use the normal automatically detected label. + Run `t3 --help` for the full reference. To try T3 Code once without installing it, run `npx t3@latest` instead (needs