├── Procfile ├── README.md ├── package.json ├── stub-generator.js └── server.js /Procfile: -------------------------------------------------------------------------------- 1 | web: node server.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rest-stubs-express4 2 | =================== 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rest-stubs-express4", 3 | "description": "Generates temporary stub REST endpoints using Express 4.x", 4 | "main": "server.js", 5 | "version": "0.1.5", 6 | "author": { 7 | "name": "Adam Breindel", 8 | "email": "adbreind@gmail.com" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/adbreind/rest-stubs-express4.git" 13 | }, 14 | "dependencies": { 15 | "express": ">= 4.0.0", 16 | "morgan" : ">= 1.0.0", 17 | "body-parser" : ">= 1.0.1" 18 | }, 19 | "engines": { 20 | "node": ">= 0.8.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /stub-generator.js: -------------------------------------------------------------------------------- 1 | var fakeDatabase = {}; 2 | /* this is a map of entity name to an array of objects 3 | e.g. { food : [ 4 | { 5 | name: "apple", 6 | id : 21 7 | }, 8 | { 9 | name: "fries", 10 | id : 24 11 | }] 12 | } 13 | etc. */ 14 | 15 | equals = function(field, val, obj) { return obj[field] == val }; 16 | 17 | equalsId = equals.bind(undefined, "id"); 18 | 19 | log = function() { 20 | console.log(JSON.stringify(fakeDatabase)); 21 | }; 22 | 23 | exports.initializeEntity = function(name, objects) { 24 | if (!fakeDatabase[name]) 25 | fakeDatabase[name] = []; 26 | if (objects) 27 | fakeDatabase[name] = objects; 28 | }; 29 | 30 | exports.findAll = function(name) { 31 | return function(req, res, next) { 32 | res.send(fakeDatabase[name]); 33 | } 34 | }; 35 | 36 | exports.findById = function(name) { 37 | return function(req, res) { 38 | var id = req.params.id; 39 | console.log('Retrieving ' + name + ': ' + id); 40 | var found = fakeDatabase[name].filter(equalsId.bind(undefined, id))[0]; 41 | if (found) 42 | res.send(found); 43 | else { 44 | res.status(404); 45 | res.end(); 46 | } 47 | } 48 | }; 49 | 50 | exports.create = function(name) { 51 | return function(req, res) { 52 | var entity = req.body; 53 | var records = fakeDatabase[name]; 54 | entity.id = records.reduce(function(p, c) { 55 | return (c.id && c.id > p) ? c.id : p; 56 | }, 0) + 1; 57 | console.log('Adding ' + name + ': ' + JSON.stringify(entity)); 58 | records.push(entity); 59 | res.send(entity); 60 | } 61 | } 62 | 63 | exports.update = function(name) { 64 | return function(req, res) { 65 | var id = req.params.id; 66 | var entity = req.body; 67 | console.log('Updating ' + name + ': ' + id); 68 | console.log(JSON.stringify(entity)); 69 | var found = fakeDatabase[name].filter(equalsId.bind(undefined, id))[0]; 70 | for (var k in entity) 71 | found[k] = entity[k]; 72 | res.send(found); 73 | } 74 | } 75 | 76 | exports.delete = function(name) { 77 | return function(req, res) { 78 | var id = req.params.id; 79 | console.log('Deleting ' + name + ': ' + id); 80 | var records = fakeDatabase[name]; 81 | var found = records.filter(equalsId.bind(undefined, id))[0]; 82 | records.splice(records.indexOf(found),1); 83 | res.end(); 84 | } 85 | } -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | stubGenerator = require('./stub-generator'), 3 | bodyParser = require('body-parser'), 4 | logger = require('morgan'); 5 | 6 | var app = express(); 7 | 8 | app.use(allowCrossDomain); 9 | app.use(logger()); 10 | app.use(bodyParser.json()); 11 | 12 | entities = []; 13 | entities.forEach(stub); 14 | 15 | function stub(name) { 16 | console.log("Stubbing: " + name); 17 | stubGenerator.initializeEntity(name); 18 | app.route('/' + name) 19 | .get(stubGenerator.findAll(name)) 20 | .post(stubGenerator.create(name)); 21 | 22 | var update = stubGenerator.update(name); 23 | 24 | app.route('/' + name + '/:id') 25 | .get(stubGenerator.findById(name)) 26 | .post(update) 27 | .put(update) 28 | .delete(stubGenerator.delete(name)); 29 | 30 | entities.push(name); 31 | } 32 | 33 | app.post("/entity/:name", function(req, res) { 34 | var entityName = req.params.name; 35 | if (entityName && entities.indexOf(entityName)==-1 && entityName.indexOf(".")==-1) { 36 | stub(entityName); 37 | res.end(); 38 | } 39 | }); 40 | 41 | stubGenerator.initializeEntity("book", [{"title":"Great Expectations","id":2},{"title":"Bleak House","id":4}]); 42 | stub("book"); 43 | 44 | stubGenerator.initializeEntity("contact", [ 45 | {"first":"Joe","last":"Smith","email":"joe@gmail.com","id":1, 46 | company_id:"xyz", lotteryWinner : false }, 47 | {"first":"Joe2","last":"Smith2","email":"joe2@gmail.com","id":2, 48 | company_id:"abc", lotteryWinner : false }, 49 | {"first":"Joe3","last":"Smith3","email":"joe3@gmail.com","phone":"555-1212", 50 | "id":3, company_id:"xyz", lotteryWinner : false} 51 | ]); 52 | stub("contact"); 53 | 54 | var port = Number(process.env.PORT || 5000); 55 | app.listen(port); 56 | console.log('Listening on port ' + port); 57 | 58 | function allowCrossDomain (req, res, next) { 59 | res.header('Access-Control-Allow-Origin', '*'); 60 | res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); 61 | res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With'); 62 | 63 | // intercept OPTIONS method 64 | if ('OPTIONS' == req.method) { 65 | res.send(200); 66 | } 67 | else { 68 | next(); 69 | } 70 | } --------------------------------------------------------------------------------