Skip to content

Instantly share code, notes, and snippets.

@AMSTKO
Created June 22, 2012 12:11
Show Gist options
  • Save AMSTKO/2972389 to your computer and use it in GitHub Desktop.
Save AMSTKO/2972389 to your computer and use it in GitHub Desktop.
toyjs.js
/*
* ToyFW
* 1.11217.003
*/
module.exports = (function() {
var fs = require('fs'),
path = require('path'),
mime = require('mime'),
express = require('express'),
formidable = require('formidable'),
app = express.createServer(),
debug = express.createServer();
// debug
var error = function(e, res) {
console.log(e.stack);
res && res.send('<h1>toyjs error</h1><h2>' + e + '</h2><pre>' + e.stack + '</pre>');
}
// extend
var extend = function(obj) {
[].slice.call(arguments, 1).forEach(function(source) {
for(var prop in source) if(source[prop] !== undefined) obj[prop] = source[prop];
});
return obj;
}
// addons
var adn = function(sgl, mvc, tmp, tls) {
// template
var templateSettings = {
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%=([\s\S]+?)%>/g,
escape : /<%-([\s\S]+?)%>/g
};
var template = function(str, data) {
var c = templateSettings;
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
'with(obj||{}){__p.push(\'' +
str.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(c.escape, function(match, code) {
return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
})
.replace(c.interpolate, function(match, code) {
return "'," + code.replace(/\\'/g, "'") + ",'";
})
.replace(c.evaluate || null, function(match, code) {
return "');" + code.replace(/\\'/g, "'")
.replace(/[\r\n\t]/g, ' ') + ";__p.push('";
})
.replace(/\r/g, '\\r')
.replace(/\n/g, '\\n')
.replace(/\t/g, '\\t')
+ "');}return __p.join('');";
var func = new Function('obj', tmpl);
if (data) return func(data);
return function(data) {
try{
return func.call(this, data);
}
catch(e) {
error(e);
}
};
};
// return public addons
return {
lang: function(tag, obj) {
templateSettings.interpolate = /\{(.+?)\}/g;
return tmp.langObj[tag] ? template(tmp.langObj[tag])(obj) : '{lang tag <em>' + tag + '</em> not found}';
},
langFile : function(file) {
var file = sgl.cfg.path + '/lang/' + sgl.cfg.lang + '/' + file + '.lang.js';
tmp.langObj = extend((path.existsSync(file) ? require(file) : {}), tmp.langObj);
},
// template
template : function(view, obj) {
obj = extend({
sgl : sgl,
mvc : mvc,
tmp : tmp,
tls : tls,
adn : adn(sgl, mvc, tmp),
status: ''
}, obj);
templateSettings.interpolate = /<%=([\s\S]+?)%>/g;
return template(mvc.view(view))(obj);
},
// cache
deleteCache : function(file) {
delete require.cache[file || this.file];
}
};
};
// server initialisation
this.server = function(sgl) {
// unique
var appre = express.createServer();
// configuration
sgl.cfg = extend({
path: './',
tools: sgl.cfg.path+'/tools.js',
host: 'undefined',
secret: '123456789',
controller: 'default', // default controlleur
cache_client: 'public, max-age=3600',
cache_model: true,
lang: 'fr',
ts: Math.round(+new Date/1000),
tsm: +new Date,
socket: false,
mongodb: false,
derail: false,
send: false,
timeout: 1000
}, sgl.cfg);
// object for general data shared
sgl.share = {};
sgl.extend = extend;
// tools
if(sgl.cfg.tools && path.existsSync(sgl.cfg.tools)) {
var tls = sgl.t = require(sgl.cfg.tools)();
}
// mvc
var mvc = {
// model
model : function(name) {
var file = sgl.cfg.path + '/models/m.' + name + '.js';
if(path.existsSync(file)) {
return require(file).call({file:file}, {
sgl : sgl,
mvc : mvc,
tls : tls
})
}
},
// view file
view : function(file) {
file = sgl.cfg.path + '/views/' + file + '.html';
return path.existsSync(file) ? fs.readFileSync(file, 'utf8') : '{view <em>' + file + '</em> not found}';
},
// controller management
controller : function(req, res, met) {
try {
// ctrl request
if(sgl.derail && sgl.derail(req, res, met) === true) {
return;
}
// request elements
var request = req.url.replace(/\?.*$/gi, '').split('/'),
controller = request[1],
task = request[2] || 'index',
segment = request[3] || null;
// ctrl route
for(x in sgl.route) {
if(controller === x) {
controller = sgl.route[x].controller;
task = sgl.route[x].task;
segment = request[2];
break;
}
}
// request object
var tmp = {
req: req,
res: res,
met: met,
session: req.session || {},
controller: controller,
task: task,
segment: segment,
body: req.body || {},
ip: req.socket.remoteAddress,
is_sent: false,
file: '',
// internationalization
langObj: {}
};
// toy object for controller
var toy = {
sgl : sgl,
mvc : mvc,
tmp : tmp,
tls : tls,
adn : adn(sgl, mvc, tmp, tls),
send : sgl.send ? sgl.send(toy) : function(src) {
if(!tmp.is_sent) {
tmp.is_sent = true;
tmp.res.send(src);
}
}
};
// controller file (a rendre asynchrone !)
tmp.file = this.cfg.path + '/controllers/c.' + tmp.controller + '.js';
if(!path.existsSync(tmp.file)) {
tmp.file = this.cfg.path + '/controllers/c.' + this.cfg.controller + '.js';
}
// send
require(tmp.file)(toy);
// timeout
setTimeout(function() {
if(tmp.is_sent === false && tmp.met === 'get') {
tmp.is_sent = true;
res.send('{setTimeout: page <em>' + tmp.req.url + '</em> not found}')
}
}, this.cfg.timeout);
}
catch(e) {
error(e, res);
}
}
};
// express configuration
//appre.use(express.logger());
//appre.use(express.bodyParser()); // remplace par formidable
appre.use(express.methodOverride());
appre.use(express.cookieParser());
appre.use(express.session({ secret: sgl.cfg.secret }));
appre.use(appre.router);
// socket.io
if(sgl.cfg.socket) {
sgl.io = require('socket.io').listen(app);
console.log(sgl.cfg.host + ': socket.io [ok]');
}
// mongodb
if(sgl.cfg.mongodb) {
// config
sgl.cfg.mongodb = extend({
host: '127.0.0.1',
port: '27017',
dbname: 'default',
server_options: {},
db_options: {}
}, sgl.cfg.mongodb);
var mongodb = require('mongodb'),
mongoserver = new mongodb.Server(sgl.cfg.mongodb.host, sgl.cfg.mongodb.port, sgl.cfg.mongodb.server_options),
db_connector = new mongodb.Db(sgl.cfg.mongodb.dbname, mongoserver, sgl.cfg.mongodb.db_options);
db_connector.open(function(err, db) {
sgl.mongodb = db;
console.log(sgl.cfg.host + ': mongodb [ok]');
});
}
// mysql
if(sgl.cfg.mysql) {
// config
sgl.cfg.mysql = extend({
host: '127.0.0.1',
port: '3306',
user: 'root',
passwd: '',
dbname: 'default'
}, sgl.cfg.mysql);
sgl.mysql = require('mysql').createClient({
user: sgl.cfg.mysql.user,
password: sgl.cfg.mysql.passwd,
host: sgl.cfg.mysql.host,
port: sgl.cfg.mysql.port,
database: sgl.cfg.mysql.dbname
});
console.log(sgl.cfg.host + ':'+sgl.cfg.mysql.port+' mysql [ok]');
}
// static (/public)
appre.get('/public*', function(req, res){
filename = sgl.cfg.path + req.url.replace(/\?.*$/gi, '');
if(path.existsSync(filename) && path.extname(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(404);
}
});
// request get
appre.get('*', function(req, res) {
mvc.controller.call(sgl, req, res, 'get');
});
// request post
appre.post('*', function(req, res) {
sgl.form = new formidable.IncomingForm();
// if multipart (file, data...)
if(req.headers['content-type'].match(/multipart\/form-data/i)) {
mvc.controller.call(sgl, req, res, 'post');
}
else {
sgl.form.parse(req, function(err, fields) {
req.body = fields;
mvc.controller.call(sgl, req, res, 'post');
});
}
});
return appre;
};
// debug tools
this.debug = function(sgl) {
try {
// unique
var appre = express.createServer();
var send = '<h1>toyjs debug tools '+sgl.cfg.host+'</h1>';
send += '<a href="/deleteAllCache">delete all cache file</a><br />';
// tmp
appre.get('*', function(req, res) {
var request = req.url.replace(/\?.*$/gi, '').split('/');
// delete cache all
if(request[1]=='deleteAllCache') {
send+='<h2>deleteAllCache cache</h2>';
for(x in require.cache) {
send+= JSON.stringify(require.cache[x]) + '<br /><br />'
delete require.cache[require.cache[x]];
}
}
res.send(send);
});
return appre;
}
catch(e) {
console.log(e);
res.send('<h1>javascript error</h1><h2>' + e + '</h2>');
}
};
// initialization
return function(cfg) {
// multi-domain support
if(cfg.domains) {
for(var x in cfg.domains) {
var domain=cfg.domains[x], sgl={};
if(path.existsSync(cfg.path + '/' + domain)) {
sgl = require(cfg.path + '/' + domain + '/' + domain + '.js')();
app.use(express.vhost(sgl.cfg.domain, this.server(sgl)));
debug.use(express.vhost(sgl.cfg.domain, this.debug(sgl)));
console.log(sgl.cfg.domain + ' [load]');
}
}
// go!
app.listen(cfg.port || 80, cfg.ip || '127.0.0.1');
debug.listen(99, cfg.ip || '127.0.0.1');
}
return app;
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment