Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow user to pass in package URL for package reading #182

Merged
merged 14 commits into from May 5, 2021
1 change: 1 addition & 0 deletions estest/index.js
Expand Up @@ -13,6 +13,7 @@ meow(
🌈 unicorns 🌈
`,
{
importMeta: import.meta,
flags: {
rainbow: {
type: 'boolean',
Expand Down
7 changes: 7 additions & 0 deletions index.d.ts
Expand Up @@ -27,6 +27,11 @@ type AnyFlag = StringFlag | BooleanFlag | NumberFlag;
type AnyFlags = Record<string, AnyFlag>;

export interface Options<Flags extends AnyFlags> {
/**
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.
*/
LitoMore marked this conversation as resolved.
Show resolved Hide resolved
readonly importMeta: ImportMeta;

/**
Define argument flags.

Expand Down Expand Up @@ -151,6 +156,7 @@ export interface Options<Flags extends AnyFlags> {
$ foo
🌈 unicorns✨🌈
`, {
importMeta: import.meta,
booleanDefault: undefined,
flags: {
rainbow: {
Expand Down Expand Up @@ -288,6 +294,7 @@ const cli = meow(`
$ foo unicorns --rainbow
🌈 unicorns 🌈
`, {
importMeta: import.meta,
flags: {
rainbow: {
type: 'boolean',
Expand Down
9 changes: 8 additions & 1 deletion 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';
Expand Down Expand Up @@ -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
});

Expand Down
48 changes: 26 additions & 22 deletions index.test-d.ts
Expand Up @@ -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<Result<never>>(meow('Help text'));
expectType<Result<never>>(meow('Help text', {hardRejection: false}));
expectType<Result<never>>(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<Result<never>>(meow({description: 'foo'}));
expectType<Result<never>>(meow({description: false}));
expectType<Result<never>>(meow({help: 'foo'}));
expectType<Result<never>>(meow({help: false}));
expectType<Result<never>>(meow({version: 'foo'}));
expectType<Result<never>>(meow({version: false}));
expectType<Result<never>>(meow({autoHelp: false}));
expectType<Result<never>>(meow({autoVersion: false}));
expectType<Result<never>>(meow({pkg: {foo: 'bar'}}));
expectType<Result<never>>(meow({argv: ['foo', 'bar']}));
expectType<Result<never>>(meow({inferType: true}));
expectType<Result<never>>(meow({booleanDefault: true}));
expectType<Result<never>>(meow({booleanDefault: null}));
expectType<Result<never>>(meow({booleanDefault: undefined}));
expectType<Result<never>>(meow({hardRejection: false}));
expectType<Result<never>>(meow({importMeta, description: 'foo'}));
expectType<Result<never>>(meow({importMeta, description: false}));
expectType<Result<never>>(meow({importMeta, help: 'foo'}));
expectType<Result<never>>(meow({importMeta, help: false}));
expectType<Result<never>>(meow({importMeta, version: 'foo'}));
expectType<Result<never>>(meow({importMeta, version: false}));
expectType<Result<never>>(meow({importMeta, autoHelp: false}));
expectType<Result<never>>(meow({importMeta, autoVersion: false}));
expectType<Result<never>>(meow({importMeta, pkg: {foo: 'bar'}}));
expectType<Result<never>>(meow({importMeta, argv: ['foo', 'bar']}));
expectType<Result<never>>(meow({importMeta, inferType: true}));
expectType<Result<never>>(meow({importMeta, booleanDefault: true}));
expectType<Result<never>>(meow({importMeta, booleanDefault: null}));
expectType<Result<never>>(meow({importMeta, booleanDefault: undefined}));
expectType<Result<never>>(meow({importMeta, hardRejection: false}));

const result = meow('Help text', {
importMeta,
flags: {
foo: {type: 'boolean', alias: 'f'},
'foo-bar': {type: 'number'},
Expand Down Expand Up @@ -66,6 +69,7 @@ result.showHelp(1);
result.showVersion();

const options = {
importMeta,
flags: {
rainbow: {
type: 'boolean',
Expand Down
53 changes: 10 additions & 43 deletions readme.md
Expand Up @@ -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 <input>

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 <input>
Expand All @@ -83,6 +42,7 @@ const cli = meow(`
$ foo unicorns --rainbow
🌈 unicorns 🌈
`, {
importMeta: import.meta,
flags: {
rainbow: {
type: 'boolean',
Expand Down Expand Up @@ -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`
Expand Down Expand Up @@ -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
Expand All @@ -268,6 +234,7 @@ const cli = meow(`
$ foo
🌈 unicorns✨🌈
`, {
importMeta: import.meta,
booleanDefault: undefined,
flags: {
rainbow: {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/fixture-allow-unknown-flags.js
Expand Up @@ -2,6 +2,7 @@
import meow from '../../index.js';

const cli = meow({
importMeta: import.meta,
description: 'Custom description',
help: `
Usage
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/fixture-required-function.js
Expand Up @@ -2,6 +2,7 @@
import meow from '../../index.js';

const cli = meow({
importMeta: import.meta,
description: 'Custom description',
help: `
Usage
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/fixture-required-multiple.js
Expand Up @@ -2,6 +2,7 @@
import meow from '../../index.js';

const cli = meow({
importMeta: import.meta,
description: 'Custom description',
help: `
Usage
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/fixture-required.js
Expand Up @@ -3,6 +3,7 @@
import meow from '../../index.js';

const cli = meow({
importMeta: import.meta,
description: 'Custom description',
help: `
Usage
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/fixture.js
Expand Up @@ -2,6 +2,7 @@
import meow from '../../index.js';

const cli = meow({
importMeta: import.meta,
description: 'Custom description',
help: `
Usage
Expand Down