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

feat: add parseSync/parseAsync method #1898

Merged
merged 3 commits into from Apr 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 14 additions & 2 deletions docs/api.md
Expand Up @@ -1338,9 +1338,21 @@ the resulting error and output will not be passed to the `parse()` callback (the

***Note:*** `parse()` should be called only once when [`command()`](#command) is called with a handler
returning a promise. If your use case requires `parse()` to be called several times, any asynchronous
operation performed in a command handler should not result in the handler returning a promise
operation performed in a command handler should not result in the handler returning a promise.

<a name="parsed"></a>.parsed
.parseAsync([args], [context], [parseCallback])
------------

Identical to `.parse()` except always returns a promise for a parsed argv
object, regardless of whether an async builder, handler, or middleware is used.

.parseSync([args], [context], [parseCallback])
------------

Identical to `.parse()` except an exception is thrown if an asynchronous
builder, handler, or middleware is used.

<a name="parsed"></a>.parsed [DEPRECATED]
------------
If the arguments have not been parsed, this property is `false`.

Expand Down
25 changes: 25 additions & 0 deletions lib/yargs-factory.ts
Expand Up @@ -1082,6 +1082,31 @@ export class YargsInstance {
}
return parsed;
}
parseAsync(
args?: string | string[],
shortCircuit?: object | ParseCallback | boolean,
_parseFn?: ParseCallback
): Promise<Arguments> {
const maybePromise = this.parse(args, shortCircuit, _parseFn);
if (!isPromise(maybePromise)) {
return Promise.resolve(maybePromise);
} else {
return maybePromise;
}
}
parseSync(
args?: string | string[],
shortCircuit?: object | ParseCallback | boolean,
_parseFn?: ParseCallback
): Arguments {
const maybePromise = this.parse(args, shortCircuit, _parseFn);
if (isPromise(maybePromise)) {
throw new YError(
'.parseSync() must not be used with asynchronous builders, handlers, or middleware'
);
}
return maybePromise;
}
parserConfiguration(config: Configuration) {
argsert('<object>', [config], arguments.length);
this.#parserConfig = config;
Expand Down
49 changes: 49 additions & 0 deletions test/yargs.cjs
Expand Up @@ -23,6 +23,9 @@ function clearRequireCache() {
delete require.cache[require.resolve('../index.cjs')];
delete require.cache[require.resolve('../build/index.cjs')];
}
function isPromise(maybePromise) {
return typeof maybePromise.then === 'function';
}

describe('yargs dsl tests', () => {
const oldProcess = {versions: {}};
Expand Down Expand Up @@ -3115,4 +3118,50 @@ describe('yargs dsl tests', () => {
assert.strictEqual(y2.getStrictOptions(), false);
});
});
describe('parseAsync', () => {
it('returns promise when parse is synchronous', () => {
const argv = yargs('foo').parseAsync();
assert.strictEqual(isPromise(argv), true);
});
it('returns promise when parse is asynchronous', async () => {
const argv = yargs('--foo bar')
.middleware(async () => {
await wait();
})
.parseAsync();
assert.strictEqual(isPromise(argv), true);
assert.strictEqual((await argv).foo, 'bar');
});
});
describe('parseSync', () => {
it('succeeds if no async functions used during parsing', () => {
const argv = yargs('foo 33')
.command(
'foo [bar]',
'foo command',
() => {},
() => {}
)
.middleware(argv => {
argv.bar *= 2;
})
.parseSync();
assert.strictEqual(argv.bar, 66);
});
it('throws if any async method is used', () => {
assert.throws(() => {
yargs('foo 33')
.command(
'foo [bar]',
'foo command',
() => {},
() => {}
)
.middleware(async argv => {
argv.bar *= 2;
})
.parseSync();
}, /.*parseSync\(\) must not be used.*/);
});
});
});