From c2c90ba6c4b3ca45bb5085c2a2046b0b57f9823c Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Thu, 1 Sep 2022 11:02:03 -0300 Subject: [PATCH] implement strict priorities. --- lib/command.js | 28 +++++++++++++++++----------- typings/index.d.ts | 4 ++-- typings/index.test-d.ts | 2 +- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/command.js b/lib/command.js index 7f125e5e8..4e97e80c1 100644 --- a/lib/command.js +++ b/lib/command.js @@ -57,13 +57,14 @@ class Command extends EventEmitter { this._showHelpAfterError = false; this._showSuggestionAfterError = true; - // 'unknown' value is left out on purpose, should be treated as such - this._precedence = [ - 'default', - 'implied', // implied by others configs - 'config', // placeholder for configuration files + this._strictPriority = false; + this._priorities = [ + 'cli', 'env', - 'cli' + 'config', // placeholder for configuration files + 'implied', // implied by others configs + 'default', // default option value + undefined // initial state, not touched yet ]; // see .configureOutput() for docs @@ -421,6 +422,13 @@ Expecting one of '${allowedValues.join("', '")}'`); return this; } + strictPriority(priorities) { + this._strictPriority = true; + if (priorities) { + this._priorities = priorities; + } + } + /** * Register callback to use as replacement for calling process.exit. * @@ -802,7 +810,8 @@ Expecting one of '${allowedValues.join("', '")}'`); * @return {Command} `this` command for chaining */ - setOptionValueWithSource(key, value, source = 'unknown') { + setOptionValueWithSource(key, value, source = null) { + if (this._strictPriority && !this._isNewSourcePreferred(source, this.getOptionValueSource(key))) return; if (this._storeOptionsAsProperties) { this[key] = value; } else { @@ -1612,10 +1621,7 @@ Expecting one of '${allowedValues.join("', '")}'`); * @api private */ _isNewSourcePreferred(newSource, existingSource) { - // unknown source should always take precedence. undefined existingSource means option not set. - if (newSource == null || !this._precedence.includes(newSource) || existingSource === undefined) return true; - if (existingSource === null || !this._precedence.includes(existingSource)) return false; - return this._precedence.indexOf(newSource) >= this._precedence.indexOf(existingSource); + return this._priorities.indexOf(newSource) <= this._priorities.indexOf(existingSource); } /** diff --git a/typings/index.d.ts b/typings/index.d.ts index 93dbec84a..aa65b5f69 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -266,7 +266,7 @@ export interface OutputConfiguration { export type AddHelpTextPosition = 'beforeAll' | 'before' | 'after' | 'afterAll'; export type HookEvent = 'preSubcommand' | 'preAction' | 'postAction'; -export type OptionValueSource = 'default' | 'implied' | 'config' | 'env' | 'cli' | 'unknown'; +export type OptionValueSource = 'default' | 'implied' | 'config' | 'env' | 'cli' | null; export interface OptionValues { [key: string]: any; @@ -595,7 +595,7 @@ export class Command { /** * Retrieve option value source. */ - getOptionValueSource(key: string): OptionValueSource; + getOptionValueSource(key: string): OptionValueSource | undefined; /** * Alter parsing of short flags with optional values. diff --git a/typings/index.test-d.ts b/typings/index.test-d.ts index 94c0b53d1..7b8af12ea 100644 --- a/typings/index.test-d.ts +++ b/typings/index.test-d.ts @@ -172,7 +172,7 @@ expectType(program.setOptionValue('example', true)); expectType(program.setOptionValueWithSource('example', [], 'cli')); // getOptionValueSource -expectType(program.getOptionValueSource('example')); +expectType(program.getOptionValueSource('example')); // combineFlagAndOptionalValue expectType(program.combineFlagAndOptionalValue());