diff --git a/src/cac.ts b/src/cac.ts index 16dfd22e..673afab1 100644 --- a/src/cac.ts +++ b/src/cac.ts @@ -349,6 +349,8 @@ export class CAC extends EventTarget { 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 082bfa09..33058597 100644 --- a/src/command.ts +++ b/src/command.ts @@ -307,6 +307,22 @@ export class Command { } } } + + /** + * Check if the number of args is more than expected + */ + checkUnusedArgs(): void { + 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}`) + } + } } export class GlobalCommand extends Command { diff --git a/tests/index.test.ts b/tests/index.test.ts index c9bc81fc..a2bc4e71 100644 --- a/tests/index.test.ts +++ b/tests/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.ts', ['lint', '--help'])