wns-mvc-package
Version:
MVC package/bundle for WNS Middleware
287 lines (245 loc) • 7.57 kB
JavaScript
/**
* @WNS - The NodeJS Middleware and Framework
*
* @copyright: Copyright © 2012- YEPT ®
* @page: http://wns.yept.net/
* @docs: http://wns.yept.net/docs/
* @license: http://wns.yept.net/license/
*/
/**
* No description yet.
*
* @author Pedro Nasser
*/
// Exports
module.exports = {
/**
* Class dependencies
*/
extend: ['wnComponent'],
/**
* NPM dependencies
*/
dependencies: ['url'],
/**
* Private
*/
private: {
_server: null,
_controllers: [],
_partials: {},
_config: {
defaultController:"site",
errorPage: "site/error",
templateEngine: "Dust",
path: {
controllers: "controllers/",
views: "views/",
partials: "partials/"
},
}
},
/**
* Public Variables
*/
public: {
/**
* @var object events to be preloaded.
*/
defaultEvents: {
'open': {},
'handle': {},
'error': {},
'send': {}
}
},
/**
* Methods
*/
methods: {
/**
* Initializer
*/
init: function ()
{
this.app = this.getParent();
this.attachEvents(this.app);
this.prepareEngines(this.app);
},
/**
* Attach events to the application
*/
attachEvents: function (app)
{
self.debug('Attaching events to the parent application',0);
if (!_(app).isObject())
return false;
if (!app.getEvent('readyRequest'))
{
self.warn('Failed to attach wnControllerServer. Requires to install `http` package on the parent server.');
self.warn('Learn how to easy install `http` package: http://github.com/pedronasser/wns-http-package');
return false;
}
app.addListener('readyRequest',function (e,req,resp) {
req.parsedUrl=url.parse(req.url,true);
req.route = self.app.getComponent('urlManager').parseRequest(req) || { translation: req.url, params: {}, template: '' };
req.template = self.route ? self.route.template : '';
self.next=e.next;
self.processRequest(req,resp);
});
},
/**
* Prepare engines.
*/
prepareEngines: function (app)
{
var engineName = this.getConfig('templateEngine') || 'Dust';
var engineClass = 'wn'+engineName+'Template';
if (!app.c[engineClass])
{
self.warn('Failed to attach '+engineClass+'. Requires to install `template` package on the application.');
self.warn('Learn how to easy install `template` package: http://github.com/pedronasser/wns-template-package');
return false;
}
app.template = app.createClass(engineClass,{});
app.template.parent = function () { return app; };
app.html = app.createClass('wnHtml',{});
app.html.setParent(app);
app.html.encoder = app.createClass('wnHtmlEncoder',{});
},
/**
* Process the request
* @param {ServerRequest} req
* @param {ServerResponse} resp
*/
processRequest: function (req,resp)
{
if (req.template.split("/").length>1 || req.template == '')
{
self.debug('Requesting for controller/action.',5);
req.html = self.app.html;
req.html.encoder = self.app.html.encoder;
_.merge(req.query.GET, req.parsedUrl.query);
_.merge(req.query.GET, req.route.params);
resp.setHeader('Content-Type','text/html');
var _p=(req.route.translation).split('/');
var _plen = _p.length;
var _controller=_plen>0&&_p[1]!=''?_p[1]:undefined;
var _action=_plen>1&&_p[2]!=''?_p[2]:undefined;
var ctrlName = (_controller !== undefined && _controller !== 'undefined') ? _controller : this.getConfig('defaultController');
var controller=this.getController(ctrlName,req,resp);
if (!controller)
{
self.errorHandler(req,resp,404,'Controller not found');
return;
}
self.e.handle(controller);
req.e = { error: controller.e.error };
resp.e = { error: controller.e.error };
controller.addListener('error',function (e,code,msg) {
self.errorHandler(req,resp,code,msg);
});
_action=req.action=(!_action?controller.defaultAction:_action);
if (controller.resolveAction(_action)==false)
{
self.errorHandler(req,resp,404,'Action not found');
}
}
},
/**
* Error handling
*/
errorHandler: function (req,resp,code,msg) {
self.debug(code+': '+msg,1);
if (code == 404 && self.getConfig('errorPage')!=undefined)
{
self.debug('Redirecting to ERROR PAGE...',2);
req.route.translation = '/'+self.getConfig('errorPage');
req.error = 'Not found';
req.code = 404;
self.processRequest(req,resp);
}
self.next();
},
/**
* Flush all loaded application's controllers cache
*/
flushControllers: function () {
for (c in _controllers)
this.c['wn'+(c.substr(0,1).toUpperCase()+c.substr(1))+'Controller']=undefined;
this.debug('All controllers has been flushed.',1);
},
/**
* Flush an application's controller cache
* @param string $c controller's name
*/
flushController: function (c) {
this.c['wn'+(c.substr(0,1).toUpperCase()+c.substr(1))+'Controller']=undefined;
this.debug('Controller ´'+c+'´ has been flushed.',1);
},
/**
* Get a new or cached instance from a controller.
* @param string $id controller's id
* @return wnController
*/
getController: function (id,req,resp)
{
id = id.toLowerCase();
var controllerName = 'wn'+(id.substr(0,1).toUpperCase()+id.substr(1))+'Controller';
var classProto = this.app.c[controllerName];
if (_.isUndefined(classProto)) {
self.debug('Looking up for the controller: '+id,1);
var controllerFile = this.getConfig('path').controllers+id+'.js';
var builder = this.app.getComponent('classBuilder');
if (fs.existsSync(this.app.modulePath+controllerFile))
{
builder.addSource(controllerName,this.app.modulePath+controllerFile);
builder.classes[controllerName]=builder.buildClass(controllerName);
if (!builder.classes[controllerName])
this.app.e.exception(new Error('Could not build the controller class.'));
this.app.c[controllerName]=builder.classes[controllerName];
_controllers[id]=this.app.c[controllerName];
classProto = this.app.c[controllerName];
self.registerPartials(id);
self.compilePartials(id);
} else
return false;
}
var config = { controllerName: id, verbosity: _verbosity, debug: _debug, path: this.getConfig('path') };
controller = new classProto(config,this.app.c,this.app,req,resp);
return controller;
},
/**
* Register all partials from a controller
* @param string $controllerName
*/
registerPartials: function (controllerName)
{
var partialPath = this.app.modulePath+this.getConfig('path').views+controllerName+'/'+this.getConfig('path').partials;
if (_.isUndefined(this.getConfig('path').partials) || !fs.existsSync(partialPath))
return false;
_partials[controllerName] = {};
var files = fs.readdirSync(partialPath);
if (files)
{
for (f in files)
{
var name = files[f].split('.')[0];
_partials[controllerName][name]=partialPath+files[f];
}
}
},
/**
* Compiled all partials
* @param string $controllerName
*/
compilePartials: function (controllerName)
{
var partials = _partials[controllerName];
for (p in partials)
{
self.app.template.renderPartial(fs.readFileSync(partials[p]).toString('utf8'),controllerName+'-'+p);
}
},
}
};