I have been working a an nodejs MVC framework, which I was able to use to build a simple nodejs CMS. Here is a live demo: nodejsmvc.com.
There are a few frameworks out there already, but I wanted to have something really lightweight, so that I have flexibility to grow it the way I desire. Also, I wanted to create something similar in implementation as my JavaScript MVC framework.
Here is a example of my routing class:
var fs = require('fs'),
c = require('../../config');
// Router.
exports.get = function(req, resp){
var url = req.url.toLowerCase(),
arr = url.split('/'),
controller = 'page',
action = 'index',
p1 = '',
p2 = '',
p3 = '';
try{
// Routing.
if(arr[1] === 'hypoteky'){
var controller = 'hypoteky';
if(arr[2]){
p1 = arr[2];
action = 'detail';
}
// Default route.
} else {
if(arr[1]){
p1 = arr[1];
}
}
// Load controller.
var ctrl = require('../Controllers/' + controller);
// Load view.
fs.readFile(c.config.appPath + '/Views/' + controller + '/' + action + '.html', function (err, template) {
if(template){
view = template.toString();
}
// Load controller.
ctrl.get({
controller: controller,
action: action,
p1: p1,
p2: p2,
p3: p3
},
view,
function(content){
resp.writeHead(200, {'content-type': 'text/html'});
resp.write(content);
resp.end();
});
});
} catch(ex){
// Error page.
resp.writeHead(200, {'content-type': 'text/html'});
resp.write(ex);
resp.end();
}
};
Here is an example of a controller:
var http = require('http'),
tmpl = require('jqtpl'),
fs = require('fs'),
su = require('../lib/util.string'),
ser = require('../lib/service'),
c = require('../../config'),
Mongolian = require("mongolian");
// Db.
var server = new Mongolian(c.config.dbConnection),
db = server.db(c.config.dbName);
if(c.config.dbConnection !== 'localhost'){
db.auth(c.config.dbUserName, c.config.dbPassword);
}
var hypoteky = db.collection("hypoteky"),
zonesDb = db.collection("zones");
var zones = [];
var helpers = {
htmlString: function(html){
try {
// Search zones.
for(var i in zones) {
html = html.replace('{zone:' + zones[i].key + '}', zones[i].content);
}
return html;
} catch (ex){
return ex;
}
}
};
// HTTP content getter.
exports.get = function(params, view, callBack){
// Detail.
if(params.p1 !== ''){
fs.readFile(c.config.appPath + '/Models/hypSpiderKeys.js', function (err, data) {
var keys = JSON.parse(data.toString());
helpers.listParams = function(d){
var sb = su.string.stringBuilder();
for (var i in keys) {
if(d[keys[i].key]){
sb.append(keys[i].name);
sb.append(': ');
sb.append(d[keys[i].key]);
sb.append('
');
}
}
return sb.toString();
};
hypoteky.findOne({ url: params.p1 }, function(err, hypoteka) {
zonesDb.find().limit(50).toArray(function (err, zonesList) {
// Zone list.
zones = zonesList;
// Array to obj conversion.
var zone = {};
for(var i in zones) {
zone[zones[i].key] = zones[i].content;
}
var content = tmpl.tmpl(view, {hypoteka: hypoteka, zone: zone}, helpers);
callBack(content);
});
});
});
} else {
// Hyp list.
hypoteky.find().limit(300).toArray(function (err, hypotekaList) {
zonesDb.find().limit(50).toArray(function (err, zonesList) {
// Zone list.
zones = zonesList;
// Array to obj conversion.
var zone = {};
for(var i in zones) {
zone[zones[i].key] = zones[i].content;
}
var content = tmpl.tmpl(view, {hypoteky: hypotekaList, zone: zone}, helpers);
callBack(content);
});
//var content = tmpl.tmpl(view, {hypoteky: hypotekaList});
//callBack(content);
});
}
};
As a view engine, I use the tmpl port the nodejs.