diff --git a/graph/connectors.js b/graph/connectors.js index c0ae9606e..7b9ec6699 100644 --- a/graph/connectors.js +++ b/graph/connectors.js @@ -4,6 +4,12 @@ const merge = require('lodash/merge'); // Errors. const errors = require('../errors'); +// Graph +const subscriptions = require('./subscriptions'); +const resolvers = require('./resolvers'); +const mutators = require('./mutators'); +const loaders = require('./loaders'); + // Models. const Action = require('../models/action'); const Asset = require('../models/asset'); @@ -39,8 +45,8 @@ const Tokens = require('../services/tokens'); const Users = require('../services/users'); const Wordlist = require('../services/wordlist'); -// Connector. -const connectors = { +// Connectors. +const defaultConnectors = { errors, models: { Action, @@ -77,14 +83,22 @@ const connectors = { Users, Wordlist, }, + graph: { + subscriptions, + resolvers, + mutators, + loaders, + }, }; -module.exports = Plugins.get('server', 'connectors').reduce( +const connectors = Plugins.get('server', 'connectors').reduce( (defaultConnectors, { plugin, connectors: pluginConnectors }) => { debug(`adding plugin '${plugin.name}'`); // Merge in the plugin connectors. return merge(defaultConnectors, pluginConnectors); }, - connectors + defaultConnectors ); + +module.exports = connectors; diff --git a/graph/context.js b/graph/context.js index f45e45da1..182ed60ad 100644 --- a/graph/context.js +++ b/graph/context.js @@ -87,4 +87,15 @@ class Context { } } +// Attach the Context to the connectors. +connectors.graph.Context = Context; + +// Connect the connect based plugings after the server has started. +plugins.defer('server', 'connect', ({ plugin, connect }) => { + debug(`connecting plugin to connectors '${plugin.name}'`); + + // Pass the connectors down to the connect plugin. + connect(connectors); +}); + module.exports = Context; diff --git a/graph/subscriptions/index.js b/graph/subscriptions/index.js index 5ade76feb..40c1c4437 100644 --- a/graph/subscriptions/index.js +++ b/graph/subscriptions/index.js @@ -2,6 +2,7 @@ const { SubscriptionManager } = require('graphql-subscriptions'); const { SubscriptionServer } = require('subscriptions-transport-ws'); const debug = require('debug')('talk:graph:subscriptions'); +const { getBroker } = require('./broker'); const { getPubsub } = require('./pubsub'); const schema = require('../schema'); const Context = require('../context'); @@ -115,4 +116,6 @@ const createSubscriptionManager = server => module.exports = { createSubscriptionManager, + getBroker, + getPubsub, }; diff --git a/plugins.js b/plugins.js index 8ffe89e3a..6f65fc9a1 100644 --- a/plugins.js +++ b/plugins.js @@ -73,6 +73,7 @@ const hookSchemas = { onConnect: Joi.func(), onDisconnect: Joi.func(), }), + connect: Joi.func().maxArity(1), }; /** @@ -293,14 +294,42 @@ class PluginManager { plugins[section] ); } + + this.deferredHooks = []; + this.ranDeferredHooks = false; } /** * Utility function which combines the Plugins.section and PluginSection.hook * calls. */ - get(section, hook) { - return this.section(section).hook(hook); + get(sectionName, hookName) { + return this.section(sectionName).hook(hookName); + } + + /** + * Utility function which combines the Plugins.section and PluginSection.hook + * calls and runs them when the `runDeferred` is called. + */ + defer(sectionName, hookName, callback) { + const plugins = this.section(sectionName).hook(hookName); + + // If we've already ran the callbacks, then we should run it immediately. + if (this.ranDeferredHooks) { + plugins.forEach(callback); + } else { + this.deferredHooks.push({ plugins, callback }); + } + } + + /** + * Calls all deferred hooks. + */ + runDeferred() { + this.deferredHooks.forEach(({ plugins, callback }) => + plugins.forEach(callback) + ); + this.ranDeferredHooks = true; } /** diff --git a/serve.js b/serve.js index 499df6cfe..49ddc9f3b 100644 --- a/serve.js +++ b/serve.js @@ -6,6 +6,7 @@ const scraper = require('./services/scraper'); const mailer = require('./services/mailer'); const MigrationService = require('./services/migration'); const SetupService = require('./services/setup'); +const PluginsService = require('./services/plugins'); const kue = require('./services/kue'); const mongoose = require('./services/mongoose'); const cache = require('./services/cache'); @@ -79,6 +80,9 @@ async function onListening() { * Start the app. */ async function serve({ jobs = false, websockets = false } = {}) { + // Run the deffered plugins. + PluginsService.runDeferred(); + // Start the cache instance. await cache.init();