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
10 changes: 10 additions & 0 deletions index.d.ts
Expand Up @@ -20,13 +20,21 @@ export interface Flag<Type extends FlagType, Default> {
readonly isMultiple?: boolean;
}

type ImportMeta = {url: string};
LitoMore marked this conversation as resolved.
Show resolved Hide resolved
type StringFlag = Flag<'string', string>;
type BooleanFlag = Flag<'boolean', boolean>;
type NumberFlag = Flag<'number', number>;
type AnyFlag = StringFlag | BooleanFlag | NumberFlag;
type AnyFlags = Record<string, AnyFlag>;

export interface Options<Flags extends AnyFlags> {
/**
Directory to start looking for the module package.json file.

This option is required, its value must be `import.meta`.
*/
LitoMore marked this conversation as resolved.
Show resolved Hide resolved
readonly importMeta: ImportMeta;

/**
Define argument flags.

Expand Down Expand Up @@ -151,6 +159,7 @@ export interface Options<Flags extends AnyFlags> {
$ foo
🌈 unicorns✨🌈
`, {
importMeta: import.meta,
booleanDefault: undefined,
flags: {
rainbow: {
Expand Down Expand Up @@ -288,6 +297,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('`importMeta` options is required, its value must be `import.meta`');
LitoMore marked this conversation as resolved.
Show resolved Hide resolved
}

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
55 changes: 12 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,14 @@ Shortcut for the `help` option.

Type: `object`

##### importMeta

Type: `string`

Directory to start looking for the module package.json file.

This option is required, its value must be `import.meta`.
LitoMore marked this conversation as resolved.
Show resolved Hide resolved

##### flags

Type: `object`
Expand Down Expand Up @@ -253,7 +221,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 +236,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