From c6be50ca83ce8ceaf9fa99d71aa098edfd41fbfa Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Fri, 11 Mar 2022 19:41:08 +0900 Subject: [PATCH 1/2] feat: throw error on unused args --- src/CAC.ts | 8 +++++++- src/Command.ts | 16 ++++++++++++++++ src/__test__/index.test.ts | 10 ++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/CAC.ts b/src/CAC.ts index 7a3df11a..c4c4e987 100644 --- a/src/CAC.ts +++ b/src/CAC.ts @@ -220,7 +220,11 @@ class CAC extends EventEmitter { this.unsetMatchedCommand() } - if (this.options.version && this.showVersionOnExit && this.matchedCommandName == null) { + if ( + this.options.version && + this.showVersionOnExit && + this.matchedCommandName == null + ) { this.outputVersion() run = false this.unsetMatchedCommand() @@ -328,6 +332,8 @@ class CAC extends EventEmitter { command.checkRequiredArgs() + command.checkUnusedArgs() + const actionArgs: any[] = [] command.args.forEach((arg, index) => { if (arg.variadic) { diff --git a/src/Command.ts b/src/Command.ts index 93027972..d7f1aeac 100644 --- a/src/Command.ts +++ b/src/Command.ts @@ -295,6 +295,22 @@ class Command { } } } + + /** + * Check if the number of args is more than expected + */ + checkUnusedArgs() { + const hasVariadicArg = this.args.some((arg) => arg.variadic) + const maximumArgsCount = hasVariadicArg ? Infinity : this.args.length + + if (maximumArgsCount < this.cli.args.length) { + const argsString = this.cli.args + .slice(maximumArgsCount) + .map((arg) => `\`${arg}\``) + .join(', ') + throw new CACError(`Unused args: ${argsString}`) + } + } } class GlobalCommand extends Command { diff --git a/src/__test__/index.test.ts b/src/__test__/index.test.ts index 6cb84069..7bbd5905 100644 --- a/src/__test__/index.test.ts +++ b/src/__test__/index.test.ts @@ -165,6 +165,16 @@ test('throw on unknown options', () => { }).toThrowError('Unknown option `--xx`') }) +test('throw on unused args', () => { + const cli = cac() + + cli.command('build [entry]', 'Build your app').action(() => {}) + + expect(() => { + cli.parse(`node bin build app.js foo bar`.split(' ')) + }).toThrowError('Unused args: `foo`, `bar`') +}) + describe('--version in help message', () => { test('sub command', async () => { const output = await getOutput('help.js', ['lint', '--help']) From 92051f26e86edd02b858b5b6e17c605a34fcc96e Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:35:26 +0900 Subject: [PATCH 2/2] chore: fix build --- src/command.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.ts b/src/command.ts index 9f2a1dcb..33058597 100644 --- a/src/command.ts +++ b/src/command.ts @@ -311,7 +311,7 @@ export class Command { /** * Check if the number of args is more than expected */ - checkUnusedArgs() { + checkUnusedArgs(): void { const hasVariadicArg = this.args.some((arg) => arg.variadic) const maximumArgsCount = hasVariadicArg ? Infinity : this.args.length