diff --git a/.changeset/calm-globals-context.md b/.changeset/calm-globals-context.md new file mode 100644 index 0000000..0bbd07b --- /dev/null +++ b/.changeset/calm-globals-context.md @@ -0,0 +1,5 @@ +--- +'incur': patch +--- + +Fixed parsed global options missing from command handler contexts. diff --git a/src/Cli.test-d.ts b/src/Cli.test-d.ts index d4edbc7..43cda71 100644 --- a/src/Cli.test-d.ts +++ b/src/Cli.test-d.ts @@ -500,6 +500,31 @@ test('globals type flows to middleware context', () => { }) }) +test('globals type flows to command contexts', () => { + Cli.create('test', { + globals: z.object({ apiKey: z.string().optional() }), + }).command('ping', { + middleware: [ + (c, next) => { + expectTypeOf(c.globals.apiKey).toEqualTypeOf() + return next() + }, + ], + run(c) { + expectTypeOf(c.globals.apiKey).toEqualTypeOf() + return {} + }, + }) + + Cli.create('test', { + globals: z.object({ apiKey: z.string().optional() }), + run(c) { + expectTypeOf(c.globals.apiKey).toEqualTypeOf() + return {} + }, + }) +}) + test('globalAlias keys are constrained to globals schema keys', () => { Cli.create('test', { globals: z.object({ apiKey: z.string() }), diff --git a/src/Cli.test.ts b/src/Cli.test.ts index 3e80012..c3a4e32 100644 --- a/src/Cli.test.ts +++ b/src/Cli.test.ts @@ -6081,6 +6081,31 @@ describe('displayName', () => { }) describe('globals', () => { + test('globals are parsed and available in command handlers', async () => { + const cli = Cli.create('test', { + globals: z.object({ rpcUrl: z.string() }), + }).command('ping', { + run(c) { + return { url: c.globals.rpcUrl } + }, + }) + + const { output } = await serve(cli, ['--rpc-url', 'http://example.com', 'ping', '--json']) + expect(JSON.parse(output)).toEqual({ url: 'http://example.com' }) + }) + + test('globals are parsed and available in root handlers', async () => { + const cli = Cli.create('test', { + globals: z.object({ rpcUrl: z.string() }), + run(c) { + return { url: c.globals.rpcUrl } + }, + }) + + const { output } = await serve(cli, ['--rpc-url', 'http://example.com', '--json']) + expect(JSON.parse(output)).toEqual({ url: 'http://example.com' }) + }) + test('globals are parsed and available in middleware', async () => { const cli = Cli.create('test', { globals: z.object({ rpcUrl: z.string() }), diff --git a/src/Cli.ts b/src/Cli.ts index b12f7d5..dca5c59 100644 --- a/src/Cli.ts +++ b/src/Cli.ts @@ -59,7 +59,7 @@ export type Cli< const output extends z.ZodType | undefined = undefined, >( name: name, - definition: CommandDefinition, + definition: CommandDefinition, ): Cli< commands & { [key in name]: { args: InferOutput; options: InferOutput } }, vars, @@ -571,6 +571,8 @@ export declare namespace create { format: Formatter.Format /** Whether the user explicitly passed `--format` or `--json`. */ formatExplicit: boolean + /** Parsed global options from the CLI-level globals schema. */ + globals: InferOutput /** The CLI name. */ name: string /** Return a success result with optional metadata (e.g. CTAs). */ @@ -3664,6 +3666,7 @@ type CommandDefinition< output extends z.ZodType | undefined = undefined, vars extends z.ZodObject | undefined = undefined, cliEnv extends z.ZodObject | undefined = undefined, + globals extends z.ZodObject | undefined = undefined, > = CommandMeta & { /** Alternative names for this command (e.g. `['extensions', 'ext']` for an `extension` command). */ aliases?: string[] | undefined @@ -3706,7 +3709,7 @@ type CommandDefinition< */ outputPolicy?: OutputPolicy | undefined /** Middleware that runs only for this command, after root and group middleware. */ - middleware?: MiddlewareHandler[] | undefined + middleware?: MiddlewareHandler[] | undefined /** Alternative usage patterns shown in help output. */ usage?: Usage[] | undefined /** The command handler. Return a value for single-return, or use `async *run` to stream chunks. */ @@ -3731,6 +3734,8 @@ type CommandDefinition< format: Formatter.Format /** Whether the user explicitly passed `--format` or `--json`. */ formatExplicit: boolean + /** Parsed global options from the CLI-level globals schema. */ + globals: InferOutput /** The CLI name. */ name: string /** Return a success result with optional metadata (e.g. CTAs). */ diff --git a/src/internal/command.ts b/src/internal/command.ts index 7b29830..01f2c4a 100644 --- a/src/internal/command.ts +++ b/src/internal/command.ts @@ -113,6 +113,7 @@ export async function execute(command: any, options: execute.Options): Promise