mirror of
https://github.com/strapi/strapi.git
synced 2025-09-26 00:39:49 +00:00
Simplify and reduce codebase for loading hooks
This commit is contained in:
parent
f2f85037e4
commit
aaaec192a7
@ -6,18 +6,18 @@
|
||||
|
||||
// Node.js core.
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
// Local utilities.
|
||||
const json = require('strapi-utils').json;
|
||||
|
||||
/**
|
||||
* Expose new instance of `Configuration`
|
||||
*/
|
||||
|
||||
module.exports = strapi => {
|
||||
return new Configuration();
|
||||
module.exports = class Configuration {
|
||||
|
||||
function Configuration() {
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* Strapi default configuration
|
||||
@ -25,7 +25,7 @@ module.exports = strapi => {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
this.defaults = appPath => {
|
||||
defaults(context, appPath) {
|
||||
|
||||
// If `appPath` not specified, unfortunately, this is a fatal error,
|
||||
// since reasonable defaults cannot be assumed.
|
||||
@ -42,11 +42,11 @@ module.exports = strapi => {
|
||||
appPath: appPath,
|
||||
|
||||
// Core settings non provided by hooks.
|
||||
host: process.env.HOST || process.env.HOSTNAME || strapi.config.host || 'localhost',
|
||||
port: process.env.PORT || strapi.config.port || 1337,
|
||||
host: process.env.HOST || process.env.HOSTNAME || context.config.host || 'localhost',
|
||||
port: process.env.PORT || context.config.port || 1337,
|
||||
|
||||
// Make the environment in config match the server one.
|
||||
environment: strapi.app.env || process.env.NODE_ENV,
|
||||
environment: context.app.env || process.env.NODE_ENV,
|
||||
|
||||
// Default reload config.
|
||||
reload: {
|
||||
@ -81,9 +81,27 @@ module.exports = strapi => {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
this.load = require('./load').apply(this, [strapi]);
|
||||
load(context, cb) {
|
||||
|
||||
// Bind the context of all instance methods.
|
||||
_.bindAll(this);
|
||||
/**
|
||||
* Expose version/dependency info for the currently-running
|
||||
* Strapi on the `strapi` object (from its `package.json`).
|
||||
*/
|
||||
|
||||
const pathToThisVersionOfStrapi = path.join(__dirname, '..', '..');
|
||||
|
||||
json.getPackage(pathToThisVersionOfStrapi, (err, pkg) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
context.version = pkg.version;
|
||||
context.dependencies = pkg.dependencies;
|
||||
|
||||
// Override the previous contents of `strapi.config` with the new, validated
|
||||
// config with defaults and overrides mixed in the appropriate order.
|
||||
context.config = this.defaults(context, context.config.appPath || process.cwd());
|
||||
cb();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,67 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Node.js core.
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules.
|
||||
const async = require('async');
|
||||
|
||||
// Local utilities.
|
||||
const json = require('strapi-utils').json;
|
||||
|
||||
/**
|
||||
* Expose Configuration loader
|
||||
*
|
||||
* Load command-line overrides
|
||||
*
|
||||
* For reference, config priority is:
|
||||
* -> implicit defaults
|
||||
* -> environment variables
|
||||
* -> user config files
|
||||
* -> local config file
|
||||
* -> configOverride (in call to `strapi.start()`)
|
||||
* -> --cmdline args
|
||||
*/
|
||||
|
||||
module.exports = function (strapi) {
|
||||
return cb => {
|
||||
|
||||
// Commence with loading/validating/defaulting all the rest of the config.
|
||||
async.auto({
|
||||
|
||||
/**
|
||||
* Expose version/dependency info for the currently-running
|
||||
* Strapi on the `strapi` object (from its `package.json`).
|
||||
*/
|
||||
|
||||
versionAndDependencyInfo: cb => {
|
||||
const pathToThisVersionOfStrapi = path.join(__dirname, '..', '..');
|
||||
|
||||
json.getPackage(pathToThisVersionOfStrapi, function (err, pkg) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
strapi.version = pkg.version;
|
||||
strapi.dependencies = pkg.dependencies;
|
||||
|
||||
cb();
|
||||
});
|
||||
}
|
||||
}, err => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
// Override the previous contents of `strapi.config` with the new, validated
|
||||
// config with defaults and overrides mixed in the appropriate order.
|
||||
strapi.config = this.defaults(strapi.config.appPath || process.cwd());
|
||||
|
||||
cb();
|
||||
});
|
||||
};
|
||||
};
|
@ -13,9 +13,8 @@ const async = require('async');
|
||||
const herd = require('herd');
|
||||
|
||||
// Local dependencies.
|
||||
const Hook = require('./configuration/hooks');
|
||||
const __Configuration = require('./configuration');
|
||||
const __loadHooks = require('./private/loadHooks');
|
||||
const Configuration = require('./configuration');
|
||||
const loadHooks = require('./private/loadHooks');
|
||||
const DEFAULT_HOOKS = require('./configuration/hooks/defaultHooks');
|
||||
|
||||
/**
|
||||
@ -23,11 +22,6 @@ const DEFAULT_HOOKS = require('./configuration/hooks/defaultHooks');
|
||||
*/
|
||||
|
||||
module.exports = function (configOverride, cb) {
|
||||
const self = this;
|
||||
|
||||
const Configuration = __Configuration(this);
|
||||
const loadHooks = __loadHooks(this);
|
||||
|
||||
if (this._exiting) {
|
||||
this.log.error('Cannot load or start an application after it has already been stopped.');
|
||||
process.exit(1);
|
||||
@ -48,27 +42,38 @@ module.exports = function (configOverride, cb) {
|
||||
// Apply core defaults and hook-agnostic configuration,
|
||||
// esp. overrides including command-line options, environment variables,
|
||||
// and options that were passed in programmatically.
|
||||
config: [Configuration.load],
|
||||
config: cb => new Configuration().load(this, cb),
|
||||
// Optionally expose globals as soon as the
|
||||
// config hook is loaded.
|
||||
exposeGlobals: ['config', (result, cb) => self.exposeGlobals(cb)],
|
||||
exposeGlobals: ['config', (result, cb) => this.exposeGlobals(cb)],
|
||||
// Initialize dictionary's hooks.
|
||||
preInitializeHooks: ['exposeGlobals', (result, cb) => preInitializeHooks.apply(this, [cb])],
|
||||
// Create configurations tree (dictionary).
|
||||
dictionary: ['exposeGlobals', (result, cb) => {
|
||||
loadDictionary: ['preInitializeHooks', (result, cb) => loadHooks.apply(this, [cb])],
|
||||
// Initialize hooks left.
|
||||
initializeHooks: ['loadDictionary', (result, cb) => initializeHooks.apply(this, [cb])],
|
||||
// Load hooks into memory.
|
||||
loadHooks: ['initializeHooks', (result, cb) => loadHooks.apply(this, [cb])]
|
||||
}, (err, results) => ready__.apply(this, [cb])());
|
||||
|
||||
// Makes `app.load()` chainable.
|
||||
return this;
|
||||
|
||||
/**
|
||||
* Pre-initialize hooks by putting only dictionary hooks,
|
||||
* into the `hooks` global varialbe.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function preInitializeHooks(cb) {
|
||||
// Pre-initialize hooks for create dictionary.
|
||||
_.assign(self.hooks, _.mapValues(_.get(DEFAULT_HOOKS, 'dictionary'), (hook, hookIdentity) => {
|
||||
_.assign(this.hooks, _.mapValues(_.get(DEFAULT_HOOKS, 'dictionary'), (hook, hookIdentity) => {
|
||||
return require('./configuration/hooks/dictionary/' + hookIdentity);
|
||||
}));
|
||||
|
||||
loadHooks(self.hooks, cb);
|
||||
}],
|
||||
// Initialize hooks global variable and configurations
|
||||
initializeHooks: ['dictionary', initializeHooks],
|
||||
// Load hooks into memory.
|
||||
loadHooks: ['initializeHooks', (result, cb) => loadHooks(self.hooks, cb)]
|
||||
}, ready__(cb));
|
||||
|
||||
// Makes `app.load()` chainable.
|
||||
return self;
|
||||
cb();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiliaze hooks,
|
||||
@ -77,10 +82,9 @@ module.exports = function (configOverride, cb) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
|
||||
function initializeHooks(result, cb) {
|
||||
function initializeHooks(cb) {
|
||||
// Reset
|
||||
self.hooks = {};
|
||||
this.hooks = {};
|
||||
|
||||
const tree = {};
|
||||
|
||||
@ -92,14 +96,14 @@ module.exports = function (configOverride, cb) {
|
||||
});
|
||||
|
||||
// Extend tree with external hooks.
|
||||
_.forEach(self.externalHooks, (hook, hookIdentity) => {
|
||||
_.forEach(this.externalHooks, (hook, hookIdentity) => {
|
||||
_.set(tree, hookIdentity, hook);
|
||||
});
|
||||
|
||||
// Remove this sensitive object.
|
||||
delete strapi.externalHooks;
|
||||
delete this.externalHooks;
|
||||
|
||||
const mapper = _.clone(self.config.hooks);
|
||||
const mapper = _.clone(this.config.hooks);
|
||||
|
||||
// Map (warning: we could have some order issues).
|
||||
_.assignWith(mapper, tree, (objValue, srcValue) => {
|
||||
@ -107,15 +111,15 @@ module.exports = function (configOverride, cb) {
|
||||
});
|
||||
|
||||
// Pick hook to load.
|
||||
self.hooks = _.pickBy(mapper, value => value !== false);
|
||||
this.hooks = _.pickBy(mapper, value => value !== false);
|
||||
|
||||
// Require only necessary hooks.
|
||||
self.hooks =_.mapValues(self.hooks, (hook, hookIdentity) => {
|
||||
this.hooks =_.mapValues(this.hooks, (hook, hookIdentity) => {
|
||||
try {
|
||||
return require(_.get(tree, hookIdentity));
|
||||
} catch (err) {
|
||||
try {
|
||||
return require(path.resolve(self.config.appPath, 'node_modules', hookIdentity));
|
||||
return require(path.resolve(this.config.appPath, 'node_modules', hookIdentity));
|
||||
} catch (err) {
|
||||
cb(err);
|
||||
}
|
||||
@ -132,44 +136,44 @@ module.exports = function (configOverride, cb) {
|
||||
*/
|
||||
|
||||
function ready__(cb) {
|
||||
self.emit('hooks:builtIn:ready');
|
||||
this.emit('hooks:builtIn:ready');
|
||||
|
||||
return err => {
|
||||
if (err) {
|
||||
// Displaying errors, try to start the server through
|
||||
self.log.error(err);
|
||||
this.log.error(err);
|
||||
}
|
||||
|
||||
// Automatically define the server URL from
|
||||
// `proxy`, `ssl`, `host`, and `port` config.
|
||||
if (_.isString(self.config.proxy)) {
|
||||
self.config.url = self.config.proxy;
|
||||
if (_.isString(this.config.proxy)) {
|
||||
this.config.url = this.config.proxy;
|
||||
} else {
|
||||
if (_.isPlainObject(self.config.ssl) && self.config.ssl.disabled === false) {
|
||||
self.config.url = 'https://' + self.config.host + ':' + self.config.port;
|
||||
if (_.isPlainObject(this.config.ssl) && this.config.ssl.disabled === false) {
|
||||
this.config.url = 'https://' + this.config.host + ':' + this.config.port;
|
||||
} else {
|
||||
self.config.url = 'http://' + self.config.host + ':' + self.config.port;
|
||||
this.config.url = 'http://' + this.config.host + ':' + this.config.port;
|
||||
}
|
||||
}
|
||||
|
||||
// We can finally make the server listen on the configured port.
|
||||
// Use of the `herd` node module to herd the child processes with
|
||||
// zero downtime reloads.
|
||||
if (_.isPlainObject(self.config.reload) && !_.isEmpty(self.config.reload) && self.config.reload.workers > 0) {
|
||||
herd(self.config.name)
|
||||
if (_.isPlainObject(this.config.reload) && !_.isEmpty(this.config.reload) && this.config.reload.workers > 0) {
|
||||
herd(this.config.name)
|
||||
.close(function () {
|
||||
process.send('message');
|
||||
})
|
||||
.timeout(self.config.reload.timeout)
|
||||
.size(self.config.reload.workers)
|
||||
.timeout(this.config.reload.timeout)
|
||||
.size(this.config.reload.workers)
|
||||
.run(function () {
|
||||
self.server.listen(self.config.port);
|
||||
this.server.listen(this.config.port);
|
||||
});
|
||||
} else {
|
||||
self.server.listen(self.config.port);
|
||||
this.server.listen(this.config.port);
|
||||
}
|
||||
|
||||
cb && cb(null, self);
|
||||
cb && cb(null, this);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -18,11 +18,9 @@ const Hook = require('../configuration/hooks');
|
||||
* @api private
|
||||
*/
|
||||
|
||||
module.exports = function (strapi) {
|
||||
return (hooks, cb) => {
|
||||
|
||||
module.exports = function(cb) {
|
||||
function prepareHook(id) {
|
||||
let hookPrototype = hooks[id];
|
||||
let hookPrototype = this.hooks[id];
|
||||
|
||||
// Handle folder-defined modules (default to `./lib/index.js`)
|
||||
// Since a hook definition must be a function.
|
||||
@ -48,15 +46,15 @@ module.exports = function (strapi) {
|
||||
def.configKey = hookPrototype.configKey || def.identity;
|
||||
|
||||
// New up an actual Hook instance.
|
||||
hooks[id] = new Hook(strapi, def);
|
||||
this.hooks[id] = new Hook(this, 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) || {};
|
||||
const defaults = (_.isFunction(hook.defaults) ? hook.defaults(this.config) : hook.defaults) || {};
|
||||
|
||||
_.defaultsDeep(strapi.config, defaults);
|
||||
_.defaultsDeep(this.config, defaults);
|
||||
}
|
||||
|
||||
// Load a hook and initialize it.
|
||||
@ -65,40 +63,39 @@ module.exports = function (strapi) {
|
||||
|
||||
setTimeout(() => {
|
||||
if (timeout) {
|
||||
strapi.log.error('The hook `' + id + '` wasn\'t loaded (too long to load)!');
|
||||
this.log.error('The hook `' + id + '` wasn\'t loaded (too long to load)!');
|
||||
process.nextTick(cb);
|
||||
}
|
||||
}, strapi.config.hookTimeout || 1000);
|
||||
}, this.config.hookTimeout || 1000);
|
||||
|
||||
hooks[id].load(err => {
|
||||
this.hooks[id].load(err => {
|
||||
timeout = false;
|
||||
|
||||
if (err) {
|
||||
strapi.log.error('The hook `' + id + '` failed to load!');
|
||||
strapi.emit('hook:' + id + ':error');
|
||||
this.log.error('The hook `' + id + '` failed to load!');
|
||||
this.emit('hook:' + id + ':error');
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
strapi.emit('hook:' + id + ':loaded');
|
||||
this.emit('hook:' + id + ':loaded');
|
||||
|
||||
// Defer to next tick to allow other stuff to happen.
|
||||
process.nextTick(cb);
|
||||
});
|
||||
}
|
||||
|
||||
async.series(_.map(hooks, (hook, identity) => {
|
||||
async.series(_.map(this.hooks, (hook, identity) => {
|
||||
// Don't load disabled hook
|
||||
if (_.get(strapi.config.hooks, identity) === false) {
|
||||
if (_.get(this.config.hooks, identity) === false) {
|
||||
return cb => {
|
||||
cb();
|
||||
};
|
||||
}
|
||||
|
||||
return cb => {
|
||||
prepareHook(identity);
|
||||
applyDefaults(hook);
|
||||
loadHook(identity, cb);
|
||||
prepareHook.apply(this, [identity]);
|
||||
applyDefaults.apply(this, [hook]);
|
||||
loadHook.apply(this, [identity, cb]);
|
||||
}
|
||||
}), err => cb(err));
|
||||
};
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user