#!/usr/bin/env node require('colors'); var Ne = require('neon'); Nitrogen = { Manifest : require('./lib/manifest.js'), Server : {} }; Ne.Class(Nitrogen.Server, 'Editor')({ prototype : { fs : require('fs'), express : require('express'), httpProxy : require('http-proxy'), io : require('socket.io'), http : require('http'), app : null, server : null, socket : null, port : 4000, occipitalOptions : {}, init : function init(config) { Object.keys(config).forEach(function (property) { this[property] = config[property]; }, this); console.log('Nitrogen Session Server starting '); this.app = this.express(); this.proxy = new this.httpProxy.RoutingProxy(); this.server = this.http.createServer(this.app); this.initRack(); this.initDb(); this.initRoutes(); this.server.listen(this.port); this.socket = this.io.listen(this.server); this.initSyncEvents(); console.log('Nitrogen Session Server listening on port ' + this.port); }, initRack : function initRack() { var nitrogen = this; this.app.use(this.express.logger()); this.app.use(this.express.compress()); this.app.use(function (request, response, next) { response.header("Access-Control-Allow-Origin", "*"); response.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); response.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With'); if ('OPTIONS' == request.method) { response.send(200); } else { next(); } }); // This has to be here in order for a proxied post to work. // See https://github.com/nodejitsu/node-http-proxy/issues/180 // for more information. this.app.use(function (request, response, next) { if (request.url.match(/\/attachments\/.*/) && request.method === "POST" ){ var options = nitrogen.occipitalOptions; nitrogen.proxy.proxyRequest( request, response, options ); } else { return next(); } }); this.app.use(this.express.bodyParser()); this.app.use('/', this.express.static('public')); }, initDb : function initDb() { var fileNames = this.fs.readdirSync(__dirname + '/../').filter(function(fn){ return fn.match(/.*\.json$/); }); var i, filePath, collectionName; data = Nitrogen.data = {}; for( i=0; i < fileNames.length; i+=1 ){ filePath = __dirname + '/../' + fileNames[i]; collectionName = fileNames[i].replace(/.json/, ''); data[collectionName] = this.fs.readFileSync(filePath).toString().replace(/\n$/, "").split(/\n/).map(function(r){ return JSON.parse(r); }); } }, initRoutes : function initRoutes() { var nitrogen = this, path = require('path'); this.app.get('/', function (request, response) { var file = path.resolve('./public/app.html'); response.sendfile(file); }); this.app.get('/api/all', function (req, res) { res.set('Content-Type', 'application/json'); res.send(JSON.stringify(data)); }); this.app.get('/api/:model', function (req, res) { var records = data[req.params.model] res.set('Content-Type', 'application/json'); res.send(JSON.stringify(records)); }); this.app.get('/api/:model/:id', function (req, res){ var model = req.params.model; var record = data[model].filter(function (record) { return record.id == req.params.id; })[0]; if (record) { res.set('Content-Type', 'application/json'); res.send(JSON.stringify(record)); } else { res.set('Content-Type', 'application/json'); res.send(404, 'record not found'); } }); this.app.get('/api/:model/:id/delete', function (req, res){ var model = req.params.model; var record = data[model].filter(function (record) { return record.id == req.params.id; })[0]; data[model].splice(data[model].indexOf(record), 1); res.set('Content-Type', 'application/json'); res.send('{}'); }); this.app.post('/api/:model/create', function (req, res){ var model = req.params.model; var record = req.body; record.id = util.generateUid(24); data[model].push(record); res.set('Content-Type', 'application/json'); res.send(JSON.stringify(record)); }); this.app.post('/api/:model/:id/update', function (req, res){ var model = req.params.model; var record = data[model].filter(function (record) { return record.id == req.params.id; })[0]; var position = data[model].indexOf(record); console.log(req); data[model].splice(position, 1, req.body); var record = data[model].filter(function (record) { return record.id == req.params.id; })[0]; res.set('Content-Type', 'application/json'); res.send(JSON.stringify(record)); }); this.app.get('/manifest_doc.js', function (req, res) { res.set('Content-Type', 'application/json'); // Generate the package every time for development Manifest.generatePackage(function () { res.sendfile(path.resolve('./public/manifest_doc.js')); }); /* TODO: Uncomment when file detection is done nitrogen.fs.exists('./public/manifest_doc.js', function (exists) { if (exists) { res.sendfile(path.resolve('./public/manifest_doc.js')); } else { // create package Manifest.generatePackage(function () { res.sendfile(path.resolve('./public/manifest_doc.js')); }); } }); */ }); this.app.get('/get_assets', function (req, res) { res.set('Content-Type', 'text/plain'); // Generate the package everytime for development Manifest.generatePackage(function () { res.sendfile(path.resolve('../app_assets/package.dat')); }); /* TODO: Uncomment when file detection is ready nitrogen.fs.exists('../app_assets/package.dat', function (exists) { if (exists) { res.sendfile(path.resolve('../app_assets/package.dat')); } else { // create package Manifest.generatePackage(function () { res.sendfile(path.resolve('../app_assets/package.dat')); }); } }); */ }); this.app.get('/attachments/*', function (req, res) { var options = nitrogen.occipitalOptions; nitrogen.proxy.proxyRequest( req, res, options ); }); }, initSyncEvents : function () { this.socket.sockets.on('connection', function (socket) { socket.emit('connected', {message : "Connection established"}); socket.on('sync', function (sync_data) { console.log(">> Incoming LSD DATA".blue); sync_data = JSON.parse(sync_data); // Let's handle each guy switch(sync_data.action) { case "create": data["tasks"].push(sync_data.data); break; case "update": var record = data["tasks"].filter(function (record) { return record.id == sync_data.data.id; })[0]; var position = data["tasks"].indexOf(record); data["tasks"].splice(position, 1, sync_data.data); break; case "remove": var record = data["tasks"].filter(function (record) { return record.id == sync_data.data.id; })[0]; var position = data["tasks"].indexOf(record); data["tasks"].splice(position, 1); break; } socket.emit('sync_ok', {message : "Sync Received: OK"}); }); }); this.socket.sockets.on('disconnect', function (socket) { socket.emit('disconnected', {message : "Connection lost"}); }); } } }); new Nitrogen.Server.Editor({ port : process.argv[2] || 4000, occipitalOptions : { host : (process.argv[3]) ? process.argv[3].replace(/:.*/, '') : '127.0.0.1', port : (process.argv[3]) ? process.argv[3].replace(/.*:/, '') : '3001' } });