Created
June 22, 2012 12:11
-
-
Save AMSTKO/2972389 to your computer and use it in GitHub Desktop.
toyjs.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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