- Prefer `T3CODE_STATE_DIR` from env when `--state-dir` is unset or blank - Throw on invalid `T3CODE_PORT` overrides and always recompute `VITE_WS_URL` - Add tests for env/state-dir precedence, blank overrides, and invalid ports
Unified · Split
| @@ -151,8 +151,18 @@ export function parseDevRunnerArgs(rawArgs) { · 150 unmodified lines | ||
| 151 | 151 | }; |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | −function resolveStateDir(envOverrides) { | |
| 155 | − return envOverrides.T3CODE_STATE_DIR ?? DEFAULT_DEV_STATE_DIR; | |
| 154 | +function resolveStateDir(env, envOverrides) { | |
| 155 | + const overrideValue = envOverrides?.T3CODE_STATE_DIR?.trim(); | |
| 156 | + if (overrideValue) { | |
| 157 | + return overrideValue; | |
| 158 | + } | |
| 159 | + | |
| 160 | + const envValue = env?.T3CODE_STATE_DIR?.trim(); | |
| 161 | + if (envValue) { | |
| 162 | + return envValue; | |
| 163 | + } | |
| 164 | + | |
| 165 | + return DEFAULT_DEV_STATE_DIR; | |
| 156 | 166 | } |
| 157 | 167 | |
| 158 | 168 | export function createDevRunnerEnv({ mode, env, offset, envOverrides }) { |
| @@ -169,12 +179,15 @@ export function createDevRunnerEnv({ mode, env, offset, envOverrides }) { · 10 unmodified lines | ||
| 169 | 179 | ...envOverrides, |
| 170 | 180 | }; |
| 171 | 181 | |
| 172 | − output.T3CODE_STATE_DIR = resolveStateDir(envOverrides); | |
| 182 | + output.T3CODE_STATE_DIR = resolveStateDir(env, envOverrides); | |
| 173 | 183 | |
| 174 | 184 | const parsedServerPort = Number(output.T3CODE_PORT); |
| 175 | − if (Number.isInteger(parsedServerPort) && parsedServerPort > 0 && parsedServerPort <= 65535) { | |
| 176 | − output.VITE_WS_URL = `ws://localhost:${parsedServerPort}`; | |
| 185 | + if (!Number.isInteger(parsedServerPort) || parsedServerPort < 1 || parsedServerPort > 65535) { | |
| 186 | + throw new Error( | |
| 187 | + `Invalid T3CODE_PORT override: '${String(output.T3CODE_PORT)}'. Expected an integer between 1 and 65535.`, | |
| 188 | + ); | |
| 177 | 189 | } |
| 190 | + output.VITE_WS_URL = `ws://localhost:${parsedServerPort}`; | |
| 178 | 191 | |
| 179 | 192 | if (mode === "dev" || mode === "dev:server" || mode === "dev:web") { |
| 180 | 193 | // Running server/web in browser mode should not inherit desktop launcher state. |
| @@ -42,7 +42,7 @@ describe("createDevRunnerEnv", () => { · 41 unmodified lines | ||
| 42 | 42 | it("defaults state dir to ~/.t3/dev when not provided", () => { |
| 43 | 43 | const env = createDevRunnerEnv({ |
| 44 | 44 | mode: "dev", |
| 45 | − env: { T3CODE_STATE_DIR: "/tmp/prod-state" }, | |
| 45 | + env: {}, | |
| 46 | 46 | offset: 0, |
| 47 | 47 | envOverrides: {}, |
| 48 | 48 | }); |
| @@ -50,6 +50,17 @@ describe("createDevRunnerEnv", () => { · 1 unmodified line | ||
| 50 | 50 | expect(env.T3CODE_STATE_DIR).toBe(DEFAULT_DEV_STATE_DIR); |
| 51 | 51 | }); |
| 52 | 52 | |
| 53 | + it("uses existing env state dir when --state-dir is not provided", () => { | |
| 54 | + const env = createDevRunnerEnv({ | |
| 55 | + mode: "dev:server", | |
| 56 | + env: { T3CODE_STATE_DIR: "/tmp/existing-state" }, | |
| 57 | + offset: 0, | |
| 58 | + envOverrides: {}, | |
| 59 | + }); | |
| 60 | + | |
| 61 | + expect(env.T3CODE_STATE_DIR).toBe("/tmp/existing-state"); | |
| 62 | + }); | |
| 63 | + | |
| 53 | 64 | it("lets --state-dir override existing env state dir", () => { |
| 54 | 65 | const env = createDevRunnerEnv({ |
| 55 | 66 | mode: "dev:server", |
| @@ -61,6 +72,17 @@ describe("createDevRunnerEnv", () => { · 5 unmodified lines | ||
| 61 | 72 | expect(env.T3CODE_STATE_DIR).toBe("/tmp/override-state"); |
| 62 | 73 | }); |
| 63 | 74 | |
| 75 | + it("treats whitespace-only --state-dir as missing and falls back to env/default", () => { | |
| 76 | + const env = createDevRunnerEnv({ | |
| 77 | + mode: "dev:server", | |
| 78 | + env: { T3CODE_STATE_DIR: "/tmp/existing-state" }, | |
| 79 | + offset: 0, | |
| 80 | + envOverrides: { T3CODE_STATE_DIR: " " }, | |
| 81 | + }); | |
| 82 | + | |
| 83 | + expect(env.T3CODE_STATE_DIR).toBe("/tmp/existing-state"); | |
| 84 | + }); | |
| 85 | + | |
| 64 | 86 | it("recomputes websocket url when port is overridden", () => { |
| 65 | 87 | const env = createDevRunnerEnv({ |
| 66 | 88 | mode: "dev", |
| @@ -89,4 +111,15 @@ describe("createDevRunnerEnv", () => { · 22 unmodified lines | ||
| 89 | 111 | expect(env.T3CODE_NO_BROWSER).toBe("1"); |
| 90 | 112 | expect(env.T3CODE_AUTH_TOKEN).toBe("cli-token"); |
| 91 | 113 | }); |
| 114 | + | |
| 115 | + it("fails fast for invalid port overrides", () => { | |
| 116 | + expect(() => | |
| 117 | + createDevRunnerEnv({ | |
| 118 | + mode: "dev", | |
| 119 | + env: {}, | |
| 120 | + offset: 0, | |
| 121 | + envOverrides: { T3CODE_PORT: "not-a-port" }, | |
| 122 | + }), | |
| 123 | + ).toThrow("Invalid T3CODE_PORT override"); | |
| 124 | + }); | |
| 92 | 125 | }); |