pax_global_header 0000666 0000000 0000000 00000000064 13746371342 0014524 g ustar 00root root 0000000 0000000 52 comment=a1f5f0fb16057e137259607565a319e5d3e2152b
meow-8.0.0/ 0000775 0000000 0000000 00000000000 13746371342 0012500 5 ustar 00root root 0000000 0000000 meow-8.0.0/.editorconfig 0000664 0000000 0000000 00000000257 13746371342 0015161 0 ustar 00root root 0000000 0000000 root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.yml]
indent_style = space
indent_size = 2
meow-8.0.0/.gitattributes 0000664 0000000 0000000 00000000023 13746371342 0015366 0 ustar 00root root 0000000 0000000 * text=auto eol=lf
meow-8.0.0/.github/ 0000775 0000000 0000000 00000000000 13746371342 0014040 5 ustar 00root root 0000000 0000000 meow-8.0.0/.github/funding.yml 0000664 0000000 0000000 00000000156 13746371342 0016217 0 ustar 00root root 0000000 0000000 github: sindresorhus
open_collective: sindresorhus
tidelift: npm/meow
custom: https://sindresorhus.com/donate
meow-8.0.0/.github/security.md 0000664 0000000 0000000 00000000263 13746371342 0016232 0 ustar 00root root 0000000 0000000 # Security Policy
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
meow-8.0.0/.gitignore 0000664 0000000 0000000 00000000027 13746371342 0014467 0 ustar 00root root 0000000 0000000 node_modules
yarn.lock
meow-8.0.0/.npmrc 0000664 0000000 0000000 00000000023 13746371342 0013613 0 ustar 00root root 0000000 0000000 package-lock=false
meow-8.0.0/.travis.yml 0000664 0000000 0000000 00000000066 13746371342 0014613 0 ustar 00root root 0000000 0000000 language: node_js
node_js:
- '14'
- '12'
- '10'
meow-8.0.0/estest/ 0000775 0000000 0000000 00000000000 13746371342 0014007 5 ustar 00root root 0000000 0000000 meow-8.0.0/estest/index.js 0000664 0000000 0000000 00000000506 13746371342 0015455 0 ustar 00root root 0000000 0000000 import {createRequire} from 'module';
const meow = createRequire(import.meta.url)('../index.js');
meow(`
Usage
$ estest
Options
--rainbow, -r Include a rainbow
Examples
$ estest unicorns --rainbow
🌈 unicorns 🌈
`,
{
flags: {
rainbow: {
type: 'boolean',
alias: 'r'
}
}
}
);
meow-8.0.0/estest/package.json 0000664 0000000 0000000 00000000076 13746371342 0016300 0 ustar 00root root 0000000 0000000 {
"name": "estest",
"type": "module",
"version": "1.2.3"
}
meow-8.0.0/index.d.ts 0000664 0000000 0000000 00000016735 13746371342 0014415 0 ustar 00root root 0000000 0000000 import {PackageJson} from 'type-fest';
declare namespace meow {
type FlagType = 'string' | 'boolean' | 'number';
/**
Callback function to determine if a flag is required during runtime.
@param flags - Contains the flags converted to camel-case excluding aliases.
@param input - Contains the non-flag arguments.
@returns True if the flag is required, otherwise false.
*/
type IsRequiredPredicate = (flags: Readonly, input: readonly string[]) => boolean;
interface Flag {
readonly type?: Type;
readonly alias?: string;
readonly default?: Default;
readonly isRequired?: boolean | IsRequiredPredicate;
readonly isMultiple?: boolean;
}
type StringFlag = Flag<'string', string>;
type BooleanFlag = Flag<'boolean', boolean>;
type NumberFlag = Flag<'number', number>;
type AnyFlag = StringFlag | BooleanFlag | NumberFlag;
type AnyFlags = Record;
interface Options {
/**
Define argument flags.
The key is the flag name and the value is an object with any of:
- `type`: Type of value. (Possible values: `string` `boolean` `number`)
- `alias`: Usually used to define a short flag alias.
- `default`: Default value when the flag is not specified.
- `isRequired`: Determine if the flag is required.
If it's only known at runtime whether the flag is required or not you can pass a Function instead of a boolean, which based on the given flags and other non-flag arguments should decide if the flag is required.
- `isMultiple`: Indicates a flag can be set multiple times. Values are turned into an array. (Default: false)
Multiple values are provided by specifying the flag multiple times, for example, `$ foo -u rainbow -u cat`. Space- or comma-separated values are *not* supported.
@example
```
flags: {
unicorn: {
type: 'string',
alias: 'u',
default: ['rainbow', 'cat'],
isMultiple: true,
isRequired: (flags, input) => {
if (flags.otherFlag) {
return true;
}
return false;
}
}
}
```
*/
readonly flags?: Flags;
/**
Description to show above the help text. Default: The package.json `"description"` property.
Set it to `false` to disable it altogether.
*/
readonly description?: string | false;
/**
The help text you want shown.
The input is reindented and starting/ending newlines are trimmed which means you can use a [template literal](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/template_strings) without having to care about using the correct amount of indent.
The description will be shown above your help text automatically.
Set it to `false` to disable it altogether.
*/
readonly help?: string | false;
/**
Set a custom version output. Default: The package.json `"version"` property.
Set it to `false` to disable it altogether.
*/
readonly version?: string | false;
/**
Automatically show the help text when the `--help` flag is present. Useful to set this value to `false` when a CLI manages child CLIs with their own help text.
This option is only considered when there is only one argument in `process.argv`.
*/
readonly autoHelp?: boolean;
/**
Automatically show the version text when the `--version` flag is present. Useful to set this value to `false` when a CLI manages child CLIs with their own version text.
This option is only considered when there is only one argument in `process.argv`.
*/
readonly autoVersion?: boolean;
/**
`package.json` as an `Object`. Default: Closest `package.json` upwards.
_You most likely don't need this option._
*/
readonly pkg?: Record;
/**
Custom arguments object.
@default process.argv.slice(2)
*/
readonly argv?: readonly string[];
/**
Infer the argument type.
By default, the argument `5` in `$ foo 5` becomes a string. Enabling this would infer it as a number.
@default false
*/
readonly inferType?: boolean;
/**
Value of `boolean` flags not defined in `argv`.
If set to `undefined`, the flags not defined in `argv` will be excluded from the result. The `default` value set in `boolean` flags take precedence over `booleanDefault`.
_Note: If used in conjunction with `isMultiple`, the default flag value is set to `[]`._
__Caution: Explicitly specifying `undefined` for `booleanDefault` has different meaning from omitting key itself.__
@example
```
import meow = require('meow');
const cli = meow(`
Usage
$ foo
Options
--rainbow, -r Include a rainbow
--unicorn, -u Include a unicorn
--no-sparkles Exclude sparkles
Examples
$ foo
🌈 unicorns✨🌈
`, {
booleanDefault: undefined,
flags: {
rainbow: {
type: 'boolean',
default: true,
alias: 'r'
},
unicorn: {
type: 'boolean',
default: false,
alias: 'u'
},
cake: {
type: 'boolean',
alias: 'c'
},
sparkles: {
type: 'boolean',
default: true
}
}
});
//{
// flags: {
// rainbow: true,
// unicorn: false,
// sparkles: true
// },
// unnormalizedFlags: {
// rainbow: true,
// r: true,
// unicorn: false,
// u: false,
// sparkles: true
// },
// …
//}
```
*/
readonly booleanDefault?: boolean | null | undefined;
/**
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.
@default true
*/
readonly hardRejection?: boolean;
}
type TypedFlag =
Flag extends {type: 'number'}
? number
: Flag extends {type: 'string'}
? string
: Flag extends {type: 'boolean'}
? boolean
: unknown;
type PossiblyOptionalFlag =
Flag extends {isRequired: true}
? FlagType
: Flag extends {default: any}
? FlagType
: FlagType | undefined;
type TypedFlags = {
[F in keyof Flags]: Flags[F] extends {isMultiple: true}
? PossiblyOptionalFlag>>
: PossiblyOptionalFlag>
};
interface Result {
/**
Non-flag arguments.
*/
input: string[];
/**
Flags converted to camelCase excluding aliases.
*/
flags: TypedFlags & Record;
/**
Flags converted camelCase including aliases.
*/
unnormalizedFlags: TypedFlags & Record;
/**
The `package.json` object.
*/
pkg: PackageJson;
/**
The help text used with `--help`.
*/
help: string;
/**
Show the help text and exit with code.
@param exitCode - The exit code to use. Default: `2`.
*/
showHelp: (exitCode?: number) => void;
/**
Show the version text and exit.
*/
showVersion: () => void;
}
}
/**
@param helpMessage - Shortcut for the `help` option.
@example
```
#!/usr/bin/env node
'use strict';
import meow = require('meow');
import foo = require('.');
const cli = meow(`
Usage
$ foo
Options
--rainbow, -r Include a rainbow
Examples
$ foo unicorns --rainbow
🌈 unicorns 🌈
`, {
flags: {
rainbow: {
type: 'boolean',
alias: 'r'
}
}
});
//{
// input: ['unicorns'],
// flags: {rainbow: true},
// ...
//}
foo(cli.input[0], cli.flags);
```
*/
declare function meow(helpMessage: string, options?: meow.Options): meow.Result;
declare function meow(options?: meow.Options): meow.Result;
export = meow;
meow-8.0.0/index.js 0000664 0000000 0000000 00000012301 13746371342 0014142 0 ustar 00root root 0000000 0000000 'use strict';
const path = require('path');
const buildParserOptions = require('minimist-options');
const parseArguments = require('yargs-parser');
const camelCaseKeys = require('camelcase-keys');
const decamelizeKeys = require('decamelize-keys');
const trimNewlines = require('trim-newlines');
const redent = require('redent');
const readPkgUp = require('read-pkg-up');
const hardRejection = require('hard-rejection');
const normalizePackageData = require('normalize-package-data');
// Prevent caching of this module so module.parent is always accurate
delete require.cache[__filename];
const parentDir = path.dirname(module.parent && module.parent.filename ? module.parent.filename : '.');
const isFlagMissing = (flagName, definedFlags, receivedFlags, input) => {
const flag = definedFlags[flagName];
let isFlagRequired = true;
if (typeof flag.isRequired === 'function') {
isFlagRequired = flag.isRequired(receivedFlags, input);
if (typeof isFlagRequired !== 'boolean') {
throw new TypeError(`Return value for isRequired callback should be of type boolean, but ${typeof isFlagRequired} was returned.`);
}
}
if (typeof receivedFlags[flagName] === 'undefined') {
return isFlagRequired;
}
return flag.isMultiple && receivedFlags[flagName].length === 0;
};
const getMissingRequiredFlags = (flags, receivedFlags, input) => {
const missingRequiredFlags = [];
if (typeof flags === 'undefined') {
return [];
}
for (const flagName of Object.keys(flags)) {
if (flags[flagName].isRequired && isFlagMissing(flagName, flags, receivedFlags, input)) {
missingRequiredFlags.push({key: flagName, ...flags[flagName]});
}
}
return missingRequiredFlags;
};
const reportMissingRequiredFlags = missingRequiredFlags => {
console.error(`Missing required flag${missingRequiredFlags.length > 1 ? 's' : ''}`);
for (const flag of missingRequiredFlags) {
console.error(`\t--${flag.key}${flag.alias ? `, -${flag.alias}` : ''}`);
}
};
const buildParserFlags = ({flags, booleanDefault}) => {
const parserFlags = {};
for (const [flagKey, flagValue] of Object.entries(flags)) {
const flag = {...flagValue};
if (
typeof booleanDefault !== 'undefined' &&
flag.type === 'boolean' &&
!Object.prototype.hasOwnProperty.call(flag, 'default')
) {
flag.default = flag.isMultiple ? [booleanDefault] : booleanDefault;
}
if (flag.isMultiple) {
flag.type = flag.type ? `${flag.type}-array` : 'array';
flag.default = flag.default || [];
delete flag.isMultiple;
}
parserFlags[flagKey] = flag;
}
return parserFlags;
};
const validateFlags = (flags, options) => {
for (const [flagKey, flagValue] of Object.entries(options.flags)) {
if (flagKey !== '--' && !flagValue.isMultiple && Array.isArray(flags[flagKey])) {
throw new Error(`The flag --${flagKey} can only be set once.`);
}
}
};
const meow = (helpText, options) => {
if (typeof helpText !== 'string') {
options = helpText;
helpText = '';
}
const foundPkg = readPkgUp.sync({
cwd: parentDir,
normalize: false
});
options = {
pkg: foundPkg ? foundPkg.packageJson : {},
argv: process.argv.slice(2),
flags: {},
inferType: false,
input: 'string',
help: helpText,
autoHelp: true,
autoVersion: true,
booleanDefault: false,
hardRejection: true,
...options
};
if (options.hardRejection) {
hardRejection();
}
let parserOptions = {
arguments: options.input,
...buildParserFlags(options)
};
parserOptions = decamelizeKeys(parserOptions, '-', {exclude: ['stopEarly', '--']});
if (options.inferType) {
delete parserOptions.arguments;
}
parserOptions = buildParserOptions(parserOptions);
parserOptions.configuration = {
...parserOptions.configuration,
'greedy-arrays': false
};
if (parserOptions['--']) {
parserOptions.configuration['populate--'] = true;
}
const {pkg} = options;
const argv = parseArguments(options.argv, parserOptions);
let help = redent(trimNewlines((options.help || '').replace(/\t+\n*$/, '')), 2);
normalizePackageData(pkg);
process.title = pkg.bin ? Object.keys(pkg.bin)[0] : pkg.name;
let {description} = options;
if (!description && description !== false) {
({description} = pkg);
}
help = (description ? `\n ${description}\n` : '') + (help ? `\n${help}\n` : '\n');
const showHelp = code => {
console.log(help);
process.exit(typeof code === 'number' ? code : 2);
};
const showVersion = () => {
console.log(typeof options.version === 'string' ? options.version : pkg.version);
process.exit(0);
};
if (argv._.length === 0 && options.argv.length === 1) {
if (argv.version === true && options.autoVersion) {
showVersion();
}
if (argv.help === true && options.autoHelp) {
showHelp(0);
}
}
const input = argv._;
delete argv._;
const flags = camelCaseKeys(argv, {exclude: ['--', /^\w$/]});
const unnormalizedFlags = {...flags};
validateFlags(flags, options);
for (const flagValue of Object.values(options.flags)) {
delete flags[flagValue.alias];
}
const missingRequiredFlags = getMissingRequiredFlags(options.flags, flags, input);
if (missingRequiredFlags.length > 0) {
reportMissingRequiredFlags(missingRequiredFlags);
process.exit(2);
}
return {
input,
flags,
unnormalizedFlags,
pkg,
help,
showHelp,
showVersion
};
};
module.exports = meow;
meow-8.0.0/index.test-d.ts 0000664 0000000 0000000 00000004735 13746371342 0015367 0 ustar 00root root 0000000 0000000 import {expectAssignable, expectType} from 'tsd';
import {PackageJson} from 'type-fest';
import meow = require('.');
import {Result} from '.';
expectType>(meow('Help text'));
expectType>(meow('Help text', {hardRejection: false}));
expectAssignable<{flags: {foo: number}}>(
meow({flags: {foo: {type: 'number', isRequired: true}}})
);
expectAssignable<{flags: {foo: string}}>(
meow({flags: {foo: {type: 'string', isRequired: true}}})
);
expectAssignable<{flags: {foo: boolean}}>(
meow({flags: {foo: {type: 'boolean', isRequired: true}}})
);
expectAssignable<{flags: {foo: number | undefined}}>(
meow({flags: {foo: {type: 'number'}}})
);
expectAssignable<{flags: {foo: string | undefined}}>(
meow({flags: {foo: {type: 'string'}}})
);
expectAssignable<{flags: {foo: boolean | undefined}}>(
meow({flags: {foo: {type: 'boolean'}}})
);
expectType>(meow({description: 'foo'}));
expectType>(meow({description: false}));
expectType>(meow({help: 'foo'}));
expectType>(meow({help: false}));
expectType>(meow({version: 'foo'}));
expectType>(meow({version: false}));
expectType>(meow({autoHelp: false}));
expectType>(meow({autoVersion: false}));
expectType>(meow({pkg: {foo: 'bar'}}));
expectType>(meow({argv: ['foo', 'bar']}));
expectType>(meow({inferType: true}));
expectType>(meow({booleanDefault: true}));
expectType>(meow({booleanDefault: null}));
expectType>(meow({booleanDefault: undefined}));
expectType>(meow({hardRejection: false}));
const result = meow('Help text', {
flags: {
foo: {type: 'boolean', alias: 'f'},
'foo-bar': {type: 'number'},
bar: {type: 'string', default: ''},
abc: {type: 'string', isMultiple: true}
}
});
expectType(result.input);
expectType(result.pkg);
expectType(result.help);
expectType(result.flags.foo);
expectType(result.flags.fooBar);
expectType(result.flags.bar);
expectType(result.flags.abc);
expectType(result.unnormalizedFlags.foo);
expectType(result.unnormalizedFlags.f);
expectType(result.unnormalizedFlags['foo-bar']);
expectType(result.unnormalizedFlags.bar);
expectType(result.unnormalizedFlags.abc);
result.showHelp();
result.showHelp(1);
result.showVersion();
meow-8.0.0/license 0000664 0000000 0000000 00000002135 13746371342 0014046 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) Sindre Sorhus (https://sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
meow-8.0.0/meow.gif 0000664 0000000 0000000 00002245021 13746371342 0014144 0 ustar 00root root 0000000 0000000 GIF89a% #&#%EM(#(/-L/GHI.Z(
ܐQOknf{ 'OkK qOMwwwLLL)))fff hQn ȋcݔحhTLlrYלkrI97q+.o
- !NETSCAPE2.0 !XMP DataXMP?xpacke ! % , fTsکt,k'vX8x