From ae0fa5683f1f40efa7cffdaf86d3ad300dca97d6 Mon Sep 17 00:00:00 2001 From: Matt Hamann Date: Fri, 15 Apr 2022 00:02:32 -0400 Subject: [PATCH] feat(argv): handle nconf options w/ external yargs --- README.md | 10 +++++--- lib/nconf/stores/argv.js | 54 ++++++++++++++++++++++++++-------------- package.json | 2 +- test/stores/argv-test.js | 20 +++++++++++++++ 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index bf48f5c1..2f2fb4d5 100644 --- a/README.md +++ b/README.md @@ -240,10 +240,10 @@ If the return value is falsey, the entry will be dropped from the store, otherwi }); ``` -It's also possible to pass a configured yargs instance +It's also possible to pass a configured yargs instance and also include relevant nconf options. ``` js - nconf.argv(require('yargs') + let yargs = require('yargs') .version('1.2.3') .usage('My usage definition') .strict() @@ -254,7 +254,11 @@ It's also possible to pass a configured yargs instance demand: true, default: 'some-value' } - })); + }); + + nconf.argv(yargs, { + parseValues: true + }); ``` ### Env diff --git a/lib/nconf/stores/argv.js b/lib/nconf/stores/argv.js index ac006139..6d0466da 100644 --- a/lib/nconf/stores/argv.js +++ b/lib/nconf/stores/argv.js @@ -18,26 +18,39 @@ var util = require('util'), var Argv = exports.Argv = function (options, usage) { Memory.call(this, options); - options = options || {}; + this.isYargsExternal = false; + + options = options || {}; + + // Consistent handling when a yargs instance is passed in + if (isYargs(options)) { + this.yargs = this.options = options; + this.isYargsExternal = true; + + this._internalOptions = typeof usage === 'object' ? usage : {}; + } else { + this.yargs = require('yargs'); + this.options = this._internalOptions = options; + } + this.type = 'argv'; this.readOnly = true; - this.options = options; this.usage = usage; - if(typeof options.parseValues === 'boolean') { - this.parseValues = options.parseValues; - delete options.parseValues; + if(typeof this._internalOptions.parseValues === 'boolean') { + this.parseValues = this._internalOptions.parseValues; + delete this._internalOptions.parseValues; } else { this.parseValues = false; } - if (typeof options.transform === 'function') { - this.transform = options.transform; - delete options.transform; + if (typeof this._internalOptions.transform === 'function') { + this.transform = this._internalOptions.transform; + delete this._internalOptions.transform; } else { this.transform = false; } - if (typeof options.separator === 'string' || options.separator instanceof RegExp) { - this.separator = options.separator; - delete options.separator; + if (typeof this._internalOptions.separator === 'string' || this._internalOptions.separator instanceof RegExp) { + this.separator = this._internalOptions.separator; + delete this._internalOptions.separator; } else { this.separator = ''; } @@ -61,14 +74,17 @@ Argv.prototype.loadSync = function () { // into this instance. // Argv.prototype.loadArgv = function () { - var self = this, - yargs, argv; - - yargs = isYargs(this.options) ? - this.options : - typeof this.options === 'object' ? - require('yargs')(process.argv.slice(2)).options(this.options) : - require('yargs')(process.argv.slice(2)); + var self = this; + var yargs = this.yargs; + var argv; + + if (!this.isYargsExternal) { + if (typeof this._internalOptions === 'object') { + yargs = this.yargs(process.argv.slice(2)).options(this._internalOptions); + } else { + yargs = this.yargs(process.argv.slice(2)); + } + } if (typeof this.usage === 'string') { yargs.usage(this.usage) } diff --git a/package.json b/package.json index cf86478b..1d0c9e77 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "async": "^3.0.0", "ini": "^2.0.0", "secure-keys": "^1.0.0", - "yargs": "^16.1.1" + "yargs": "^17.4.1" }, "devDependencies": { "coveralls": "^3.1.0", diff --git a/test/stores/argv-test.js b/test/stores/argv-test.js index fb2b457f..76aae9b8 100644 --- a/test/stores/argv-test.js +++ b/test/stores/argv-test.js @@ -35,6 +35,26 @@ vows.describe('nconf/stores/argv').addBatch({ assert.equal(argv.get('v'), 'false'); } }, + "can be created with a custom yargs with nconf options":{ + topic: function(){ + var yargsInstance = yargs(['--help', 'foo']).alias('v', 'verbose').default('v', 'false').version(false).help(false).usage(false); + return [yargsInstance, new nconf.Argv(yargsInstance, { + parseValues: true, + })]; + }, + "and can give access to them": function (argv) { + var yargsInstance = argv[0]; + argv = argv[1] + assert.equal(argv.options, yargsInstance) + }, + "values are the one from the custom yargv, but parsed": function (argv) { + argv = argv[1] + argv.loadSync() + assert.equal(argv.get('verbose'), false); + assert.equal(argv.get('v'), false); + assert.equal(argv.get('help'), 'foo'); + } + }, "can be created with a nconf yargs":{ topic: function(){ var options = {verbose: {alias: 'v', default: 'false'}};