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

How to stop yargs handling --help, --version etc #395

Open
jcoglan opened this issue Apr 5, 2022 · 2 comments
Open

How to stop yargs handling --help, --version etc #395

jcoglan opened this issue Apr 5, 2022 · 2 comments

Comments

@jcoglan
Copy link

jcoglan commented Apr 5, 2022

Forgive me if this is a silly question, but after a few hours reading the docs for nconf and yargs I've not been able to figure it out. Say I have this program that reads config from argv or env, and it normalises the parameter names from each source using transform() functions:

const nconf = require('nconf')
const yargs = require('yargs')

const ENV_PREFIX = /^DEMO_/

nconf.argv({
  transform ({ key, value }) {
    key = key.replace(/-/g, '_')
    return { key, value }
  },
  parseValues: true
})

nconf.env({
  transform ({ key, value }) {
    if (ENV_PREFIX.test(key)) {
      key = key.replace(ENV_PREFIX, '').toLowerCase()
      return { key, value }
    }
  },
  parseValues: true
})

let options = {
  setup: nconf.get('setup'),
  max_jobs: nconf.get('max_jobs')
}

console.log(options)

This parses values from each source correctly and selects values with the correct precedence:

$ node nconf-demo.js
{ setup: undefined, max_jobs: undefined }

$ DEMO_SETUP=true DEMO_MAX_JOBS=2 node nconf-demo.js
{ setup: true, max_jobs: 2 }

$ DEMO_SETUP=true DEMO_MAX_JOBS=2 node nconf-demo.js --no-setup --max-jobs 3
{ setup: false, max_jobs: 3 }

However, certain argument names cause special behaviour in yargs, for example if you use --help or --version then yargs executes a special handler and terminates the process:

$ node nconf-demo.js --help
Options:
  --help     Show help                                                 [boolean]
  --version  Show version number                                       [boolean]

Allowing the config parser to exit the process is not desirable behaviour for a long-running process, and it also makes the application impossible to test other than by bypassing its CLI script, so I would like to turn this behaviour off. I tried doing this by modifying the argv() call as follows:

nconf.argv(yargs.help(false).version(false), {
  transform ({ key, value }) {
    key = key.replace(/-/g, '_')
    return { key, value }
  },
  parseValues: true
})

This causes strange behaviour, for example the --max-job setting is ignored:

$ DEMO_SETUP=true DEMO_MAX_JOBS=2 node nconf-demo.js --no-setup --max-jobs 3
{ setup: false, max_jobs: 2 }

It turns out that in this case, the transform() function for argv is not executed, so the key remains as max-jobs instead of being canonicalised to max_jobs.

Is it possible to turn off these special behaviours of yargs so that it functions only as an argument parser, without printing its own output or exiting the process, while using nconf options like transform() at the same time?

As an aside, I discovered that parseValues is also ignored here, but its default value for argv is true contrary to what the docs say. i.e. calling nconf.argv({ parseValues: false }) has no effect; arguments are turned into numbers and booleans rather than remaining as strings.

@mhamann
Copy link
Collaborator

mhamann commented Apr 7, 2022

That's an interesting find! I need to look at this a bit deeper to see if there's a way to alter this behavior. This might also be a bug in nconf...

In the meantime, if you happen to discover any new information, please let me know!

@mhamann
Copy link
Collaborator

mhamann commented Apr 15, 2022

@jcoglan I finally got a few minutes to take a closer look at this.

I'm not sure what the original intent of nconf + yargs was, but it makes sense to me that someone might want to use some of the CLI features from yargs (like usage and help) as part of their nconf-enabled app. I would assume there are folks doing this today.

However, as you noted, some people may not want that behavior, which is why nconf supports a custom/external yargs instance being passed to the argv loader (as you showed in your final example).

You also observed that passing a custom yargs instance to nconf results in options like parseValues being ignored/unavailable. While the readme doesn't explicitly state that such a scenario is supported, I do agree that intuitively, someone would expect to be able to use both features in parallel. I've implemented a fix for this behavior and updated the readme to explicitly show its availability. I think this will launch as part of nconf v0.13 next week.

Finally, I investigated your assertion that parseValues: false is not the default for the argv loader, but I could not duplicate the behavior you indicated. When I don't specify that option in the args, values are not parsed (e.g., 'false' is a string, not a boolean). Fliping parseValues: true resulted in the expected behavior of 'false' becoming a boolean. If you still find that this is a problem, please provide a code sample so I can duplicate it.

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

No branches or pull requests

2 participants