galleon
Version:
A badass SMTP mail server built on Node to make your life simpler.
115 lines (101 loc) • 3.75 kB
JavaScript
var shell = require('shelljs');
var _ = require('lodash');
var async = require('async');
var herb = require('herb');
var colors = require('colors');
var configFile = require('./configFile');
var Modulator = function () {
this.env = configFile;
this.modules = this.env.getModulesSync();
this.container = {};
};
Modulator.prototype._getModules = function () {
this.modules = this.env.getModulesSync();
};
Modulator.prototype._add = function (MODULE) {
var m = require(MODULE);
this.env.addModules([{
reference: MODULE,
name: m.name,
extends: m.extends,
config: m.defaults
}]);
};
Modulator.prototype.load = function (modules) {
var context = this;
// Modules are likely required to be loaded on start thus will be loaded Synchronously
_.each(modules || context.modules, function (MODULE) {
// Fill context.modules according to 'extends' attribute
// Assign array if key is undefined
if (!context.container[MODULE.extends]) context.container[MODULE.extends] = {};
// Push current Module to the respective key
context.container[MODULE.extends][MODULE.reference] = MODULE;
});
return context.container;
};
Modulator.prototype.launch = function () {
var context = this;
var args = _.toArray(arguments);
var cat = args.shift();
var callback = args.pop();
var functions = [];
if ((!context.container) || (!_.isPlainObject(context.container)) || (!context.container[cat])) return callback();
// Populate functions
_.each(context.container[cat], function (MODULE) {
functions.push(function (callback) {
/* Slows down module execution but prevents unintended crashes */
// Prevents a bad module from corrupting the entire eco-system
try {
context.container[cat][MODULE.reference].__gcopy = require(MODULE.reference);
context.container[cat][MODULE.reference].__gcopy.exec.apply(MODULE, args);
} catch (error) {
callback(error);
}
});
});
// Watch for config changes
configFile.watch(function () {
if (!context.container) return;
context._getModules();
_.each(context.container[cat], function (MODULE, REF) {
try {
if (!_.isEqual(_.findWhere(context.modules, { reference: REF }).config, MODULE.config)) {
if (typeof MODULE.__gcopy.update === 'function') { MODULE.__gcopy.update(_.findWhere(context.modules, { reference: REF }).config); }
}
} catch (e) { }
});
context._getModules();
});
// Ignore if no modules are registered for the current task
if (functions.length <= 0) return callback();
async.series(functions, callback);
};
Modulator.prototype.install = function (moduleName) {
var context = this;
moduleName = moduleName.toLowerCase();
moduleName = (moduleName.substring(0, 8) !== 'galleon-') ? 'galleon-' + moduleName : moduleName;
shell.exec('npm install -g ' + moduleName, function (code, output) {
if (code === 0) {
context._add(moduleName);
herb.log(moduleName.toUpperCase().magenta, "SUCCESSFULLY INSTALLED!".green);
herb.warn("Changes will only take affect after restart!");
} else {
herb.log("INSTALLATION FAILED!".red, "\nCODE:", code);
}
});
};
Modulator.prototype.update = function (name, config) {
var context = this;
var MatchFound = false;
// Modules are likely required to be loaded on start thus will be loaded Synchronously
_.each(this.modules, function (MODULE) {
// If Current Module Matches name
if ((MODULE.name.toLowerCase() === name) || (MODULE.reference.toLowerCase() === name)) {
// Update Config
context.env.updateModuleConfig(MODULE, config);
MatchFound = true;
}
});
return MatchFound;
};
module.exports = Modulator;