Skip to content

Instantly share code, notes, and snippets.

@adrienj
Forked from AMSTKO/(controller)default.js
Created June 27, 2011 22:52
Show Gist options
  • Save adrienj/1050055 to your computer and use it in GitHub Desktop.
Save adrienj/1050055 to your computer and use it in GitHub Desktop.
ToyFW.js
/*
* default
*/
module.exports = function (req, res, met) {
this.mvc.langFile('default');
var src = this.mvc.template('index', {'user':['pingouchoux']});
return src;
};
/*
* fr
*/
module.exports = {
'welcome': 'Bienvenue {user} ! :)'
}
<%=lang('welcome', {'user':user})%><br />
<%=lang('fucklol312', {'user':user})%>

ToyFW.js

ToyFW.js is a MVC framework for node.js that is currently in development. ToyFW uses Express to create servers and has a built-in dispatcher to route controllers. The model part is not yet implemented.

Features

  • Multidomain
  • MVC
  • Multi language
  • Highly configurable

Getting Started

server.js :

require('./toyfw.js')({
    domains: {
        '*mysite.com': {}
    },
    port: 80
    ip: '123.45.67.89'
});

And then start the server :

$node server.js

You can even do shorter :

require('./toyfw.js')('*mysite.com');
// or redirecting multiple domains to one site :
require('./toyfw.js')(['*mysite.com', '*mysites.com']);

As no configuration is passed, it listens on localhost:80. And by default, the local directory is where should be controller/ and view/.

Usage

Folders

./
    server.js
    controller/
        default.js
        contact.js
        errors.js
    lang/
        en/
            name.lang.js
        fr/
            name.lang.js
    view/
        index.html
        contact.html
    public/
        img/
        css/
        js/

Domains

The domains section accepts several types of data.

    domains: '*mysite.com'

or

    domains: ['*mysite.com', '*test.com']

or

    domains: {
        '*mysite.com': {},
        '*test.com': {}
    }

or

    domains: {
        '*mysite.com': {
            srv: function(app, express) {
                app.use(app.router);
                app.use(express.logger());
                app.use(express.bodyParser());
            }
        },
        '*test.com': {}
    }

or

    domains: {
        '*mysite.com': {
            srv: function(app, express, cfg) {
                app.use(express.cookieParser());
                app.use(express.methodOverride());
                app.use(express.session({ secret: cfg.secret }));
            },
            cfg: {
                path:             '/home/path/to/mysite',
                secret:           'lolcat',
                cache_client:     'public, max-age=3600',
                cache_controller: false,
                lang:             'en' // Default language
            }
        }
    }

or

    domains: {
        '*mysite.com': require('./toyfw.js')({
            srv: function(app, express) {
                app.use(app.router);
                app.use(express.logger());
                app.use(express.bodyParser());
            }
        })
    }

or

    domains: {
        '*mysite.com': app // Where app is an Express server
    }

MVC

Controllers

A controller must be in the ./controller/ folder. If mysite.com/test is requested, then the controller test will be loaded. If it does not exist, then the default controller will be loaded.

If not redefined in the cfg section, controller/default.js is the default controller.

A controller must be defined like this :

controller/default.js :

module.exports = function () {
    return 'This text is generated from the controller';
};

A controller can hide himself by returning the number 404. Exemple :

controller/secure.js :

var isAllowed = function() { ... };
module.exports = function () {
    if(!isAllowed()) {
       return 404;
    } else {
       return 'Content of the secret page';
    }
};

Views

Views are in the ./view/ folder. this.mvc.template uses the underscore.js template engine.

Load a view with template :

controller/default.js :

module.exports = function () {
    return this.mvc.template('index', {message: 'Test Message!'});;
};

view/index.html :

<b>The message is :</b> <%=message%>

output :

The message is : Test Message!

Langs

Lang files are in the ./lang/ folder. Each lang is in its folder (like ./lang/en/). Usage :

controller/default.js :

module.exports = function () {
    this.mvc.langFile('mainwords');
    return this.mvc.template('index', {userName: 'admin'});;
};

view/index.html :

<h1><%=lang('welcome', { user: userName })%></h1>
<p><%=lang('connected', { count: Math.round(Math.random()*800) })%></p>

lang/en/mainwords.lang.js :

module.exports = {
    'welcome':      'Welcome {user}!',
    'connected':    '{count} users are online at this moment.'
};

output :

Welcome admin!

327 users are online at this moment.

/*
* ~/app$ node nsrv.js
*/
require('./toyfw.js')({
domains: {
'*xy.com': {
srv : function (app, express, cfg) {
app.use(app.router);
app.use(express.logger());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.methodOverride());
app.use(express.session({ secret: cfg.secret }));
},
cfg : {
path: '/home/user/app',
host: 'xy.com',
secret: 'lolcat',
controller: 'default', // default controlleur
cache_client: 'public, max-age=3600',
cache_controller: false,
lang: 'fr'
}
}
},
port: 80,
ip: 'ip'
});
/*
* ToyFW
* release 1.0
*/
module.exports = (function () {
var fs = require('fs'),
path = require('path'),
mime = require('mime'),
express = require('express'),
mongoose = require('mongoose'),
_ = require('underscore'),
app = express.createServer();
return function (sgl) {
// Multi-domain support
if(!_.isEmpty(sgl) && (!_.isEmpty(sgl.domains) || _.isString(sgl) || _.isArray(sgl))) {
// 'mysite.com' or ['mysite.com', 'john.com']
if(_.isString(sgl) || _.isArray(sgl)) {
sgl = {
domains: sgl,
port: 80
}
}
// { domains: 'mysite.com' }
if(_.isString(sgl.domains)) {
sgl.domains = (function(){
var output = {};
output[sgl.domains] = {};
return output;
})();
}
// { domains: ['mysite.com', 'john.com'] }
else if(_.isArray(sgl.domains)) {
_(sgl.domains).each((function() {
sgl.domains = {};
return function(elem) {
sgl.domains[elem] = {};
};
})());
}
// { domains: {'mysite.com': {...}} }
var self = arguments.callee,
count = Object.keys(sgl.domains).length,
server, i = 0;
for(var domain in sgl.domains) {
if(hasOwnProperty.call(sgl.domains, domain)) {
server = sgl.domains[domain];
app.use(express.vhost(domain,
// path
_.isString(server) ? require(server).app :
// params to create app
server.srv || server.cfg || _.isEmpty(server) ? self(server) :
// app
server
));
if(++i === count) {
app.listen(sgl.port || 80, sgl.ip);
return app;
}
}
}
}
// config
sgl.cfg = _.extend({
path: './',
host: 'undefined',
secret: '123456789',
controller: 'default', // default controlleur
view: '',
cache_client: 'public, max-age=3600',
cache_controller: true,
lang: 'en',
ts: Math.round(+new Date/1000),
tsm: +new Date
}, sgl.cfg);
// mvc
sgl.mvc = {
// view file
view: function (file) {
file = __dirname + '/view/' + file + '.html';
return path.existsSync(file) ? fs.readFileSync(file, 'utf8') : '{view <em>' + file + '</em> not found}';
},
// routing management
routing: function (req, res, met) {
var requestUrl = req.url.split('/'),
controller = requestUrl[1],
file = __dirname + '/controller/' + (controller === '' ? this.cfg.controller : controller) + '.js',
prev_cache_controller = this.cfg.cache_controller,
exists = path.existsSync(file);
if(!exists) {
file = __dirname + '/controller/' + this.cfg.controller + '.js';
}
this.cfg.view = exists ? ( requestUrl[2] || 'index' ) : controller;
var src = require(file).call(this, req, res, met);
res.send(src === 404 ? '{page <em>' + req.url + '</em> not found}' : src);
if(!this.cfg.cache_controller) {
delete require.cache[file];
}
this.cfg.cache_controller = prev_cache_controller;
},
// model
model: function () {
//...
},
// template
template: function (view, obj) {
_.templateSettings = {
interpolate : /<%=([\s\S]+?)%>/g
};
obj = _.extend({'lang':this.lang, 'langObj':this.langObj}, obj);
return _.template(this.view(view))(obj);
},
//langObj
langObj: {},
// lang
lang: function (tag, obj) {
_.templateSettings = {
interpolate : /\{(.+?)\}/g
};
return this.langObj[tag] ? _.template(this.langObj[tag])(obj) : '{lang tag <em>' + tag + '</em> not found}';
},
// langload
langFile: function (file) {
if(!sgl.cfg.lang) {
return;
}
var file = __dirname + '/lang/' + sgl.cfg.lang + '/' + file + '.lang.js';
this.langObj = _.extend((path.existsSync(file) ? require(file) : {}), this.langObj);
}
};
// tools
sgl.tool = path.existsSync('./tools.js') ? require('./tools.js') : {};
// server
sgl.srv && sgl.srv(app, express, sgl.cfg);
// static (/public)
app.get('/public*', function(req, res){
filename = sgl.cfg.path + req.url;
if(req.url !== '/public/' && path.existsSync(filename)) {
fs.readFile(filename, "binary", function(err, file) {
res.writeHead(200, {'Content-Type': mime.lookup(filename), 'Cache-Control': sgl.cfg.cache_client});
res.write(file, "binary");
res.end();
});
}
else {
res.send('{file <em>' + req.url + '</em> not found}');
}
});
// request
app.get('*', function(req, res) {
sgl.mvc.routing.call(sgl, req, res, 'get');
});
app.post('*', function(req, res) {
sgl.mvc.routing.call(sgl, req, res, 'post');
});
console.log(sgl.cfg.host + ' [load]');
return app;
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment