From 5865c3015504e49812e10b1b345c4682d1af3d9c Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 11 Jan 2018 14:20:51 -0700 Subject: [PATCH] added a plugin context --- plugins.js | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/plugins.js b/plugins.js index 577289b25..0f0b4ab3d 100644 --- a/plugins.js +++ b/plugins.js @@ -4,6 +4,8 @@ const resolve = require('resolve'); const debug = require('debug')('talk:plugins'); const Joi = require('joi'); const amp = require('app-module-path'); +const pkg = require('./package.json'); +const config = require('./config'); const PLUGINS_JSON = process.env.TALK_PLUGINS_JSON; @@ -63,6 +65,16 @@ const hookSchemas = { }), }; +/** + * PluginContext provides server context for the global application. + */ +class PluginContext { + constructor() { + this.pkg = pkg; + this.config = config; + } +} + /** * isInternal checks to see if a given plugin is internal, and returns true * if it is. @@ -168,7 +180,8 @@ Object.keys(plugins).forEach((type) => itteratePlugins(plugins[type]).forEach((p * Stores a reference to a section for a section of Plugins. */ class PluginSection { - constructor(plugins) { + constructor(context, plugins) { + this.context = context; this.required = false; this.plugins = itteratePlugins(plugins); } @@ -195,43 +208,48 @@ class PluginSection { } /** - * This itterates over the section to provide all plugin hooks that are + * This iterates over the section to provide all plugin hooks that are * available. */ - hook(hook) { + hook(hookName) { // Load the plugin source if we haven't already. this.require(); return this.plugins - .filter(({module}) => hook in module) - .filter((plugin) => { + .filter(({module}) => hookName in module) + .map((plugin) => { + + // Optionally bind the plugin context to a function if it's one. + const hook = typeof plugin.module[hookName] === 'function' ? + plugin.module[hookName].bind(this.context) : + plugin.module[hookName]; // Validate the hook. - if (hook in hookSchemas) { - Joi.assert(plugin.module[hook], hookSchemas[hook], `Plugin '${plugin.name}' failed validation for the '${hook}' hook`); + if (hookName in hookSchemas) { + Joi.assert(hook, hookSchemas[hookName], `Plugin '${plugin.name}' failed validation for the '${hookName}' hook`); } - return true; - }) - .map((plugin) => ({ - plugin, - [hook]: plugin.module[hook] - })); + return { + plugin, + [hookName]: hook, + }; + }); } } -const NullPluginSection = new PluginSection([]); +const NullPluginSection = new PluginSection({}, []); /** * Stores references to all the plugins available on the application. */ class PluginManager { constructor(plugins) { + this.context = new PluginContext(); this.sections = {}; for (let section in plugins) { - this.sections[section] = new PluginSection(plugins[section]); + this.sections[section] = new PluginSection(this.context, plugins[section]); } }