UNPKG

@nomiclabs/buidler

Version:

Buidler is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.

152 lines 6.54 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const debug_1 = __importDefault(require("debug")); const path = __importStar(require("path")); const semver = __importStar(require("semver")); const errors_1 = require("./errors"); const errors_list_1 = require("./errors-list"); const execution_mode_1 = require("./execution-mode"); const log = debug_1.default("buidler:core:plugins"); /** * Validates a plugin dependencies and loads it. * @param pluginName - The plugin name * @param buidlerContext - The BuidlerContext * @param from - Where to resolve plugins and dependencies from. Only for * testing purposes. */ function usePlugin(buidlerContext, pluginName, from) { log("Loading plugin %s", pluginName); const executionMode = execution_mode_1.getExecutionMode(); if (from === undefined) { // We have two different ways to search for plugins. // // If Buidler is installed globally, we want to force the plugins to also be // installed globally, otherwise we can end up in a very chaotic situation. // The way we enforce this is by setting `from` to something inside Buidler // itself, as it will be placed in the global node_modules. // // If Buidler is not installed globally, we want the plugins to be // accessible from the project's root, not from the Buidler installation. // The reason for this is that yarn workspaces can easily hoist Buidler and // not the plugins, leaving you with something like this: // // root/ // node_modules/ // buidler // subpackage1/ // node_modules/ // plugin@v1/ // buidler.config.js // subpackage2/ // node_modules/ // plugin@v2/ // buidler.config.js // // If we were to load the plugins from the Buidler installation in this // situation, they wouldn't be found. Instead, we should load them from the // project's root. // // To make things slightly more complicated, we don't really know the // project's root, as we are still loading the config. What we do know // though, is the config file's path, which must be inside the project, so // we use that instead. if (executionMode === execution_mode_1.ExecutionMode.EXECUTION_MODE_GLOBAL_INSTALLATION) { from = __dirname; } else { from = buidlerContext.getConfigPath(); } } let globalFlag = ""; let globalWarning = ""; if (executionMode === execution_mode_1.ExecutionMode.EXECUTION_MODE_GLOBAL_INSTALLATION) { globalFlag = " --global"; globalWarning = "You are using a global installation of Buidler. Plugins and their dependencies must also be global.\n"; } const pluginPackageJson = readPackageJson(pluginName, from); if (pluginPackageJson === undefined) { const installExtraFlags = globalFlag; throw new errors_1.BuidlerError(errors_list_1.ERRORS.PLUGINS.NOT_INSTALLED, { plugin: pluginName, extraMessage: globalWarning, extraFlags: installExtraFlags, }); } // We use the package.json's version of the name, as it is normalized. pluginName = pluginPackageJson.name; if (buidlerContext.loadedPlugins.includes(pluginName)) { return; } if (pluginPackageJson.peerDependencies !== undefined) { for (const [dependencyName, versionSpec] of Object.entries(pluginPackageJson.peerDependencies)) { const dependencyPackageJson = readPackageJson(dependencyName, from); let installExtraFlags = globalFlag; if (versionSpec.match(/^[0-9]/) !== null) { installExtraFlags += " --save-exact"; } if (dependencyPackageJson === undefined) { throw new errors_1.BuidlerError(errors_list_1.ERRORS.PLUGINS.MISSING_DEPENDENCY, { plugin: pluginName, dependency: dependencyName, extraMessage: globalWarning, extraFlags: installExtraFlags, versionSpec, }); } const installedVersion = dependencyPackageJson.version; if (!semver.satisfies(installedVersion, versionSpec, { includePrerelease: true, })) { throw new errors_1.BuidlerError(errors_list_1.ERRORS.PLUGINS.DEPENDENCY_VERSION_MISMATCH, { plugin: pluginName, dependency: dependencyName, extraMessage: globalWarning, extraFlags: installExtraFlags, versionSpec, installedVersion, }); } } } const options = from !== undefined ? { paths: [from] } : undefined; const pluginPath = require.resolve(pluginName, options); loadPluginFile(pluginPath); buidlerContext.setPluginAsLoaded(pluginName); } exports.usePlugin = usePlugin; function loadPluginFile(absolutePluginFilePath) { log("Loading plugin file %s", absolutePluginFilePath); const imported = require(absolutePluginFilePath); const plugin = imported.default !== undefined ? imported.default : imported; if (typeof plugin === "function") { plugin(); } } exports.loadPluginFile = loadPluginFile; function readPackageJson(packageName, from) { try { const options = from !== undefined ? { paths: [from] } : undefined; const packageJsonPath = require.resolve(path.join(packageName, "package.json"), options); return require(packageJsonPath); } catch (error) { return undefined; } } exports.readPackageJson = readPackageJson; function ensurePluginLoadedWithUsePlugin() { // No-op. Only here for backwards compatibility } exports.ensurePluginLoadedWithUsePlugin = ensurePluginLoadedWithUsePlugin; //# sourceMappingURL=plugins.js.map