Skip to content

Commit

Permalink
Add allowUnknownFlags options
Browse files Browse the repository at this point in the history
  • Loading branch information
weareoutman committed Dec 23, 2020
1 parent a0ce744 commit 30c2e44
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 0 deletions.
7 changes: 7 additions & 0 deletions index.d.ts
Expand Up @@ -199,6 +199,13 @@ declare namespace meow {
@default true
*/
readonly hardRejection?: boolean;

/**
Whether to allow unknown flags or not.
@default true
*/
readonly allowUnknownFlags?: boolean;
}

type TypedFlag<Flag extends AnyFlag> =
Expand Down
19 changes: 19 additions & 0 deletions index.js
Expand Up @@ -54,6 +54,11 @@ const reportMissingRequiredFlags = missingRequiredFlags => {
}
};

const reportUnknownFlags = unknownFlags => {
console.error(`Unknown flag${unknownFlags.length > 1 ? 's' : ''}`);
console.error(unknownFlags.join('\n'));
};

const buildParserFlags = ({flags, booleanDefault}) => {
const parserFlags = {};

Expand Down Expand Up @@ -110,6 +115,7 @@ const meow = (helpText, options) => {
autoVersion: true,
booleanDefault: false,
hardRejection: true,
allowUnknownFlags: true,
...options
};

Expand Down Expand Up @@ -139,6 +145,11 @@ const meow = (helpText, options) => {
parserOptions.configuration['populate--'] = true;
}

if (!options.allowUnknownFlags) {
// Collect unknown options in `argv._` to be checked later.
parserOptions.configuration['unknown-options-as-args'] = true;
}

const {pkg} = options;
const argv = parseArguments(options.argv, parserOptions);
let help = redent(trimNewlines((options.help || '').replace(/\t+\n*$/, '')), 2);
Expand Down Expand Up @@ -177,6 +188,14 @@ const meow = (helpText, options) => {
const input = argv._;
delete argv._;

if (!options.allowUnknownFlags) {
const unknownFlags = input.filter(item => typeof item === 'string' && item.startsWith('-'));
if (unknownFlags.length > 0) {
reportUnknownFlags(unknownFlags);
process.exit(2);
}
}

const flags = camelCaseKeys(argv, {exclude: ['--', /^\w$/]});
const unnormalizedFlags = {...flags};

Expand Down
7 changes: 7 additions & 0 deletions readme.md
Expand Up @@ -314,6 +314,13 @@ Default: `true`
Whether to use [`hard-rejection`](https://github.com/sindresorhus/hard-rejection) or not. Disabling this can be useful if you need to handle `process.on('unhandledRejection')` yourself.
#### allowUnknownFlags
Type `boolean`\
Default: `true`
Whether to allow unknown flags or not.
## Promises
Meow will make unhandled rejected promises [fail hard](https://github.com/sindresorhus/hard-rejection) instead of the default silent fail. Meaning you don't have to manually `.catch()` promises used in your CLI.
Expand Down
22 changes: 22 additions & 0 deletions test/allow-unkonwn-flags.js
@@ -0,0 +1,22 @@
import path from 'path';
import test from 'ava';
import execa from 'execa';

const fixtureAllowUnknownFlags = path.join(__dirname, 'fixtures', 'fixture-allow-unknown-flags.js');

test('spawn CLI and test specifying unknown flags', async t => {
const error = await t.throwsAsync(
execa(fixtureAllowUnknownFlags, ['--foo', 'bar', '--unspecified-a', '--unspecified-b', 'input-is-allowed'])
);
const {stderr, message} = error;
t.regex(message, /Command failed with exit code 2/);
t.regex(stderr, /Unknown flag/);
t.regex(stderr, /--unspecified-a/);
t.regex(stderr, /--unspecified-b/);
t.notRegex(stderr, /input-is-allowed/);
});

test('spawn CLI and test specifying known flags', async t => {
const {stdout} = await execa(fixtureAllowUnknownFlags, ['--foo', 'bar']);
t.is(stdout, 'bar');
});
19 changes: 19 additions & 0 deletions test/fixtures/fixture-allow-unknown-flags.js
@@ -0,0 +1,19 @@
#!/usr/bin/env node
'use strict';
const meow = require('../..');

const cli = meow({
description: 'Custom description',
help: `
Usage
foo <input>
`,
allowUnknownFlags: false,
flags: {
foo: {
type: 'string'
}
}
});

console.log(cli.flags.foo);

0 comments on commit 30c2e44

Please sign in to comment.