UNPKG

@midgar/midgar

Version:
131 lines (112 loc) 3.42 kB
/** * @typedef {Object} PluginDef * @property {string} name Plugin name * @property {constructor} plugin Plugin class * @property {Array<string>} dependencies Dependencies plugin names */ /** * PluginMaganger class * Manage plugins */ class PluginManager { /** * @param {App} app App instance */ constructor (app) { /** * App instance * @type {App} */ this.app = app this._pluginDefs = {} /** * Plugins instance Dictionary by plugin name * @type {object} */ this.plugins = {} } /** * Add a plugin définition */ async addPlugin (plugin) { this._pluginDefs[plugin.name] = plugin } /** * Create plugin instances * * @return {Promise<Object>} */ async createPluginInstances () { for (const name in this._pluginDefs) { if (this.plugins[name] === undefined) { await this._createPluginInstance(name) } } } /** * Return a plugin instance by name * * @param {string} name Plugin name * @return {Plugin} */ getPlugin (name) { if (this.plugins[name] === undefined) throw new Error(`Invalid plugin name: ${name} !`) return this.plugins[name] } /** * This method exist only for been mock durting test * * @param {String} name module name * * @return {module} * @private */ _require (name) { return require(name) } /** * Create plugin instance and init plugin * * @param {String} name Plugin name * @param {String} pluginPath Plugin path * * @return {Promise<Plugin>} * @private */ async _createPluginInstance (name, parents = []) { if (this._pluginDefs[name] === undefined) { let pluginDef try { pluginDef = this._require(name) } catch (error) { this.app.debug(error) throw new Error(`Cannot find npm package for plugin ${name} !`) } this._pluginDefs[name] = pluginDef } const pluginDef = this._pluginDefs[name] let PluginClass = pluginDef.plugin const args = [this.app] if (pluginDef.dependencies) { parents.push(name) for (const dependency of pluginDef.dependencies) { if (parents.indexOf(dependency) !== -1) { throw new Error( `PM: Circular dependency in plugin ${name}, ${dependency} already depend on ${name} (${parents.join('->')})!` ) } if (this.plugins[dependency] === undefined) { await this._createPluginInstance(dependency, [...parents]) } args.push(this.plugins[dependency]) } } this.app.debug(`PM: Create plugin instance ${name}.`) // Create plugin intance const plugin = new PluginClass(...args) this.plugins[name] = plugin await plugin.init() await this.app.emit(name + ':after-create-instance') } } module.exports = PluginManager