in src/config.js [38:140]
export function applyConfigToArgv({
argv,
argvFromCLI,
configObject,
options,
configFileName,
}) {
let newArgv = { ...argv };
for (const option of Object.keys(configObject)) {
if (camelCase(option) !== option) {
throw new UsageError(
`The config option "${option}" must be ` +
`specified in camel case: "${camelCase(option)}"`,
);
}
// A config option cannot be a sub-command config
// object if it is an array.
if (
!Array.isArray(configObject[option]) &&
typeof options[option] === 'object' &&
typeof configObject[option] === 'object'
) {
// Descend into the nested configuration for a sub-command.
newArgv = applyConfigToArgv({
argv: newArgv,
argvFromCLI,
configObject: configObject[option],
options: options[option],
configFileName,
});
continue;
}
const decamelizedOptName = decamelize(option, { separator: '-' });
if (typeof options[decamelizedOptName] !== 'object') {
throw new UsageError(
`The config file at ${configFileName} specified ` +
`an unknown option: "${option}"`,
);
}
if (options[decamelizedOptName].type === undefined) {
// This means yargs option type wasn't not defined correctly
throw new WebExtError(`Option: ${option} was defined without a type.`);
}
const expectedType =
options[decamelizedOptName].type === 'count'
? 'number'
: options[decamelizedOptName].type;
const optionType = Array.isArray(configObject[option])
? 'array'
: typeof configObject[option];
if (optionType !== expectedType) {
throw new UsageError(
`The config file at ${configFileName} specified ` +
`the type of "${option}" incorrectly as "${optionType}"` +
` (expected type "${expectedType}")`,
);
}
let defaultValue;
if (options[decamelizedOptName]) {
if (options[decamelizedOptName].default !== undefined) {
defaultValue = options[decamelizedOptName].default;
} else if (expectedType === 'boolean') {
defaultValue = false;
}
}
// This is our best effort (without patching yargs) to detect
// if a value was set on the CLI instead of in the config.
// It looks for a default value and if the argv value is
// different, it assumes that the value was configured on the CLI.
const wasValueSetOnCLI =
typeof argvFromCLI[option] !== 'undefined' &&
argvFromCLI[option] !== defaultValue;
if (wasValueSetOnCLI) {
log.debug(
`Favoring CLI: ${option}=${argvFromCLI[option]} over ` +
`configuration: ${option}=${configObject[option]}`,
);
newArgv[option] = argvFromCLI[option];
continue;
}
newArgv[option] = configObject[option];
const coerce = options[decamelizedOptName].coerce;
if (coerce) {
log.debug(`Calling coerce() on configured value for ${option}`);
newArgv[option] = coerce(newArgv[option]);
}
newArgv[decamelizedOptName] = newArgv[option];
}
return newArgv;
}