| 'use strict' | |
| const fs = require('graceful-fs') | |
| const path = require('path') | |
| const helper = require('./helper') | |
| const log = require('./logger').create('plugin') | |
| const IGNORED_PACKAGES = ['karma-cli', 'karma-runner.github.com'] | |
| function resolve (plugins, emitter) { | |
| const modules = [] | |
| function requirePlugin (name) { | |
| log.debug(`Loading plugin ${name}.`) | |
| try { | |
| modules.push(require(name)) | |
| } catch (e) { | |
| if (e.code === 'MODULE_NOT_FOUND' && e.message.includes(name)) { | |
| log.error(`Cannot find plugin "${name}".\n Did you forget to install it?\n npm install ${name} --save-dev`) | |
| } else { | |
| log.error(`Error during loading "${name}" plugin:\n ${e.message}`) | |
| } | |
| emitter.emit('load_error', 'plug_in', name) | |
| } | |
| } | |
| plugins.forEach(function (plugin) { | |
| if (helper.isString(plugin)) { | |
| if (!plugin.includes('*')) { | |
| requirePlugin(plugin) | |
| return | |
| } | |
| const pluginDirectory = path.normalize(path.join(__dirname, '/../..')) | |
| const regexp = new RegExp(`^${plugin.replace(/\*/g, '.*').replace(/\//g, '[/\\\\]')}`) | |
| log.debug(`Loading ${plugin} from ${pluginDirectory}`) | |
| fs.readdirSync(pluginDirectory) | |
| .map((e) => { | |
| const modulePath = path.join(pluginDirectory, e) | |
| if (e[0] === '@') { | |
| return fs.readdirSync(modulePath).map((e) => path.join(modulePath, e)) | |
| } | |
| return modulePath | |
| }) | |
| .reduce((a, x) => a.concat(x), []) | |
| .map((modulePath) => path.relative(pluginDirectory, modulePath)) | |
| .filter((moduleName) => !IGNORED_PACKAGES.includes(moduleName) && regexp.test(moduleName)) | |
| .forEach((pluginName) => requirePlugin(path.join(pluginDirectory, pluginName))) | |
| } else if (helper.isObject(plugin)) { | |
| log.debug(`Loading inline plugin defining ${Object.keys(plugin).join(', ')}.`) | |
| modules.push(plugin) | |
| } else { | |
| log.error(`Invalid plugin ${plugin}`) | |
| emitter.emit('load_error', 'plug_in', plugin) | |
| } | |
| }) | |
| return modules | |
| } | |
| /** | |
| Create a function to handle errors in plugin loading. | |
| @param {Object} injector, the dict of dependency injection objects. | |
| @return function closed over injector, which reports errors. | |
| */ | |
| function createInstantiatePlugin (injector) { | |
| const emitter = injector.get('emitter') | |
| // Cache to avoid report errors multiple times per plugin. | |
| const pluginInstances = new Map() | |
| return function instantiatePlugin (kind, name) { | |
| if (pluginInstances.has(name)) { | |
| return pluginInstances.get(name) | |
| } | |
| let p | |
| try { | |
| p = injector.get(`${kind}:${name}`) | |
| if (!p) { | |
| log.error(`Failed to instantiate ${kind} ${name}`) | |
| emitter.emit('load_error', kind, name) | |
| } | |
| } catch (e) { | |
| if (e.message.includes(`No provider for "${kind}:${name}"`)) { | |
| log.error(`Cannot load "${name}", it is not registered!\n Perhaps you are missing some plugin?`) | |
| } else { | |
| log.error(`Cannot load "${name}"!\n ` + e.stack) | |
| } | |
| emitter.emit('load_error', kind, name) | |
| } | |
| pluginInstances.set(name, p, `${kind}:${name}`) | |
| return p | |
| } | |
| } | |
| createInstantiatePlugin.$inject = ['injector'] | |
| module.exports = { resolve, createInstantiatePlugin } |