verdaccio
Version:
A lightweight private npm proxy registry
144 lines (106 loc) • 4.15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = loadPlugin;
var _path = _interopRequireDefault(require("path"));
var _lodash = _interopRequireDefault(require("lodash"));
var _logger = _interopRequireDefault(require("./logger"));
var _constants = require("./constants");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @prettier
*
*/
/**
* Requires a module.
* @param {*} path the module's path
* @return {Object}
*/
function tryLoad(path) {
try {
return require(path);
} catch (err) {
if (err.code === _constants.MODULE_NOT_FOUND) {
return null;
}
throw err;
}
}
function mergeConfig(appConfig, pluginConfig) {
return _lodash.default.merge(appConfig, pluginConfig);
}
function isValid(plugin) {
return _lodash.default.isFunction(plugin) || _lodash.default.isFunction(plugin.default);
}
function isES6(plugin) {
return Object.keys(plugin).includes('default');
}
/**
* Load a plugin following the rules
* - First try to load from the internal directory plugins (which will disappear soon or later).
* - A second attempt from the external plugin directory
* - A third attempt from node_modules, in case to have multiple match as for instance verdaccio-ldap
* and sinopia-ldap. All verdaccio prefix will have preferences.
* @param {*} config a reference of the configuration settings
* @param {*} pluginConfigs
* @param {*} params a set of params to initialize the plugin
* @param {*} sanityCheck callback that check the shape that should fulfill the plugin
* @return {Array} list of plugins
*/
function loadPlugin(config, pluginConfigs = {}, params, sanityCheck, prefix = 'verdaccio') {
return Object.keys(pluginConfigs).map(pluginId => {
let plugin;
const localPlugin = _path.default.resolve(__dirname + '/../plugins', pluginId); // try local plugins first
plugin = tryLoad(localPlugin); // try the external plugin directory
if (plugin === null && config.plugins) {
const pluginDir = config.plugins;
const externalFilePlugin = _path.default.resolve(pluginDir, pluginId);
plugin = tryLoad(externalFilePlugin); // npm package
if (plugin === null && pluginId.match(/^[^\.\/]/)) {
plugin = tryLoad(_path.default.resolve(pluginDir, `${prefix}-${pluginId}`)); // compatibility for old sinopia plugins
if (!plugin) {
plugin = tryLoad(_path.default.resolve(pluginDir, `sinopia-${pluginId}`));
}
}
} // npm package
if (plugin === null && pluginId.match(/^[^\.\/]/)) {
plugin = tryLoad(`${prefix}-${pluginId}`); // compatibility for old sinopia plugins
if (!plugin) {
plugin = tryLoad(`sinopia-${pluginId}`);
}
}
if (plugin === null) {
plugin = tryLoad(pluginId);
} // relative to config path
if (plugin === null && pluginId.match(/^\.\.?($|\/)/)) {
plugin = tryLoad(_path.default.resolve(_path.default.dirname(config.self_path), pluginId));
}
if (plugin === null) {
_logger.default.logger.error({
content: pluginId
}, 'plugin not found. try npm install verdaccio-@{content}');
throw Error(`
${prefix}-${pluginId} plugin not found. try "npm install ${prefix}-${pluginId}"`);
}
if (!isValid(plugin)) {
_logger.default.logger.error({
content: pluginId
}, "@{content} doesn't look like a valid plugin");
throw Error(`"${pluginId}" is not a valid plugin`);
}
/* eslint new-cap:off */
plugin = isES6(plugin) ? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params) : plugin(pluginConfigs[pluginId], params);
/* eslint new-cap:off */
if (plugin === null || !sanityCheck(plugin)) {
_logger.default.logger.error({
content: pluginId
}, "@{content} doesn't look like a valid plugin");
throw Error(`"${pluginId}" is not a valid plugin`);
}
_logger.default.logger.warn({
content: `${prefix}-${pluginId}`
}, 'Plugin successfully loaded: @{content}');
return plugin;
});
}