hardhat
Version:
Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
125 lines • 5.91 kB
JavaScript
import { HardhatError } from "@nomicfoundation/hardhat-errors";
import { getEnvVariableNameFromGlobalOption } from "@nomicfoundation/hardhat-utils/env";
import { ArgumentType } from "../../types/arguments.js";
import { parseArgumentValue, validateArgumentValue, validateArgumentName, validateArgumentShortName, } from "./arguments.js";
/**
* Builds a map of the global option definitions by going through all the
* plugins and validating the global options they define.
*
* Note: this function can be used before initializing the HRE, so the plugins
* shouldn't be consider validated. Hence, we should validate the global
* options.
*/
export function buildGlobalOptionDefinitions(resolvedPlugins) {
const globalOptionDefinitions = new Map();
const globalOptionDefinitionsByShortName = new Map();
for (const plugin of resolvedPlugins) {
if (plugin.globalOptions === undefined) {
continue;
}
for (const option of plugin.globalOptions) {
const existingByName = globalOptionDefinitions.get(option.name);
if (existingByName !== undefined) {
throw new HardhatError(HardhatError.ERRORS.CORE.GENERAL.GLOBAL_OPTION_ALREADY_DEFINED, {
plugin: plugin.id,
globalOption: option.name,
definedByPlugin: existingByName.pluginId,
});
}
if (option.shortName !== undefined) {
const existingByShortName = globalOptionDefinitionsByShortName.get(option.shortName);
if (existingByShortName !== undefined) {
throw new HardhatError(HardhatError.ERRORS.CORE.GENERAL.GLOBAL_OPTION_ALREADY_DEFINED, {
plugin: plugin.id,
globalOption: option.shortName,
definedByPlugin: existingByShortName.pluginId,
});
}
}
const validatedGlobalOption = buildGlobalOptionDefinition(option);
const mapEntry = {
pluginId: plugin.id,
option: validatedGlobalOption,
};
globalOptionDefinitions.set(validatedGlobalOption.name, mapEntry);
if (validatedGlobalOption.shortName !== undefined) {
globalOptionDefinitionsByShortName.set(validatedGlobalOption.shortName, mapEntry);
}
}
}
return globalOptionDefinitions;
}
/**
* Builds a global option definition, validating the name, type, and default
* value.
*/
export function buildGlobalOptionDefinition({ name, shortName, description, type, defaultValue, }) {
const argumentType = type ?? ArgumentType.STRING;
validateArgumentName(name);
if (shortName !== undefined) {
validateArgumentShortName(shortName);
}
validateArgumentValue("defaultValue", argumentType, defaultValue);
return {
name,
shortName,
description,
type: argumentType,
defaultValue,
};
}
/**
* Resolves global options by merging user-provided options with environment
* variables, adhering to predefined global option definitions. This function
* ensures that only options specified in the globalOptionDefinitions are
* considered. Each option is validated against its definition in the map, with
* user-provided options taking precedence over environment variables. If an
* option is not provided by the user or set as an environment variable, its
* default value (as specified in the globalOptionDefinitions) is used.
*
* @param userProvidedGlobalOptions The options explicitly provided by the
* user. These take precedence over equivalent environment variables.
* @param globalOptionDefinitions A map defining valid global options, their default
* values, and expected types. This map is used to validate and parse the options.
* @returns {GlobalOptions} An object containing the resolved global options,
* with each option adhering to its definition in the globalOptionDefinitions.
* @throws {HardhatError} with descriptor
* {@link HardhatError.ERRORS.CORE.ARGUMENTS.INVALID_VALUE_FOR_TYPE} if a user-provided
* option has an invalid value for its type.
*/
export function resolveGlobalOptions(userProvidedGlobalOptions, globalOptionDefinitions) {
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions --
We start with an empty object, and incrementally build a safe GlobalOptions */
const globalOptions = {};
// iterate over the definitions to parse and validate the arguments
for (const [name, { option }] of globalOptionDefinitions) {
let value =
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
-- GlobalOptions is empty for user extension, so we need to cast it to
assign the value. */
userProvidedGlobalOptions[name];
let parsedValue;
// if the value is provided in the user options, it's already parsed
// and it takes precedence over env vars
if (value !== undefined) {
parsedValue = value;
}
else {
value = process.env[getEnvVariableNameFromGlobalOption(name)];
if (value !== undefined) {
// if the value is provided via an env var, it needs to be parsed
parsedValue = parseArgumentValue(value, option.type, name);
}
else {
// if the value is not provided by the user or env var, use the default
parsedValue = option.defaultValue;
}
}
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions --
This operation is unsafe, because the GlobalOptions type is augmented by
plugins. */
globalOptions[name] = parsedValue;
}
return globalOptions;
}
//# sourceMappingURL=global-options.js.map