2015-10-01 00:30:16 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Module dependencies
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Public node modules.
|
|
|
|
const _ = require('lodash');
|
|
|
|
const async = require('async');
|
2015-11-05 14:25:36 +01:00
|
|
|
const cluster = require('cluster');
|
2015-10-01 00:30:16 +02:00
|
|
|
|
|
|
|
// Local dependencies.
|
|
|
|
const __hooks = require('../configuration/hooks');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolve the hook definitions and then finish loading them
|
|
|
|
*
|
|
|
|
* @api private
|
|
|
|
*/
|
|
|
|
|
|
|
|
module.exports = function (strapi) {
|
|
|
|
const Hook = __hooks(strapi);
|
|
|
|
|
|
|
|
return function initializeHooks(hooks, cb) {
|
|
|
|
function prepareHook(id) {
|
|
|
|
let hookPrototype = hooks[id];
|
|
|
|
|
|
|
|
// Allow disabling of hooks by setting them to `false`.
|
|
|
|
if (strapi.config.hooks[hookPrototype] === false) {
|
|
|
|
delete hooks[id];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-11-05 14:25:36 +01:00
|
|
|
// Do not load the `studio` hook if the
|
|
|
|
// cluster is not the master.
|
|
|
|
if (!cluster.isMaster) {
|
|
|
|
delete hooks.studio;
|
|
|
|
}
|
|
|
|
|
2015-12-02 14:57:00 +01:00
|
|
|
// Remove undesired hooks when this is a `dry` application.
|
|
|
|
if (strapi.config.dry) {
|
|
|
|
delete hooks.blueprints;
|
|
|
|
delete hooks.dashboard;
|
|
|
|
delete hooks.grant;
|
|
|
|
delete hooks.studio;
|
|
|
|
delete hooks.waterline;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle folder-defined modules (default to `./lib/index.js`)
|
2015-10-01 00:30:16 +02:00
|
|
|
// Since a hook definition must be a function.
|
|
|
|
if (_.isObject(hookPrototype) && !_.isArray(hookPrototype) && !_.isFunction(hookPrototype)) {
|
|
|
|
hookPrototype = hookPrototype.index;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_.isFunction(hookPrototype)) {
|
|
|
|
strapi.log.error('Malformed (`' + id + '`) hook!');
|
|
|
|
strapi.log.error('Hooks should be a function with one argument (`strapi`)');
|
|
|
|
strapi.stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantiate the hook.
|
|
|
|
const def = hookPrototype(strapi);
|
|
|
|
|
|
|
|
// Mix in an `identity` property to hook definition.
|
|
|
|
def.identity = id.toLowerCase();
|
|
|
|
|
|
|
|
// If a config key was defined for this hook when it was loaded
|
|
|
|
// (probably because a user is overridding the default config key),
|
|
|
|
// set it on the hook definition.
|
|
|
|
def.configKey = hookPrototype.configKey || def.identity;
|
|
|
|
|
|
|
|
// New up an actual Hook instance.
|
|
|
|
hooks[id] = new Hook(def);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to apply a hook's `defaults` object or function.
|
|
|
|
function applyDefaults(hook) {
|
|
|
|
|
|
|
|
// Get the hook defaults.
|
|
|
|
const defaults = (_.isFunction(hook.defaults) ? hook.defaults(strapi.config) : hook.defaults) || {};
|
|
|
|
_.defaults(strapi.config, defaults);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load a hook and initialize it.
|
|
|
|
function loadHook(id, cb) {
|
|
|
|
const timeoutInterval = 5000;
|
|
|
|
let hookTimeout;
|
|
|
|
|
|
|
|
hookTimeout = setTimeout(function tooLong() {
|
|
|
|
const hooksTookTooLongErr = 'The hook `' + id + '` is taking too long to load.';
|
|
|
|
const err = new Error(hooksTookTooLongErr);
|
|
|
|
err.code = 'E_HOOK_TIMEOUT';
|
|
|
|
cb(err);
|
|
|
|
}, timeoutInterval);
|
|
|
|
|
|
|
|
hooks[id].load(function (err) {
|
|
|
|
clearTimeout(hookTimeout);
|
|
|
|
if (err) {
|
2015-11-02 15:56:56 +01:00
|
|
|
strapi.log.error('The hook `' + id + '` failed to load!');
|
2015-10-01 00:30:16 +02:00
|
|
|
strapi.emit('hook:' + id + ':error');
|
|
|
|
return cb(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
strapi.emit('hook:' + id + ':loaded');
|
|
|
|
|
|
|
|
// Defer to next tick to allow other stuff to happen.
|
|
|
|
process.nextTick(cb);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async.series({
|
|
|
|
|
|
|
|
// Load the user config dictionary.
|
|
|
|
_config: function loadConfigHook(cb) {
|
|
|
|
if (!hooks._config) {
|
|
|
|
return cb();
|
|
|
|
}
|
|
|
|
prepareHook('_config');
|
|
|
|
applyDefaults(hooks._config);
|
|
|
|
loadHook('_config', cb);
|
|
|
|
},
|
|
|
|
|
|
|
|
// Load the user APIs dictionary.
|
|
|
|
_api: function loadApiHook(cb) {
|
|
|
|
if (!hooks._api) {
|
|
|
|
return cb();
|
|
|
|
}
|
|
|
|
prepareHook('_api');
|
|
|
|
applyDefaults(hooks._api);
|
|
|
|
loadHook('_api', cb);
|
|
|
|
},
|
|
|
|
|
2015-11-13 17:45:47 +01:00
|
|
|
// Load the studio hook.
|
|
|
|
studio: function loadStudioHook(cb) {
|
|
|
|
if (!hooks.studio) {
|
|
|
|
return cb();
|
|
|
|
}
|
|
|
|
prepareHook('studio');
|
|
|
|
applyDefaults(hooks.studio);
|
|
|
|
loadHook('studio', cb);
|
|
|
|
},
|
|
|
|
|
2015-11-18 18:29:44 +01:00
|
|
|
// Load the dashboard hook.
|
|
|
|
dashboard: function loadRouterHook(cb) {
|
|
|
|
if (!hooks.dashboard) {
|
2015-11-13 22:01:51 +01:00
|
|
|
return cb();
|
|
|
|
}
|
2015-11-18 18:29:44 +01:00
|
|
|
prepareHook('dashboard');
|
|
|
|
applyDefaults(hooks.dashboard);
|
|
|
|
loadHook('dashboard', cb);
|
2015-11-13 22:01:51 +01:00
|
|
|
},
|
|
|
|
|
2015-10-01 00:30:16 +02:00
|
|
|
// Prepare all other hooks.
|
|
|
|
prepare: function prepareHooks(cb) {
|
2015-11-18 18:29:44 +01:00
|
|
|
async.each(_.without(_.keys(hooks), '_config', '_api', 'studio', 'dashboard', 'router'), function (id, cb) {
|
2015-10-01 00:30:16 +02:00
|
|
|
prepareHook(id);
|
|
|
|
process.nextTick(cb);
|
|
|
|
}, cb);
|
|
|
|
},
|
|
|
|
|
|
|
|
// Apply the default config for all other hooks.
|
|
|
|
defaults: function defaultConfigHooks(cb) {
|
2015-11-18 18:29:44 +01:00
|
|
|
async.each(_.without(_.keys(hooks), '_config', '_api', 'studio', 'dashboard', 'router'), function (id, cb) {
|
2015-10-01 00:30:16 +02:00
|
|
|
const hook = hooks[id];
|
|
|
|
applyDefaults(hook);
|
|
|
|
process.nextTick(cb);
|
|
|
|
}, cb);
|
|
|
|
},
|
|
|
|
|
|
|
|
// Load all other hooks.
|
|
|
|
load: function loadOtherHooks(cb) {
|
2015-11-18 18:29:44 +01:00
|
|
|
async.each(_.without(_.keys(hooks), '_config', '_api', 'studio', 'dashboard', 'router'), function (id, cb) {
|
2015-10-01 00:30:16 +02:00
|
|
|
loadHook(id, cb);
|
|
|
|
}, cb);
|
2015-11-18 18:29:44 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
// Load the router hook.
|
|
|
|
router: function loadRouterHook(cb) {
|
|
|
|
if (!hooks.router) {
|
|
|
|
return cb();
|
|
|
|
}
|
|
|
|
prepareHook('router');
|
|
|
|
applyDefaults(hooks.router);
|
|
|
|
loadHook('router', cb);
|
2015-10-01 00:30:16 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
function hooksReady(err) {
|
|
|
|
return cb(err);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
};
|