From 30c2e44a0824b8e58822eebe2adc07597bed7a5b Mon Sep 17 00:00:00 2001 From: weareoutman Date: Fri, 27 Nov 2020 17:20:26 +0800 Subject: [PATCH] Add `allowUnknownFlags` options --- index.d.ts | 7 +++++++ index.js | 19 +++++++++++++++++ readme.md | 7 +++++++ test/allow-unkonwn-flags.js | 22 ++++++++++++++++++++ test/fixtures/fixture-allow-unknown-flags.js | 19 +++++++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 test/allow-unkonwn-flags.js create mode 100755 test/fixtures/fixture-allow-unknown-flags.js diff --git a/index.d.ts b/index.d.ts index df3f10e..ad9bf13 100644 --- a/index.d.ts +++ b/index.d.ts @@ -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 = diff --git a/index.js b/index.js index dccbcb5..b1720e9 100644 --- a/index.js +++ b/index.js @@ -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 = {}; @@ -110,6 +115,7 @@ const meow = (helpText, options) => { autoVersion: true, booleanDefault: false, hardRejection: true, + allowUnknownFlags: true, ...options }; @@ -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); @@ -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}; diff --git a/readme.md b/readme.md index a8c9285..cf41b60 100644 --- a/readme.md +++ b/readme.md @@ -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. diff --git a/test/allow-unkonwn-flags.js b/test/allow-unkonwn-flags.js new file mode 100644 index 0000000..fd24c11 --- /dev/null +++ b/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'); +}); diff --git a/test/fixtures/fixture-allow-unknown-flags.js b/test/fixtures/fixture-allow-unknown-flags.js new file mode 100755 index 0000000..131e9e9 --- /dev/null +++ b/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 + `, + allowUnknownFlags: false, + flags: { + foo: { + type: 'string' + } + } +}); + +console.log(cli.flags.foo);