commander 8.2.0 → 8.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -98,7 +98,8 @@ const program = new Command();
98
98
  Options are defined with the `.option()` method, also serving as documentation for the options. Each option can have a short flag (single character) and a long name, separated by a comma or space or vertical bar ('|').
99
99
 
100
100
  The parsed options can be accessed by calling `.opts()` on a `Command` object, and are passed to the action handler.
101
- You can also use `.getOptionValue()` and `.setOptionValue()` to work with a single option value.
101
+ (You can also use `.getOptionValue()` and `.setOptionValue()` to work with a single option value,
102
+ and `.getOptionValueSource()` and `.setOptionValueWithSource()` when it matters where the option value came from.)
102
103
 
103
104
  Multi-word options such as "--template-engine" are camel-cased, becoming `program.opts().templateEngine` etc.
104
105
 
@@ -778,13 +779,6 @@ You can execute custom actions by listening to command and option events.
778
779
  program.on('option:verbose', function () {
779
780
  process.env.VERBOSE = this.opts().verbose;
780
781
  });
781
-
782
- program.on('command:*', function (operands) {
783
- console.error(`error: unknown command '${operands[0]}'`);
784
- const availableCommands = program.commands.map(cmd => cmd.name());
785
- mySuggestBestMatch(operands[0], availableCommands);
786
- process.exitCode = 1;
787
- });
788
782
  ```
789
783
 
790
784
  ## Bits and pieces
package/lib/command.js CHANGED
@@ -36,7 +36,7 @@ class Command extends EventEmitter {
36
36
  this._scriptPath = null;
37
37
  this._name = name || '';
38
38
  this._optionValues = {};
39
- this._optionValueSources = {}; // default < env < cli
39
+ this._optionValueSources = {}; // default < config < env < cli
40
40
  this._storeOptionsAsProperties = false;
41
41
  this._actionHandler = null;
42
42
  this._executableHandler = false;
@@ -463,10 +463,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
463
463
  *
464
464
  * @example
465
465
  * program
466
- * .command('help')
467
- * .description('display verbose help')
466
+ * .command('serve')
467
+ * .description('start service')
468
468
  * .action(function() {
469
- * // output help here
469
+ * // do work here
470
470
  * });
471
471
  *
472
472
  * @param {Function} fn
@@ -527,7 +527,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
527
527
  }
528
528
  // preassign only if we have a default
529
529
  if (defaultValue !== undefined) {
530
- this._setOptionValueWithSource(name, defaultValue, 'default');
530
+ this.setOptionValueWithSource(name, defaultValue, 'default');
531
531
  }
532
532
  }
533
533
 
@@ -558,13 +558,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
558
558
  if (typeof oldValue === 'boolean' || typeof oldValue === 'undefined') {
559
559
  // if no value, negate false, and we have a default, then use it!
560
560
  if (val == null) {
561
- this._setOptionValueWithSource(name, option.negate ? false : defaultValue || true, valueSource);
561
+ this.setOptionValueWithSource(name, option.negate ? false : defaultValue || true, valueSource);
562
562
  } else {
563
- this._setOptionValueWithSource(name, val, valueSource);
563
+ this.setOptionValueWithSource(name, val, valueSource);
564
564
  }
565
565
  } else if (val !== null) {
566
566
  // reassign
567
- this._setOptionValueWithSource(name, option.negate ? false : val, valueSource);
567
+ this.setOptionValueWithSource(name, option.negate ? false : val, valueSource);
568
568
  }
569
569
  };
570
570
 
@@ -793,13 +793,32 @@ Expecting one of '${allowedValues.join("', '")}'`);
793
793
  };
794
794
 
795
795
  /**
796
- * @api private
797
- */
798
- _setOptionValueWithSource(key, value, source) {
796
+ * Store option value and where the value came from.
797
+ *
798
+ * @param {string} key
799
+ * @param {Object} value
800
+ * @param {string} source - expected values are default/config/env/cli
801
+ * @return {Command} `this` command for chaining
802
+ */
803
+
804
+ setOptionValueWithSource(key, value, source) {
799
805
  this.setOptionValue(key, value);
800
806
  this._optionValueSources[key] = source;
807
+ return this;
801
808
  }
802
809
 
810
+ /**
811
+ * Get source of option value.
812
+ * Expected values are default | config | env | cli
813
+ *
814
+ * @param {string} key
815
+ * @return {string}
816
+ */
817
+
818
+ getOptionValueSource(key) {
819
+ return this._optionValueSources[key];
820
+ };
821
+
803
822
  /**
804
823
  * Get user arguments implied or explicit arguments.
805
824
  * Side-effects: set _scriptPath if args included application, and use that to set implicit command name.
@@ -1112,6 +1131,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1112
1131
  * @param {Promise|undefined} promise
1113
1132
  * @param {Function} fn
1114
1133
  * @return {Promise|undefined}
1134
+ * @api private
1115
1135
  */
1116
1136
 
1117
1137
  _chainOrCall(promise, fn) {
@@ -1456,8 +1476,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
1456
1476
  this.options.forEach((option) => {
1457
1477
  if (option.envVar && option.envVar in process.env) {
1458
1478
  const optionKey = option.attributeName();
1459
- // env is second lowest priority source, above default
1460
- if (this.getOptionValue(optionKey) === undefined || this._optionValueSources[optionKey] === 'default') {
1479
+ // Priority check. Do not overwrite cli or options from unknown source (client-code).
1480
+ if (this.getOptionValue(optionKey) === undefined || ['default', 'config', 'env'].includes(this.getOptionValueSource(optionKey))) {
1461
1481
  if (option.required || option.optional) { // option can take a value
1462
1482
  // keep very simple, optional always takes value
1463
1483
  this.emit(`optionEnv:${option.name()}`, process.env[option.envVar]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commander",
3
- "version": "8.2.0",
3
+ "version": "8.3.0",
4
4
  "description": "the complete solution for node.js command-line programs",
5
5
  "keywords": [
6
6
  "commander",
@@ -214,8 +214,9 @@ export interface OutputConfiguration {
214
214
 
215
215
  }
216
216
 
217
- type AddHelpTextPosition = 'beforeAll' | 'before' | 'after' | 'afterAll';
218
- type HookEvent = 'preAction' | 'postAction';
217
+ export type AddHelpTextPosition = 'beforeAll' | 'before' | 'after' | 'afterAll';
218
+ export type HookEvent = 'preAction' | 'postAction';
219
+ export type OptionValueSource = 'default' | 'env' | 'config' | 'cli';
219
220
 
220
221
  export interface OptionValues {
221
222
  [key: string]: any;
@@ -424,10 +425,10 @@ export class Command {
424
425
  * @example
425
426
  * ```
426
427
  * program
427
- * .command('help')
428
- * .description('display verbose help')
428
+ * .command('serve')
429
+ * .description('start service')
429
430
  * .action(function() {
430
- * // output help here
431
+ * // do work here
431
432
  * });
432
433
  * ```
433
434
  *
@@ -526,12 +527,22 @@ export class Command {
526
527
  */
527
528
  getOptionValue(key: string): any;
528
529
 
529
- /**
530
+ /**
530
531
  * Store option value.
531
532
  */
532
533
  setOptionValue(key: string, value: unknown): this;
533
534
 
534
535
  /**
536
+ * Store option value and where the value came from.
537
+ */
538
+ setOptionValueWithSource(key: string, value: unknown, source: OptionValueSource): this;
539
+
540
+ /**
541
+ * Retrieve option value source.
542
+ */
543
+ getOptionValueSource(key: string): OptionValueSource;
544
+
545
+ /**
535
546
  * Alter parsing of short flags with optional values.
536
547
  *
537
548
  * @example