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

Yargs v17 calls coerce with undefined when option is not passed #2130

Closed
dsamerotte opened this issue Feb 5, 2022 · 4 comments
Closed

Yargs v17 calls coerce with undefined when option is not passed #2130

dsamerotte opened this issue Feb 5, 2022 · 4 comments

Comments

@dsamerotte
Copy link

Per #1219, yargs has not historically called coerce when the associated option is not passed. However, when porting my code to v17, I see that this is no longer the case, and I'm wondering whether this is an intentional breaking change or a regression. The only potentially relevant breaking change that I see in the release notes is that "coerce is now applied before validation," but I wouldn't expect this change in behavior from that description alone.

I understand that yarg's middleware underwent substantial changes in v17. Based on my two-second investigation, it looks like v16 maps over the supplied options and then calls coerce as needed, such that coerce can never receive undefined. However, v17 instead appears to reduce all middleware without checking the existence of the related option.

The obvious result is that code like .coerce('dir', path.resolve), which still appears in the docs, no longer works, and client code now needs to explicitly check for undefined.

If this is an intentional change, should this also affect subcommand processing? I'm even seeing coerce called like this in parent commands when calling only a subcommand and when the parent option is not passed and is marked as global: false. If I understand the global option correctly, this seems especially strange.

I thought I'd keep this short and start with the high-level question first. Based on the answer, I can, of course, provide additional thoughts and information. Thanks!

@elitree
Copy link

elitree commented Feb 24, 2022

Just to illustrate with an example of one difference in v17 which doesn't seem right (or at least, I didn't anticipate it based on the changelog):

const yargs = require('yargs');

let args = yargs
.strict()
.option('abc', {
    boolean: true
})
.option('xyz',{
    implies: ['abc'],
    // removing this coerce method will avoid errors when no params are passed
    coerce: (val) => val && val.toLowerCase()
});

console.log('////yargs x.y.z////');
console.log(JSON.stringify(args));

Based on the above, since option 'abc' isn't a required option, I would expect to be able to pass no arguments. This is the case in v16:

$ node index.js
////yargs 16.2.0////
{"$0":"index.js","parsed":false,"argv":{"_":[],"$0":"index.js"}}

In v17, however, the combination of the requires relationship and the coerce causes a "Missing dependent arguments" error:

$ node index.js
////yargs 17.3.0////
Options:
  --help     Show help                                                 [boolean]
  --version  Show version number                                       [boolean]
  --abc                                                                [boolean]
  --xyz

Missing dependent arguments:
 xyz -> abc

As another related bit of information here, when no coerce method is defined for xyz, the implies method works the same in both v16 and v17 for this scenario, and does not generate a dependents error:

$ node index.js
////yargs 16.2.0 without coerce for xyz////
{"$0":"index.js","parsed":false,"argv":{"_":[],"$0":"index.js"}}

$ node index.js
////yargs 17.3.0 without coerce for xyz////
{"customScriptName":false,"parsed":false,"$0":"index.js","argv":{"_":[],"$0":"index.js"}}

Given that there's no dependents error for the implies relationship in v17 after merely removing the coerce method, it seems that this new behavior isn't the desired one. Is this a bug? Thanks!

@bcoe
Copy link
Member

bcoe commented Mar 19, 2022

@dsamerotte this sounds like an unintended breaking change, which would be good to fix.

@xmedeko
Copy link

xmedeko commented Apr 20, 2022

Should be fixed in 17.4.1.

@jly36963 jly36963 removed their assignment Jan 29, 2023
@shadowspawn
Copy link
Member

Closing as fixed by #2161.

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

No branches or pull requests

6 participants