| author | |
| committer | |
| log | 27c2b145f8d214b5c578eefc463278d0916fb048 |
| tree | 6fc4853e053d67f3898c2f819a1dc42331346128 |
| parent | 8515f02770a05d5f1c0f740c5223938fb6ab102b |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>2 files changed, 22 insertions(+), 3 deletions(-)
apps/server/src/cli-config.test.ts+9| ... | ... | @@ -40,6 +40,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 40 | 40 | port: Option.none(), |
| 41 | 41 | host: Option.none(), |
| 42 | 42 | baseDir: Option.none(), |
| 43 | cwd: Option.none(), | |
| 43 | 44 | devUrl: Option.none(), |
| 44 | 45 | noBrowser: Option.none(), |
| 45 | 46 | authToken: Option.none(), |
| ... | ... | @@ -102,6 +103,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 102 | 103 | port: Option.some(8788), |
| 103 | 104 | host: Option.some("127.0.0.1"), |
| 104 | 105 | baseDir: Option.some(baseDir), |
| 106 | cwd: Option.none(), | |
| 105 | 107 | devUrl: Option.some(new URL("http://127.0.0.1:4173")), |
| 106 | 108 | noBrowser: Option.some(true), |
| 107 | 109 | authToken: Option.some("flag-token"), |
| ... | ... | @@ -178,6 +180,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 178 | 180 | port: Option.none(), |
| 179 | 181 | host: Option.none(), |
| 180 | 182 | baseDir: Option.none(), |
| 183 | cwd: Option.none(), | |
| 181 | 184 | devUrl: Option.none(), |
| 182 | 185 | noBrowser: Option.none(), |
| 183 | 186 | authToken: Option.none(), |
| ... | ... | @@ -228,6 +231,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 228 | 231 | const fs = yield* FileSystem.FileSystem; |
| 229 | 232 | const path = yield* Path.Path; |
| 230 | 233 | const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-cli-config-dirs-" }); |
| 234 | const customCwd = path.join(baseDir, "nested", "project"); | |
| 231 | 235 | |
| 232 | 236 | const resolved = yield* resolveServerConfig( |
| 233 | 237 | { |
| ... | ... | @@ -235,6 +239,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 235 | 239 | port: Option.some(4888), |
| 236 | 240 | host: Option.none(), |
| 237 | 241 | baseDir: Option.some(baseDir), |
| 242 | cwd: Option.some(customCwd), | |
| 238 | 243 | devUrl: Option.some(new URL("http://127.0.0.1:5173")), |
| 239 | 244 | noBrowser: Option.none(), |
| 240 | 245 | authToken: Option.none(), |
| ... | ... | @@ -253,6 +258,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 253 | 258 | ); |
| 254 | 259 | |
| 255 | 260 | for (const directory of [ |
| 261 | customCwd, | |
| 256 | 262 | resolved.stateDir, |
| 257 | 263 | resolved.logsDir, |
| 258 | 264 | resolved.providerLogsDir, |
| ... | ... | @@ -264,6 +270,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 264 | 270 | ]) { |
| 265 | 271 | expect(yield* fs.exists(directory)).toBe(true); |
| 266 | 272 | } |
| 273 | expect(resolved.cwd).toBe(path.resolve(customCwd)); | |
| 267 | 274 | }), |
| 268 | 275 | ); |
| 269 | 276 | |
| ... | ... | @@ -290,6 +297,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 290 | 297 | port: Option.some(8788), |
| 291 | 298 | host: Option.some("127.0.0.1"), |
| 292 | 299 | baseDir: Option.none(), |
| 300 | cwd: Option.none(), | |
| 293 | 301 | devUrl: Option.some(new URL("http://127.0.0.1:4173")), |
| 294 | 302 | noBrowser: Option.none(), |
| 295 | 303 | authToken: Option.some("flag-token"), |
| ... | ... | @@ -360,6 +368,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 360 | 368 | port: Option.some(4888), |
| 361 | 369 | host: Option.none(), |
| 362 | 370 | baseDir: Option.some(baseDir), |
| 371 | cwd: Option.none(), | |
| 363 | 372 | devUrl: Option.none(), |
| 364 | 373 | noBrowser: Option.none(), |
| 365 | 374 | authToken: Option.none(), |
apps/server/src/cli.ts+13-3| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | import { NetService } from "@t3tools/shared/Net"; |
| 2 | 2 | import { parsePersistedServerObservabilitySettings } from "@t3tools/shared/serverSettings"; |
| 3 | 3 | import { Config, Effect, FileSystem, LogLevel, Option, Path, Schema } from "effect"; |
| 4 | import { Command, Flag, GlobalFlag } from "effect/unstable/cli"; | |
| 4 | import { Argument, Command, Flag, GlobalFlag } from "effect/unstable/cli"; | |
| 5 | 5 | |
| 6 | 6 | import { |
| 7 | 7 | DEFAULT_PORT, |
| ... | ... | @@ -13,7 +13,7 @@ import { |
| 13 | 13 | type ServerConfigShape, |
| 14 | 14 | } from "./config"; |
| 15 | 15 | import { readBootstrapEnvelope } from "./bootstrap"; |
| 16 | import { resolveBaseDir } from "./os-jank"; | |
| 16 | import { expandHomePath, resolveBaseDir } from "./os-jank"; | |
| 17 | 17 | import { runServer } from "./server"; |
| 18 | 18 | |
| 19 | 19 | const PortSchema = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 65535 })); |
| ... | ... | @@ -140,6 +140,7 @@ interface CliServerFlags { |
| 140 | 140 | readonly port: Option.Option<number>; |
| 141 | 141 | readonly host: Option.Option<string>; |
| 142 | 142 | readonly baseDir: Option.Option<string>; |
| 143 | readonly cwd: Option.Option<string>; | |
| 143 | 144 | readonly devUrl: Option.Option<URL>; |
| 144 | 145 | readonly noBrowser: Option.Option<boolean>; |
| 145 | 146 | readonly authToken: Option.Option<string>; |
| ... | ... | @@ -225,6 +226,9 @@ export const resolveServerConfig = ( |
| 225 | 226 | ), |
| 226 | 227 | ), |
| 227 | 228 | ); |
| 229 | const rawCwd = Option.getOrElse(flags.cwd, () => process.cwd()); | |
| 230 | const cwd = path.resolve(yield* expandHomePath(rawCwd.trim())); | |
| 231 | yield* fs.makeDirectory(cwd, { recursive: true }); | |
| 228 | 232 | const derivedPaths = yield* deriveServerPaths(baseDir, devUrl); |
| 229 | 233 | yield* ensureServerDirectories(derivedPaths); |
| 230 | 234 | const persistedObservabilitySettings = yield* loadPersistedObservabilitySettings( |
| ... | ... | @@ -315,7 +319,7 @@ export const resolveServerConfig = ( |
| 315 | 319 | otlpServiceName: env.otlpServiceName, |
| 316 | 320 | mode, |
| 317 | 321 | port, |
| 318 | cwd: process.cwd(), | |
| 322 | cwd, | |
| 319 | 323 | baseDir, |
| 320 | 324 | ...derivedPaths, |
| 321 | 325 | serverTracePath, |
| ... | ... | @@ -336,6 +340,12 @@ const commandFlags = { |
| 336 | 340 | port: portFlag, |
| 337 | 341 | host: hostFlag, |
| 338 | 342 | baseDir: baseDirFlag, |
| 343 | cwd: Argument.string("cwd").pipe( | |
| 344 | Argument.withDescription( | |
| 345 | "Working directory for provider sessions (defaults to the current directory).", | |
| 346 | ), | |
| 347 | Argument.optional, | |
| 348 | ), | |
| 339 | 349 | devUrl: devUrlFlag, |
| 340 | 350 | noBrowser: noBrowserFlag, |
| 341 | 351 | authToken: authTokenFlag, |