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 command builder to accept a promise #1042

Closed
quilicicf opened this issue Jan 9, 2018 · 15 comments · Fixed by #1888
Closed

Allow command builder to accept a promise #1042

quilicicf opened this issue Jan 9, 2018 · 15 comments · Fixed by #1888

Comments

@quilicicf
Copy link

quilicicf commented Jan 9, 2018

Feature request

Allow the command builder to accept a promise like follows:

yargs.command('command', 'Does foo', async function() { ... })

This feature is the same as the one from #510 but for the command builder.

Note: in #510, the example shows the async function as 3rd parameter, it should be as 4th because the 3rd is actually the command builder and not the command handler. I'll update this note when the comment is fixed.

Use case

The defaults of a command's parameter depend on the configuration of the app.
In some cases the configuration is not defined => the app prompts the user and helps him bootstrap the configuration then runs the initial command.
The command builder needs to be async.

@adamovsky
Copy link

adamovsky commented Jan 6, 2019

This feature would be great. A real life example why it's needed, is here:

https://github.com/stepweb/github/blob/master/src/commands/query/builder.js#L4

This is a GitHub GraphQL CLI that queries GitHub's API to resolve what the various possible commands are. However, since builder() doesn't support async, we need to compensate for this deficiency by front-loading all commands at boot-up (which is obviously not ideal since we're loading even things the user might not need).

https://github.com/stepweb/github/blob/master/index.js#L18

@LeoMartinDev
Copy link

Any update ?

@bcoe
Copy link
Member

bcoe commented Apr 18, 2019

👋 I think it would potentially be a fairly major overhaul to yargs to allow a builder to be asynchronous.

This functionality would be super cool, but it might not be something we can easily offer in the immediately future -- the problem being the expectation that const opts = yargs.parse('foo') will be populated with parsed options -- this wouldn't be possible if steps in yargs' configuration were asynchronous.

I wonder if it would be worth creating a new project ... call it async-yargs that returns a Promise rather than an options object?

@XGHeaven
Copy link

@bcoe I think to add a new api returns Promise instead of create a new package would be a good choice. for example

const opts = yargs.parse('foo') // options
const promise = yargs.parseAsync('foo') // Promise<options>

You can ignore a promise return value in sync mode and await promise in async mode.

@bcoe
Copy link
Member

bcoe commented Sep 20, 2020

@XGHeaven @quilicicf my thinking was that we could do this in the next major version of yargs, ideally once top level await is supported.

I believe we will need a bit of an overhaul of how we handle asynchronous behavior to get things right.

@quilicicf
Copy link
Author

That would be great 👍

@bcoe
Copy link
Member

bcoe commented Jan 9, 2021

I would like to investigate landing this work before we release the next major version of yargs.

Refs: #1823

@bcoe
Copy link
Member

bcoe commented Mar 14, 2021

@quilicicf @adamovsky could I ask you to try npm i yargs@next and let me know how it works for you?

If you provide an async builder now, yargs will return a promise rather than a parsed arguments object. There are still some bugs to work out, so it will be a couple more weeks before I think it lands.

@quilicicf
Copy link
Author

I'm setting up a reminder, will try to do that in the coming days 👍

@quilicicf
Copy link
Author

Hey @bcoe,

I have played around a bit with the async builder, it works like a charm with a little caveat I didn't expect: displaying the help calls the async builder, which means that in my use-case, the user is prompted for configuration before they get to see the command's help text.

I'm wondering if this can be worked around.

An example of the precise case where this can happen.

  • It's the first time I'm using git-on-steroids
  • I check the available commands with git-on-steroids --help => responds fast, no issue
  • Then I call mytool pr --help to check what it does
  • The command pr accepts a parameter --remote that allows me to specify the remote to open PRs on
  • The parameter --editor has a default value that is read from my personal configuration (every one has their conventions for naming remotes)
  • When there is no value in my personal configuration for a required setting, git-on-steroids prompts me for it, then executes the command
  • When I call mytool pr --help, the builder is called and tries to set the default value for --remote, so I'm prompted for the default value of the attribute --remote before I ever have the opportunity to discover what it is supposed to be

I'm wondering if yargs could give the builder the knowledge about whether the command was run with --help or not so that my builder decides whether to prompt the user or not depending on whether the command actually is supposed to be run or just documented 🤔

@bcoe
Copy link
Member

bcoe commented Mar 16, 2021

@quilicicf I think we need to execute the builder, before help, otherwise we can't show information like default values (if they're configured in the builder).

I like the idea of providing a second parameter to the builder that indicates whether it's helpOnly? This is actually already how things are implemented internally (we pass around a helpOnly variable, and use it to short-circuit before handlers).

@quilicicf
Copy link
Author

It'd be awesome to have this helpOnly info in the builder indeed :-)
I think it would close this issue gracefully 🎉

@bcoe
Copy link
Member

bcoe commented Mar 26, 2021

@quilicicf could you try npm i yargs@17.0.0-candidate.8? I've added the second parameter helpOrVersionSet.

bcoe added a commit that referenced this issue Mar 26, 2021
Fixes: #1042
BREAKING CHANGE: providing an async builder will now cause yargs to return async result
BREAKING CHANGE: .positional() now allowed at root level of yargs.
@quilicicf
Copy link
Author

Will do! @bcoe

@quilicicf
Copy link
Author

Works like a charm!
Thanks 🤩

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants