compound
Version:
CompoundJS - MVC framework for NodeJS
261 lines (229 loc) • 7.48 kB
JavaScript
var Compound = require('../compound');
var util = require('util');
var http = require('http');
var https = require('https');
var fs = require('fs');
var path = require('path');
function CompoundServer(app, root, opts) {
Compound.call(this, app, root);
if (app) {
if (opts && opts.key && opts.cert) {
this.server = https.createServer(opts, app);
} else {
this.server = http.createServer(app);
}
app.listen = function() {
app.emit('before listening', this.server);
this.server.listen.apply(this.server, arguments);
}.bind(this);
app.use(function compound(req, res, next) {
req.locals = req.locals || {};
app.compound.emit('request', req, res);
next();
});
}
this.__defineGetter__('rootModule', function() {
return module.parent;
});
this.logger = require('./logger');
this.generators = require('./generators');
this.installer = require('./installer');
this.structure.tools = this.tools = require('./tools');
this.extensions = require('./extensions');
this.middleware = require('./middleware');
this.loadStructure = require('./structure')(this);
this.__defineGetter__('version', function() {
return require('../../package').version;
});
}
util.inherits(CompoundServer, Compound);
CompoundServer.prototype.init = function initCompoundServer(root) {
var compound = this;
envInfo(this);
compound.logger.init(compound);
Compound.prototype.init.call(compound, root);
if (compound.app) {
if (compound.app.enabled('merge javascripts')) {
var jsDir = compound.app.get('jsDirectory');
if (jsDir) {
ensureDirClean(compound.app.root + '/public' +
jsDir, 'cache');
}
}
if (compound.app.enabled('merge stylesheets')) {
var cssDir = compound.app.get('cssDirectory');
if (cssDir) {
ensureDirClean(compound.app.root + '/public' +
cssDir, 'cache');
}
}
}
};
/**
* Put middleware inside stack before anchor.
*
* @param {String} anchor - name of anchor middleware.
* @param {Function} middleware - middleware.
*
* @return {Boolean} - is anchor middleware was found.
*/
CompoundServer.prototype.injectMiddlewareBefore = function(anchor, route, middleware) {
var mod = this.app, anchorPosition;
if (!mod) {
return;
}
if (mod.lazyrouter) {
console.warn('Deprecated compound.injectMiddlewareBefore');
return mod.use(route, middleware);
}
mod.stack.forEach(function (r, i) {
if (r.handle === anchor || r.handle.name === anchor) {
anchorPosition = i;
}
});
this.injectMiddlewareAt(anchorPosition, route, middleware);
return 'undefined' !== typeof anchorPosition;
};
/**
* Put middleware inside stack after anchor.
*
* @param {Function,String} anchor - middleware or name of anchor middleware.
* @param {Function} middleware - middleware.
*
* @return {Boolean} - is anchor middleware was found.
*/
CompoundServer.prototype.injectMiddlewareAfter = function(anchor, route, middleware) {
var mod = this.app, anchorPosition;
if (!mod) {
return;
}
if (mod.lazyrouter) {
console.warn('Deprecated compound.injectMiddlewareAfter');
return mod.use(route, middleware);
}
mod.stack.forEach(function (r, i) {
if (r.handle === anchor || r.handle.name === anchor) {
anchorPosition = i;
}
});
this.injectMiddlewareAt(anchorPosition + 1, route, middleware);
return 'undefined' !== typeof anchorPosition;
};
CompoundServer.prototype.injectMiddlewareAt = function(position, route, middleware) {
if (typeof route === 'function') {
middleware = route;
route = '';
}
var mod = this.app;
if (!mod) {
return;
}
var stack = mod.stack
if (mod.lazyrouter) {
console.warn('Deprecated compound.injectMiddlewareAt');
return mod.use(route, middleware);
}
if (position <= 0) {
stack.unshift({route: route, handle: middleware});
} else if (position && position <= stack.length) {
stack.splice(position, 0, {route: route, handle: middleware});
} else {
mod.use(middleware);
}
};
/**
* Create http server object. Automatically hook up SSL keys stored in
* app.root/config/tsl.{cert|key}
*
* @param {Object} options - example:
* {root: __dirname, any other options for express}.
* @return {Function} express server.
*/
exports.createServer = function(options) {
options = options || {};
if (typeof options === 'string') {
options = {root: options};
}
var root = options.root || process.cwd();
delete options.root;
var express = require('express');
var app = express(options);
new CompoundServer(app, root, options);
return app;
};
exports.controllers = require('./controllers');
exports.Compound = CompoundServer;
/**
* Setup route /compound/environment.json to return information about environment
*/
function envInfo(rw) {
rw.on('after configure', defineEnvInfoRoutes.bind(rw));
}
function defineEnvInfoRoutes() {
var rw = this;
var jugglingdbVersion, npmVersion, viewEngineVersion;
if (!rw.app) {
return;
}
rw.app.get('/compound/environment.json', function(req, res) {
if (rw.app.disabled('env info')) {
return res.send({forbidden: true});
}
try {
jugglingdbVersion = require('jugglingdb').version;
} catch (e) {
jugglingdbVersion = 'not installed';
}
try {
npmVersion = require('npm').version;
} catch (e) {}
try {
viewEngineVersion = require(rw.app.root + '/node_modules/' + rw.app.set('view engine')).version;
} catch (e) {
viewEngineVersion = 'not installed';
}
res.send({
settings: rw.app.settings,
versions: {
core: process.versions,
npm: npmVersion,
compound: rw.version,
jugglingdb: jugglingdbVersion,
templating: {
name: rw.app.set('view engine'),
version: viewEngineVersion
}
},
application: {
root: rw.app.root,
database: require(rw.app.root + '/config/database')[rw.app.set('env')].driver,
middleware: rw.app.stack.map(function(m) {
return m.handle.name;
})
},
env: process.env
});
});
}
/**
* Cleanup or create dir
*
* @param {String} dir - path to dir to create.
* @param {String} prefix - only remove files started with that prefix.
*/
function ensureDirClean(dir, prefix) {
fs.exists(dir, function(exists) {
if (exists) {
fs.readdir(dir, function(err, files) {
files.filter(function(file) {
return file.indexOf(prefix + '_') === 0;
}).map(function(file) {
return path.join(dir, file);
}).forEach(fs.unlink);
});
} else {
fs.mkdir(dir, 0755, function() {
});
}
});
}