From 5400b667125d91f3256b8f074b07aea096b4c32f Mon Sep 17 00:00:00 2001 From: Yash Singh Date: Sat, 16 Jan 2021 01:18:28 -0800 Subject: [PATCH 1/6] Reduce cyclomatic complexity (#175) --- index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/index.js b/index.js index 6c6bb25..f9a6423 100644 --- a/index.js +++ b/index.js @@ -189,9 +189,7 @@ const meow = (helpText, options) => { if (argv._.length === 0 && options.argv.length === 1) { if (argv.version === true && options.autoVersion) { showVersion(); - } - - if (argv.help === true && options.autoHelp) { + } else if (argv.help === true && options.autoHelp) { showHelp(0); } } From 05320aca1b22991f2595ffb6178e38811a4a25db Mon Sep 17 00:00:00 2001 From: LitoMore Date: Wed, 28 Apr 2021 03:57:00 +0800 Subject: [PATCH 2/6] Require Node.js 12 and move to ESM (#181) Co-authored-by: Sindre Sorhus --- .github/workflows/main.yml | 4 +- estest/index.js | 4 +- index.d.ts | 427 +++++++++---------- index.js | 31 +- index.test-d.ts | 3 +- package.json | 11 +- test/allow-unkonwn-flags.js | 4 +- test/fixtures/fixture-allow-unknown-flags.js | 3 +- test/fixtures/fixture-required-function.js | 3 +- test/fixtures/fixture-required-multiple.js | 3 +- test/fixtures/fixture-required.js | 2 +- test/fixtures/fixture.js | 7 +- test/is-required-flag.js | 4 +- test/test.js | 9 +- 14 files changed, 254 insertions(+), 261 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c1870cf..3b8aa86 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,12 +10,12 @@ jobs: fail-fast: false matrix: node-version: + - 16 - 14 - 12 - - 10 steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - run: npm install diff --git a/estest/index.js b/estest/index.js index b4d1af9..2992614 100644 --- a/estest/index.js +++ b/estest/index.js @@ -1,6 +1,4 @@ -import {createRequire} from 'module'; - -const meow = createRequire(import.meta.url)('../index.js'); +import meow from '../index.js'; meow(` Usage diff --git a/index.d.ts b/index.d.ts index 59492ad..ec5c613 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,25 +1,24 @@ import {PackageJson} from 'type-fest'; -declare namespace meow { - type FlagType = 'string' | 'boolean' | 'number'; +export type FlagType = 'string' | 'boolean' | 'number'; - /** - Callback function to determine if a flag is required during runtime. +/** +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. +@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; - } +@returns True if the flag is required, otherwise false. +*/ +export type IsRequiredPredicate = (flags: Readonly, input: readonly string[]) => boolean; + +export 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>; @@ -28,189 +27,189 @@ declare namespace meow { type AnyFlag = StringFlag | BooleanFlag | NumberFlag; type AnyFlags = Record; - interface Options { - /** - Define argument flags. +export interface Options { + /** + Define argument flags. - The key is the flag name in camel-case and the value is an object with any of: + The key is the flag name in camel-case 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. + - `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. - Note that flags are always defined using a camel-case key (`myKey`), but will match arguments in kebab-case (`--my-key`). + Note that flags are always defined using a camel-case key (`myKey`), but will match arguments in kebab-case (`--my-key`). - @example - ``` - flags: { - unicorn: { - type: 'string', - alias: 'u', - default: ['rainbow', 'cat'], - isMultiple: true, - isRequired: (flags, input) => { - if (flags.otherFlag) { - return true; - } - - return false; + @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; + } + ``` + */ + readonly flags?: Flags; - /** - Description to show above the help text. Default: The package.json `"description"` property. + /** + 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; + Set it to `false` to disable it altogether. + */ + readonly description?: string | false; - /** - The help text you want shown. + /** + 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 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. + The description will be shown above your help text automatically. - Set it to `false` to disable it altogether. - */ - readonly help?: string | false; + Set it to `false` to disable it altogether. + */ + readonly help?: string | false; - /** - Set a custom version output. Default: The package.json `"version"` property. + /** + Set a custom version output. Default: The package.json `"version"` property. - Set it to `false` to disable it altogether. - */ - readonly version?: string | false; + 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. + /** + 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; + 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. + /** + 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; + 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. + /** + `package.json` as an `Object`. Default: Closest `package.json` upwards. - _You most likely don't need this option._ - */ - readonly pkg?: Record; + _You most likely don't need this option._ + */ + readonly pkg?: Record; - /** - Custom arguments object. + /** + Custom arguments object. - @default process.argv.slice(2) - */ - readonly argv?: readonly string[]; + @default process.argv.slice(2) + */ + readonly argv?: readonly string[]; - /** - Infer the argument type. + /** + Infer the argument type. - By default, the argument `5` in `$ foo 5` becomes a string. Enabling this would infer it as a number. + By default, the argument `5` in `$ foo 5` becomes a string. Enabling this would infer it as a number. - @default false - */ - readonly inferType?: boolean; + @default false + */ + readonly inferType?: boolean; - /** - Value of `boolean` flags not defined in `argv`. + /** + 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`. + 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 `[]`._ + _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.__ + __Caution: Explicitly specifying `undefined` for `booleanDefault` has different meaning from omitting key itself.__ - @example - ``` - import meow = require('meow'); + @example + ``` + import meow from 'meow'; - const cli = meow(` - Usage - $ foo + const cli = meow(` + Usage + $ foo - Options - --rainbow, -r Include a rainbow - --unicorn, -u Include a unicorn - --no-sparkles Exclude sparkles + 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 - } + 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; - - /** - Whether to allow unknown flags or not. - - @default true - */ - readonly allowUnknownFlags?: boolean; - } + } + }); + + //{ + // 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 = + /** + Whether to allow unknown flags or not. + + @default true + */ + readonly allowUnknownFlags?: boolean; +} + +export type TypedFlag = Flag extends {type: 'number'} ? number : Flag extends {type: 'string'} @@ -219,57 +218,56 @@ declare namespace meow { ? boolean : unknown; - type PossiblyOptionalFlag = +export 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; - } +export type TypedFlags = { + [F in keyof Flags]: Flags[F] extends {isMultiple: true} + ? PossiblyOptionalFlag>> + : PossiblyOptionalFlag> +}; + +export 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. @@ -277,9 +275,8 @@ declare namespace meow { @example ``` #!/usr/bin/env node -'use strict'; -import meow = require('meow'); -import foo = require('.'); +import meow from 'meow'; +import foo from './index.js'; const cli = meow(` Usage @@ -309,7 +306,7 @@ const cli = meow(` 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; +export default function meow(helpMessage: string, options?: Options): Result; +// eslint-disable-next-line no-redeclare +export default function meow(options?: Options): Result; diff --git a/index.js b/index.js index f9a6423..123782a 100644 --- a/index.js +++ b/index.js @@ -1,19 +1,13 @@ -'use strict'; -const path = require('path'); -const buildParserOptions = require('minimist-options'); -const parseArguments = require('yargs-parser'); -const camelCaseKeys = require('camelcase-keys'); -const decamelize = require('decamelize'); -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 : '.'); +import buildParserOptions from 'minimist-options'; +import parseArguments from 'yargs-parser'; +import camelCaseKeys from 'camelcase-keys'; +import decamelize from 'decamelize'; +import decamelizeKeys from 'decamelize-keys'; +import trimNewlines from 'trim-newlines'; +import redent from 'redent'; +import {readPackageUpSync} from 'read-pkg-up'; +import hardRejection from 'hard-rejection'; +import normalizePackageData from 'normalize-package-data'; const isFlagMissing = (flagName, definedFlags, receivedFlags, input) => { const flag = definedFlags[flagName]; @@ -109,8 +103,7 @@ const meow = (helpText, options) => { helpText = ''; } - const foundPkg = readPkgUp.sync({ - cwd: parentDir, + const foundPkg = readPackageUpSync({ normalize: false }); @@ -231,4 +224,4 @@ const meow = (helpText, options) => { }; }; -module.exports = meow; +export default meow; diff --git a/index.test-d.ts b/index.test-d.ts index 4e7da4a..5c154d2 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,7 +1,6 @@ import {expectAssignable, expectType} from 'tsd'; import {PackageJson} from 'type-fest'; -import meow = require('.'); -import {Result} from '.'; +import meow, {Result} from './index.js'; expectType>(meow('Help text')); expectType>(meow('Help text', {hardRejection: false})); diff --git a/package.json b/package.json index 6875491..d4caf34 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ "email": "sindresorhus@gmail.com", "url": "https://sindresorhus.com" }, + "type": "module", + "exports": "./index.js", "engines": { - "node": ">=10" + "node": ">=12" }, "scripts": { "test": "xo && ava && tsd" @@ -47,18 +49,19 @@ "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", + "read-pkg-up": "^8.0.0", "redent": "^3.0.0", "trim-newlines": "^3.0.0", "type-fest": "^0.18.0", "yargs-parser": "^20.2.3" }, "devDependencies": { - "ava": "^2.4.0", + "ava": "^3.15.0", "execa": "^4.1.0", "indent-string": "^4.0.0", + "read-pkg": "^6.0.0", "tsd": "^0.13.1", - "xo": "^0.34.1" + "xo": "^0.39.1" }, "xo": { "rules": { diff --git a/test/allow-unkonwn-flags.js b/test/allow-unkonwn-flags.js index 9631bb7..fc723df 100644 --- a/test/allow-unkonwn-flags.js +++ b/test/allow-unkonwn-flags.js @@ -1,7 +1,9 @@ -import path from 'path'; +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; import test from 'ava'; import execa from 'execa'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); const fixtureAllowUnknownFlags = path.join(__dirname, 'fixtures', 'fixture-allow-unknown-flags.js'); test('spawn CLI and test specifying unknown flags', async t => { diff --git a/test/fixtures/fixture-allow-unknown-flags.js b/test/fixtures/fixture-allow-unknown-flags.js index 131e9e9..eb0c100 100755 --- a/test/fixtures/fixture-allow-unknown-flags.js +++ b/test/fixtures/fixture-allow-unknown-flags.js @@ -1,6 +1,5 @@ #!/usr/bin/env node -'use strict'; -const meow = require('../..'); +import meow from '../../index.js'; const cli = meow({ description: 'Custom description', diff --git a/test/fixtures/fixture-required-function.js b/test/fixtures/fixture-required-function.js index ef3c443..c509254 100755 --- a/test/fixtures/fixture-required-function.js +++ b/test/fixtures/fixture-required-function.js @@ -1,6 +1,5 @@ #!/usr/bin/env node -'use strict'; -const meow = require('../..'); +import meow from '../../index.js'; const cli = meow({ description: 'Custom description', diff --git a/test/fixtures/fixture-required-multiple.js b/test/fixtures/fixture-required-multiple.js index fa424e2..907ffc4 100755 --- a/test/fixtures/fixture-required-multiple.js +++ b/test/fixtures/fixture-required-multiple.js @@ -1,6 +1,5 @@ #!/usr/bin/env node -'use strict'; -const meow = require('../..'); +import meow from '../../index.js'; const cli = meow({ description: 'Custom description', diff --git a/test/fixtures/fixture-required.js b/test/fixtures/fixture-required.js index 2f3690e..ad9341a 100755 --- a/test/fixtures/fixture-required.js +++ b/test/fixtures/fixture-required.js @@ -1,6 +1,6 @@ #!/usr/bin/env node 'use strict'; -const meow = require('../..'); +import meow from '../../index.js'; const cli = meow({ description: 'Custom description', diff --git a/test/fixtures/fixture.js b/test/fixtures/fixture.js index 6917bae..5fc0f17 100755 --- a/test/fixtures/fixture.js +++ b/test/fixtures/fixture.js @@ -1,6 +1,5 @@ #!/usr/bin/env node -'use strict'; -const meow = require('../..'); +import meow from '../../index.js'; const cli = meow({ description: 'Custom description', @@ -18,9 +17,9 @@ const cli = meow({ }); if (cli.flags.camelCaseOption === 'foo') { - Object.keys(cli.flags).forEach(x => { + for (const x of Object.keys(cli.flags)) { console.log(x); - }); + } } else { console.log(cli.flags.camelCaseOption); } diff --git a/test/is-required-flag.js b/test/is-required-flag.js index 4586b28..45f4ca9 100644 --- a/test/is-required-flag.js +++ b/test/is-required-flag.js @@ -1,7 +1,9 @@ +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; import test from 'ava'; import execa from 'execa'; -const path = require('path'); +const __dirname = path.dirname(fileURLToPath(import.meta.url)); const fixtureRequiredPath = path.join(__dirname, 'fixtures', 'fixture-required.js'); const fixtureRequiredFunctionPath = path.join(__dirname, 'fixtures', 'fixture-required-function.js'); const fixtureRequiredMultiplePath = path.join(__dirname, 'fixtures', 'fixture-required-multiple.js'); diff --git a/test/test.js b/test/test.js index c8dc19d..0487543 100644 --- a/test/test.js +++ b/test/test.js @@ -1,10 +1,12 @@ +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; import test from 'ava'; import indentString from 'indent-string'; import execa from 'execa'; -import path from 'path'; -import pkg from '../package.json'; -import meow from '..'; +import {readPackageAsync} from 'read-pkg'; +import meow from '../index.js'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); const fixturePath = path.join(__dirname, 'fixtures', 'fixture.js'); const NODE_MAJOR_VERSION = process.versions.node.split('.')[0]; @@ -40,6 +42,7 @@ test('support help shortcut', t => { }); test('spawn cli and show version', async t => { + const pkg = await readPackageAsync(); const {stdout} = await execa(fixturePath, ['--version']); t.is(stdout, pkg.version); }); From 8c12b2dd2988d6d358a75c4b3962ab452640eac7 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 28 Apr 2021 03:04:25 +0700 Subject: [PATCH 3/6] Upgrade dependencies --- estest/index.js | 19 ++++++++++--------- index.d.ts | 16 +++++++--------- index.js | 18 +++++++++--------- package.json | 26 +++++++++++--------------- 4 files changed, 37 insertions(+), 42 deletions(-) diff --git a/estest/index.js b/estest/index.js index 2992614..c10f205 100644 --- a/estest/index.js +++ b/estest/index.js @@ -1,16 +1,17 @@ import meow from '../index.js'; -meow(` - Usage - $ estest +meow( + ` + Usage + $ estest - Options - --rainbow, -r Include a rainbow + Options + --rainbow, -r Include a rainbow - Examples - $ estest unicorns --rainbow - 🌈 unicorns 🌈 -`, + Examples + $ estest unicorns --rainbow + 🌈 unicorns 🌈 + `, { flags: { rainbow: { diff --git a/index.d.ts b/index.d.ts index ec5c613..70733bc 100644 --- a/index.d.ts +++ b/index.d.ts @@ -20,12 +20,11 @@ export interface Flag { 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; +type StringFlag = Flag<'string', string>; +type BooleanFlag = Flag<'boolean', boolean>; +type NumberFlag = Flag<'number', number>; +type AnyFlag = StringFlag | BooleanFlag | NumberFlag; +type AnyFlags = Record; export interface Options { /** @@ -209,7 +208,7 @@ export interface Options { readonly allowUnknownFlags?: boolean; } -export type TypedFlag = +type TypedFlag = Flag extends {type: 'number'} ? number : Flag extends {type: 'string'} @@ -218,7 +217,7 @@ export type TypedFlag = ? boolean : unknown; -export type PossiblyOptionalFlag = +type PossiblyOptionalFlag = Flag extends {isRequired: true} ? FlagType : Flag extends {default: any} @@ -306,7 +305,6 @@ const cli = meow(` foo(cli.input[0], cli.flags); ``` */ - export default function meow(helpMessage: string, options?: Options): Result; // eslint-disable-next-line no-redeclare export default function meow(options?: Options): Result; diff --git a/index.js b/index.js index 123782a..2959bc9 100644 --- a/index.js +++ b/index.js @@ -45,7 +45,7 @@ const getMissingRequiredFlags = (flags, receivedFlags, input) => { const reportMissingRequiredFlags = missingRequiredFlags => { console.error(`Missing required flag${missingRequiredFlags.length > 1 ? 's' : ''}`); for (const flag of missingRequiredFlags) { - console.error(`\t--${decamelize(flag.key, '-')}${flag.alias ? `, -${flag.alias}` : ''}`); + console.error(`\t--${decamelize(flag.key, {separator: '-'})}${flag.alias ? `, -${flag.alias}` : ''}`); } }; @@ -103,12 +103,12 @@ const meow = (helpText, options) => { helpText = ''; } - const foundPkg = readPackageUpSync({ + const foundPackage = readPackageUpSync({ normalize: false }); options = { - pkg: foundPkg ? foundPkg.packageJson : {}, + pkg: foundPackage ? foundPackage.packageJson : {}, argv: process.argv.slice(2), flags: {}, inferType: false, @@ -154,17 +154,17 @@ const meow = (helpText, options) => { parserOptions.configuration['unknown-options-as-args'] = true; } - const {pkg} = options; + const {pkg: package_} = options; const argv = parseArguments(options.argv, parserOptions); let help = redent(trimNewlines((options.help || '').replace(/\t+\n*$/, '')), 2); - normalizePackageData(pkg); + normalizePackageData(package_); - process.title = pkg.bin ? Object.keys(pkg.bin)[0] : pkg.name; + process.title = package_.bin ? Object.keys(package_.bin)[0] : package_.name; let {description} = options; if (!description && description !== false) { - ({description} = pkg); + ({description} = package_); } help = (description ? `\n ${description}\n` : '') + (help ? `\n${help}\n` : '\n'); @@ -175,7 +175,7 @@ const meow = (helpText, options) => { }; const showVersion = () => { - console.log(typeof options.version === 'string' ? options.version : pkg.version); + console.log(typeof options.version === 'string' ? options.version : package_.version); process.exit(0); }; @@ -217,7 +217,7 @@ const meow = (helpText, options) => { input, flags, unnormalizedFlags, - pkg, + pkg: package_, help, showHelp, showVersion diff --git a/package.json b/package.json index d4caf34..2ed2791 100644 --- a/package.json +++ b/package.json @@ -42,35 +42,31 @@ "console" ], "dependencies": { - "@types/minimist": "^1.2.0", + "@types/minimist": "^1.2.1", "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", + "decamelize": "^5.0.0", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", + "normalize-package-data": "^3.0.2", "read-pkg-up": "^8.0.0", "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" + "trim-newlines": "^4.0.0", + "type-fest": "^1.0.2", + "yargs-parser": "^20.2.7" }, "devDependencies": { "ava": "^3.15.0", - "execa": "^4.1.0", - "indent-string": "^4.0.0", + "execa": "^5.0.0", + "indent-string": "^5.0.0", "read-pkg": "^6.0.0", - "tsd": "^0.13.1", + "tsd": "^0.14.0", "xo": "^0.39.1" }, "xo": { "rules": { - "unicorn/no-process-exit": "off", - "node/no-unsupported-features/es-syntax": "off" - }, - "ignores": [ - "estest/index.js" - ] + "unicorn/no-process-exit": "off" + } }, "ava": { "files": [ From 0c11c391e873eef045c7357a3f62585ce8aae8d0 Mon Sep 17 00:00:00 2001 From: LitoMore Date: Wed, 5 May 2021 23:08:26 +0800 Subject: [PATCH 4/6] Allow user to pass in package URL for package reading (#182) Co-authored-by: Sindre Sorhus --- estest/index.js | 1 + index.d.ts | 7 ++ index.js | 9 ++- index.test-d.ts | 48 +++++++------- readme.md | 53 +++------------ test/fixtures/fixture-allow-unknown-flags.js | 1 + test/fixtures/fixture-required-function.js | 1 + test/fixtures/fixture-required-multiple.js | 1 + test/fixtures/fixture-required.js | 1 + test/fixtures/fixture.js | 1 + test/test.js | 69 +++++++++++++++++--- tsconfig.json | 2 +- 12 files changed, 117 insertions(+), 77 deletions(-) diff --git a/estest/index.js b/estest/index.js index c10f205..3c85bc0 100644 --- a/estest/index.js +++ b/estest/index.js @@ -13,6 +13,7 @@ meow( 🌈 unicorns 🌈 `, { + importMeta: import.meta, flags: { rainbow: { type: 'boolean', diff --git a/index.d.ts b/index.d.ts index 70733bc..2ba2f25 100644 --- a/index.d.ts +++ b/index.d.ts @@ -27,6 +27,11 @@ type AnyFlag = StringFlag | BooleanFlag | NumberFlag; type AnyFlags = Record; export interface Options { + /** + Pass in [`import.meta`](https://nodejs.org/dist/latest/docs/api/esm.html#esm_import_meta). This is used to find the correct package.json file. + */ + readonly importMeta: ImportMeta; + /** Define argument flags. @@ -151,6 +156,7 @@ export interface Options { $ foo 🌈 unicorns✨🌈 `, { + importMeta: import.meta, booleanDefault: undefined, flags: { rainbow: { @@ -288,6 +294,7 @@ const cli = meow(` $ foo unicorns --rainbow 🌈 unicorns 🌈 `, { + importMeta: import.meta, flags: { rainbow: { type: 'boolean', diff --git a/index.js b/index.js index 2959bc9..8d3d76f 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,5 @@ +import {dirname} from 'node:path'; +import {fileURLToPath} from 'node:url'; import buildParserOptions from 'minimist-options'; import parseArguments from 'yargs-parser'; import camelCaseKeys from 'camelcase-keys'; @@ -97,13 +99,18 @@ const validateFlags = (flags, options) => { } }; -const meow = (helpText, options) => { +const meow = (helpText, options = {}) => { if (typeof helpText !== 'string') { options = helpText; helpText = ''; } + if (!(options.importMeta && options.importMeta.url)) { + throw new TypeError('The `importMeta` option is required. Its value must be `import.meta`.'); + } + const foundPackage = readPackageUpSync({ + cwd: dirname(fileURLToPath(options.importMeta.url)), normalize: false }); diff --git a/index.test-d.ts b/index.test-d.ts index 5c154d2..28b6098 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -2,43 +2,46 @@ import {expectAssignable, expectType} from 'tsd'; import {PackageJson} from 'type-fest'; import meow, {Result} from './index.js'; +const importMeta = import.meta; + expectType>(meow('Help text')); -expectType>(meow('Help text', {hardRejection: false})); +expectType>(meow('Help text', {importMeta, hardRejection: false})); expectAssignable<{flags: {foo: number}}>( - meow({flags: {foo: {type: 'number', isRequired: true}}}) + meow({importMeta: import.meta, flags: {foo: {type: 'number', isRequired: true}}}) ); expectAssignable<{flags: {foo: string}}>( - meow({flags: {foo: {type: 'string', isRequired: true}}}) + meow({importMeta, flags: {foo: {type: 'string', isRequired: true}}}) ); expectAssignable<{flags: {foo: boolean}}>( - meow({flags: {foo: {type: 'boolean', isRequired: true}}}) + meow({importMeta, flags: {foo: {type: 'boolean', isRequired: true}}}) ); expectAssignable<{flags: {foo: number | undefined}}>( - meow({flags: {foo: {type: 'number'}}}) + meow({importMeta, flags: {foo: {type: 'number'}}}) ); expectAssignable<{flags: {foo: string | undefined}}>( - meow({flags: {foo: {type: 'string'}}}) + meow({importMeta, flags: {foo: {type: 'string'}}}) ); expectAssignable<{flags: {foo: boolean | undefined}}>( - meow({flags: {foo: {type: 'boolean'}}}) + meow({importMeta, 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})); +expectType>(meow({importMeta, description: 'foo'})); +expectType>(meow({importMeta, description: false})); +expectType>(meow({importMeta, help: 'foo'})); +expectType>(meow({importMeta, help: false})); +expectType>(meow({importMeta, version: 'foo'})); +expectType>(meow({importMeta, version: false})); +expectType>(meow({importMeta, autoHelp: false})); +expectType>(meow({importMeta, autoVersion: false})); +expectType>(meow({importMeta, pkg: {foo: 'bar'}})); +expectType>(meow({importMeta, argv: ['foo', 'bar']})); +expectType>(meow({importMeta, inferType: true})); +expectType>(meow({importMeta, booleanDefault: true})); +expectType>(meow({importMeta, booleanDefault: null})); +expectType>(meow({importMeta, booleanDefault: undefined})); +expectType>(meow({importMeta, hardRejection: false})); const result = meow('Help text', { + importMeta, flags: { foo: {type: 'boolean', alias: 'f'}, 'foo-bar': {type: 'number'}, @@ -66,6 +69,7 @@ result.showHelp(1); result.showVersion(); const options = { + importMeta, flags: { rainbow: { type: 'boolean', diff --git a/readme.md b/readme.md index dd9f337..0b2d434 100644 --- a/readme.md +++ b/readme.md @@ -26,52 +26,11 @@ $ npm install meow $ ./foo-app.js unicorns --rainbow ``` -**CommonJS** - ```js #!/usr/bin/env node -'use strict'; -const meow = require('meow'); -const 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); -``` - -**ES Modules** - -```js -#!/usr/bin/env node -import {createRequire} from 'module'; +import meow from 'meow'; import foo from './lib/index.js'; -const meow = createRequire(import.meta.url)('meow'); - const cli = meow(` Usage $ foo @@ -83,6 +42,7 @@ const cli = meow(` $ foo unicorns --rainbow 🌈 unicorns 🌈 `, { + importMeta: import.meta, flags: { rainbow: { type: 'boolean', @@ -126,6 +86,12 @@ Shortcut for the `help` option. Type: `object` +##### importMeta + +Type: `object` + +Pass in [`import.meta`](https://nodejs.org/dist/latest/docs/api/esm.html#esm_import_meta). This is used to find the correct package.json file. + ##### flags Type: `object` @@ -253,7 +219,7 @@ __Caution: Explicitly specifying `undefined` for `booleanDefault` has different Example: ```js -const meow = require('meow'); +const meow from 'meow'; const cli = meow(` Usage @@ -268,6 +234,7 @@ const cli = meow(` $ foo 🌈 unicorns✨🌈 `, { + importMeta: import.meta, booleanDefault: undefined, flags: { rainbow: { diff --git a/test/fixtures/fixture-allow-unknown-flags.js b/test/fixtures/fixture-allow-unknown-flags.js index eb0c100..e14de67 100755 --- a/test/fixtures/fixture-allow-unknown-flags.js +++ b/test/fixtures/fixture-allow-unknown-flags.js @@ -2,6 +2,7 @@ import meow from '../../index.js'; const cli = meow({ + importMeta: import.meta, description: 'Custom description', help: ` Usage diff --git a/test/fixtures/fixture-required-function.js b/test/fixtures/fixture-required-function.js index c509254..1d4129b 100755 --- a/test/fixtures/fixture-required-function.js +++ b/test/fixtures/fixture-required-function.js @@ -2,6 +2,7 @@ import meow from '../../index.js'; const cli = meow({ + importMeta: import.meta, description: 'Custom description', help: ` Usage diff --git a/test/fixtures/fixture-required-multiple.js b/test/fixtures/fixture-required-multiple.js index 907ffc4..7fa3bd3 100755 --- a/test/fixtures/fixture-required-multiple.js +++ b/test/fixtures/fixture-required-multiple.js @@ -2,6 +2,7 @@ import meow from '../../index.js'; const cli = meow({ + importMeta: import.meta, description: 'Custom description', help: ` Usage diff --git a/test/fixtures/fixture-required.js b/test/fixtures/fixture-required.js index ad9341a..ad2b4a6 100755 --- a/test/fixtures/fixture-required.js +++ b/test/fixtures/fixture-required.js @@ -3,6 +3,7 @@ import meow from '../../index.js'; const cli = meow({ + importMeta: import.meta, description: 'Custom description', help: ` Usage diff --git a/test/fixtures/fixture.js b/test/fixtures/fixture.js index 5fc0f17..dab6eb9 100755 --- a/test/fixtures/fixture.js +++ b/test/fixtures/fixture.js @@ -2,6 +2,7 @@ import meow from '../../index.js'; const cli = meow({ + importMeta: import.meta, description: 'Custom description', help: ` Usage diff --git a/test/test.js b/test/test.js index 0487543..f47dc28 100644 --- a/test/test.js +++ b/test/test.js @@ -8,10 +8,21 @@ import meow from '../index.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const fixturePath = path.join(__dirname, 'fixtures', 'fixture.js'); +const importMeta = import.meta; const NODE_MAJOR_VERSION = process.versions.node.split('.')[0]; +test('invalid package url', t => { + const error = t.throws(() => { + meow({ + importMeta: '/path/to/package' + }); + }); + t.is(error.message, 'The `importMeta` option is required. Its value must be `import.meta`.'); +}); + test('return object', t => { const cli = meow({ + importMeta, argv: ['foo', '--foo-bar', '-u', 'cat', '--', 'unicorn', 'cake'], help: ` Usage @@ -37,7 +48,9 @@ test('support help shortcut', t => { const cli = meow(` unicorn cat - `); + `, { + importMeta + }); t.is(cli.help, indentString('\nCLI app helper\n\nunicorn\ncat\n', 2)); }); @@ -89,7 +102,9 @@ test('spawn cli and test input flag', async t => { test.serial('pkg.bin as a string should work', t => { meow({ + importMeta, pkg: { + importMeta, name: 'browser-sync', bin: 'bin/browser-sync.js' } @@ -99,29 +114,38 @@ test.serial('pkg.bin as a string should work', t => { }); test('single character flag casing should be preserved', t => { - t.deepEqual(meow({argv: ['-F']}).flags, {F: true}); + t.deepEqual(meow({ + importMeta, + argv: ['-F'] + }).flags, {F: true}); }); test('flag declared in kebab-case is an error', t => { const error = t.throws(() => { - meow({flags: {'kebab-case': 'boolean', test: 'boolean', 'another-one': 'boolean'}}); + meow({ + importMeta, + flags: {'kebab-case': 'boolean', test: 'boolean', 'another-one': 'boolean'} + }); }); t.is(error.message, 'Flag keys may not contain \'-\': kebab-case, another-one'); }); test('type inference', t => { - t.is(meow({argv: ['5']}).input[0], '5'); - t.is(meow({argv: ['5']}, {input: 'string'}).input[0], '5'); + t.is(meow({importMeta, argv: ['5']}).input[0], '5'); + t.is(meow({importMeta, argv: ['5']}, {input: 'string'}).input[0], '5'); t.is(meow({ + importMeta, argv: ['5'], inferType: true }).input[0], 5); t.is(meow({ + importMeta, argv: ['5'], inferType: true, flags: {foo: 'string'} }).input[0], 5); t.is(meow({ + importMeta, argv: ['5'], inferType: true, flags: { @@ -129,6 +153,7 @@ test('type inference', t => { } }).input[0], 5); t.is(meow({ + importMeta, argv: ['5'], input: 'number' }).input[0], 5); @@ -136,6 +161,7 @@ test('type inference', t => { test('booleanDefault: undefined, filter out unset boolean args', t => { t.deepEqual(meow({ + importMeta, argv: ['--foo'], booleanDefault: undefined, flags: { @@ -158,6 +184,7 @@ test('booleanDefault: undefined, filter out unset boolean args', t => { test('boolean args are false by default', t => { t.deepEqual(meow({ + importMeta, argv: ['--foo'], flags: { foo: { @@ -180,6 +207,7 @@ test('boolean args are false by default', t => { test('enforces boolean flag type', t => { const cli = meow({ + importMeta, argv: ['--cursor=false'], flags: { cursor: { @@ -192,6 +220,7 @@ test('enforces boolean flag type', t => { test('accept help and options', t => { t.deepEqual(meow({ + importMeta, argv: ['-f'], flags: { foo: { @@ -206,6 +235,7 @@ test('accept help and options', t => { test('grouped short-flags work', t => { const cli = meow({ + importMeta, argv: ['-cl'], flags: { coco: { @@ -228,6 +258,7 @@ test('grouped short-flags work', t => { test('grouped flags work', t => { const cli = meow({ + importMeta, argv: ['-cl'], flags: { coco: { @@ -249,13 +280,14 @@ test('grouped flags work', t => { }); test('disable autoVersion/autoHelp if `cli.input.length > 0`', t => { - t.is(meow({argv: ['bar', '--version']}).input[0], 'bar'); - t.is(meow({argv: ['bar', '--help']}).input[0], 'bar'); - t.is(meow({argv: ['bar', '--version', '--help']}).input[0], 'bar'); + t.is(meow({importMeta, argv: ['bar', '--version']}).input[0], 'bar'); + t.is(meow({importMeta, argv: ['bar', '--help']}).input[0], 'bar'); + t.is(meow({importMeta, argv: ['bar', '--version', '--help']}).input[0], 'bar'); }); test('supports `number` flag type', t => { const cli = meow({ + importMeta, argv: ['--foo=1.3'], flags: { foo: { @@ -269,6 +301,7 @@ test('supports `number` flag type', t => { test('supports `number` flag type - flag but no value', t => { const cli = meow({ + importMeta, argv: ['--foo'], flags: { foo: { @@ -282,6 +315,7 @@ test('supports `number` flag type - flag but no value', t => { test('supports `number` flag type - flag but no value but default', t => { const cli = meow({ + importMeta, argv: ['--foo'], flags: { foo: { @@ -296,6 +330,7 @@ test('supports `number` flag type - flag but no value but default', t => { test('supports `number` flag type - no flag but default', t => { const cli = meow({ + importMeta, argv: [], flags: { foo: { @@ -311,6 +346,7 @@ test('supports `number` flag type - no flag but default', t => { test('supports `number` flag type - throws on incorrect default value', t => { t.throws(() => { meow({ + importMeta, argv: [], flags: { foo: { @@ -324,6 +360,7 @@ test('supports `number` flag type - throws on incorrect default value', t => { test('isMultiple - unset flag returns empty array', t => { t.deepEqual(meow({ + importMeta, argv: [], flags: { foo: { @@ -338,6 +375,7 @@ test('isMultiple - unset flag returns empty array', t => { test('isMultiple - flag set once returns array', t => { t.deepEqual(meow({ + importMeta, argv: ['--foo=bar'], flags: { foo: { @@ -352,6 +390,7 @@ test('isMultiple - flag set once returns array', t => { test('isMultiple - flag set multiple times', t => { t.deepEqual(meow({ + importMeta, argv: ['--foo=bar', '--foo=baz'], flags: { foo: { @@ -366,6 +405,7 @@ test('isMultiple - flag set multiple times', t => { test('isMultiple - flag with space separated values', t => { const {input, flags} = meow({ + importMeta, argv: ['--foo', 'bar', 'baz'], flags: { foo: { @@ -381,6 +421,7 @@ test('isMultiple - flag with space separated values', t => { test('isMultiple - flag with comma separated values', t => { t.deepEqual(meow({ + importMeta, argv: ['--foo', 'bar,baz'], flags: { foo: { @@ -396,6 +437,7 @@ test('isMultiple - flag with comma separated values', t => { test('single flag set more than once => throws', t => { t.throws(() => { meow({ + importMeta, argv: ['--foo=bar', '--foo=baz'], flags: { foo: { @@ -408,6 +450,7 @@ test('single flag set more than once => throws', t => { test('isMultiple - default to type string', t => { t.deepEqual(meow({ + importMeta, argv: ['--foo=bar'], flags: { foo: { @@ -421,6 +464,7 @@ test('isMultiple - default to type string', t => { test('isMultiple - boolean flag', t => { t.deepEqual(meow({ + importMeta, argv: ['--foo', '--foo=false'], flags: { foo: { @@ -435,6 +479,7 @@ test('isMultiple - boolean flag', t => { test('isMultiple - boolean flag is false by default', t => { t.deepEqual(meow({ + importMeta, argv: [], flags: { foo: { @@ -449,6 +494,7 @@ test('isMultiple - boolean flag is false by default', t => { test('isMultiple - number flag', t => { t.deepEqual(meow({ + importMeta, argv: ['--foo=1.3', '--foo=-1'], flags: { foo: { @@ -463,6 +509,7 @@ test('isMultiple - number flag', t => { test('isMultiple - flag default values', t => { t.deepEqual(meow({ + importMeta, argv: [], flags: { string: { @@ -490,6 +537,7 @@ test('isMultiple - flag default values', t => { test('isMultiple - multiple flag default values', t => { t.deepEqual(meow({ + importMeta, argv: [], flags: { string: { @@ -518,6 +566,7 @@ test('isMultiple - multiple flag default values', t => { // Happened in production 2020-05-10: https://github.com/sindresorhus/meow/pull/143#issuecomment-626287226 test('isMultiple - handles multi-word flag name', t => { t.deepEqual(meow({ + importMeta, argv: ['--foo-bar=baz'], flags: { fooBar: { @@ -533,8 +582,8 @@ test('isMultiple - handles multi-word flag name', t => { if (NODE_MAJOR_VERSION >= 14) { test('supports es modules', async t => { try { - const {stdout} = await execa('node', ['index.js', '--version'], { - cwd: path.join(__dirname, '..', 'estest') + const {stdout} = await execa('node', ['estest/index.js', '--version'], { + importMeta: path.join(__dirname, '..') }); t.regex(stdout, /1.2.3/); } catch (error) { diff --git a/tsconfig.json b/tsconfig.json index 720afed..edadef1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ "lib": [ "es2018" ], - "module": "commonjs", + "module": "esnext", "moduleResolution": "node", "noImplicitAny": true, "strictNullChecks": true, From e61af45ca65be532da8196b1a3e4b3d5de383d4d Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 5 May 2021 22:16:19 +0700 Subject: [PATCH 5/6] Meta tweaks --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2ed2791..5c0fd52 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "type": "module", "exports": "./index.js", "engines": { - "node": ">=12" + "node": ">=12.17" }, "scripts": { "test": "xo && ava && tsd" @@ -50,7 +50,7 @@ "minimist-options": "4.1.0", "normalize-package-data": "^3.0.2", "read-pkg-up": "^8.0.0", - "redent": "^3.0.0", + "redent": "^4.0.0", "trim-newlines": "^4.0.0", "type-fest": "^1.0.2", "yargs-parser": "^20.2.7" From 6052e692e4561b157d3a251d0ba045fe34303399 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 5 May 2021 22:17:50 +0700 Subject: [PATCH 6/6] 10.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5c0fd52..6dadd9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meow", - "version": "9.0.0", + "version": "10.0.0", "description": "CLI app helper", "license": "MIT", "repository": "sindresorhus/meow",