diff --git a/src/commands/doctor.test.ts b/src/commands/doctor.test.ts index 55f3e2e7..b497fd0b 100644 --- a/src/commands/doctor.test.ts +++ b/src/commands/doctor.test.ts @@ -89,6 +89,7 @@ function makeDoctorProgram(deps: DoctorDeps = {}): Command { const program = new Command(); program.exitOverride(); program.option('--output ', 'output', 'text'); + program.option('--request-timeout ', 'per-request timeout in seconds'); program.addCommand(createDoctorCommand(deps)); return program; } @@ -470,6 +471,22 @@ describe('createDoctorCommand wiring', () => { }); }); + it('rejects an invalid --request-timeout with the SHARED validation message', async () => { + // Guards the drift this repo's shared helper exists to prevent: the doctor + // command once carried a private copy whose message differed from every + // other command's. Same flag, same bad input, one message. + const rejection = await makeDoctorProgram() + .parseAsync(['node', 'ts', '--request-timeout', 'abc', 'doctor']) + .catch((error: unknown) => error); + expect(rejection).toBeInstanceOf(ApiError); + expect(rejection).toMatchObject({ + code: 'VALIDATION_ERROR', + exitCode: 5, + nextAction: + 'Flag `--request-timeout` is invalid: "abc" is not valid — must be a positive number of seconds.', + }); + }); + it('accepts valid --output modes through command wiring', async () => { writeProfile('default', { apiKey: 'sk-user-abc' }, { path: credentialsPath }); for (const mode of ['text', 'json'] as const) { diff --git a/src/commands/doctor.ts b/src/commands/doctor.ts index bf653043..3d812ad3 100644 --- a/src/commands/doctor.ts +++ b/src/commands/doctor.ts @@ -19,6 +19,7 @@ import { Command } from 'commander'; import { assertValidEndpointUrl, makeHttpClient, + parseRequestTimeoutFlag, type CommonOptions as FactoryCommonOptions, } from '../lib/client-factory.js'; import { @@ -28,13 +29,7 @@ import { normalizeEnvVar, type Config, } from '../lib/config.js'; -import { - ApiError, - CLIError, - InterruptError, - RequestTimeoutError, - localValidationError, -} from '../lib/errors.js'; +import { ApiError, CLIError, InterruptError, RequestTimeoutError } from '../lib/errors.js'; import type { FetchImpl } from '../lib/http.js'; import { globalShutdown } from '../lib/interrupt.js'; import type { CliOrgBinding, CliOrgSummary } from '../lib/org-render.js'; @@ -504,20 +499,6 @@ function resolveCommonOptions(command: Command, env?: NodeJS.ProcessEnv): Common }; } -function parseRequestTimeoutFlag(raw: string | undefined): number | undefined { - if (raw === undefined) return undefined; - const seconds = Number(raw); - if (!Number.isFinite(seconds) || seconds <= 0) { - // Match the other commands: a malformed --request-timeout is a validation - // error, not a silently-ignored default. - throw localValidationError( - 'request-timeout', - `must be a positive number of seconds (got "${raw}")`, - ); - } - return Math.round(seconds * 1000); -} - function makeOutput(mode: OutputMode, deps: DoctorDeps): Output { return new Output(mode, { stdout: deps.stdout, stderr: deps.stderr }); }