Name: rest-framework
Owner: Elao
Description: Base components to build REST API
Created: 2014-10-15 09:42:21.0
Updated: 2015-03-20 08:05:46.0
Pushed: 2014-10-28 12:29:01.0
Homepage: null
Size: 256
Language: JavaScript
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
Base components to build REST API
Rest-Framework (RT later) is a toolbox to make an robust REST API faster.
At origin, we have a lots of node server which expose REST API and we will share some code / reflex between each projects.
Each components in toolbox can be used one at time. When one component is too complex, we split in another node module. It's important to keep in mind this sentence. That why rest-framework has dependency to other components like security-framework, validation-framework.
We use bluebird as Promise engine but it's work with all Promise engine.
Collection is an component to format collection of item.
It's designed to have an data source and will handle pagination according to user request.
Pagination work with 2 query parameters:
Pagination work with 3 extra query parameters
Route
var RF = require('rest-framework');
function(req, res, next) {
var collection = RF.Collection();
var dataFunction = function(pagination) {
return new Promise(function(resolve, reject) {
var items = [];
for (var i = 1; i < 50; i++) {
items.push({
id: i,
name: "item " + i
})
}
return resolve(items);
})
};
var countFunction = function() {
return 30;
}
return returnCollection(req, res, dataFunction, countFunction);
}
If user request this route with limit query parameter at 2, collection will return to client an json like
{
count: 30,
items: [{
id: 1,
name: "item 1"
}, {
id: 2,
name: "item 2"
},
?
],
links: {
current: "http://localhost/?page=1&limit=2",
first: "http://localhost/?page=1&limit=2",
last: "http://localhost/?page=15&limit=2",
next: "http://localhost/?page=2&limit=2"
}
}
Links are generated according to req. Don't worry.
Others methods:
returnCollectionTimestamp
returnCollectionFirebase
This 2 methods are very similar because the only difference is in the links generation. Each method need a last parameters to indicate the name of item property which used for generated links.
Cors is an component to expose useful middlewares.
Error is an important component to create and handle error on application.
var RF = require('rest-framework');
var errorComponent = RF.Error({ debug: false });
Error component expose some custom javascript Error like
If you use this error then the handling error function will create appropriate status code on response.
// Create default AccessDeniedError
var error = new errorComponent.AccessDeniedError("", "it's bad no ?")
// will produce an error.message = "NOT_ALLOWED" and error.details = "its bad no ?"
// Create custom AccessDeniedError
var error = new errorComponent.AccessDeniedError("HEY_DUDE", "it's bad no ?")
// will produce an error.message = "HEY_DUDE" and error.details = "its bad no ?"
This function will return to client an formatted error message according to type of error.
{
statusCode: 403, // error.statusCode || predefined statusCode if you use core error || 500
error: 'NOT_ALLOWED', // error.message
details: "its bad no ?", // error.details
date: "Fri Oct 24 2014 15:22:43 GMT+0200 (CEST)"
}
The main module is Routing. Designed for handling error, validation and security.
When you use Routing, you need to follow few rules.
App.js
// load security config (see security-framework for detail)
var securityConfig = {
methods: {}
rules: {
me: {
methods: ['oauth']
}
}
};
// load error handler
var RF = require('rest-framework');
var errorComponent = RF.Error({ debug: false });
// Create Routing
var Routing = RF.Routing(app, securityConfig, {
debug: false,
pathControllers: '/absolute/path/to/controller'
}, errorComponent);
// Find the file in /absolute/path/to/controller/user.js
var UserController = Routing.loadController('user', {});
// create an GET route on "localhost/users" which is behind an security rule named "me" and the name of action are users" located in user.js file
Routing.loadRoute('GET', '/users', 'me', 'user/users');
Notice that you don't need to create an security-framework object but only the configuration for it.
Notice that errorComponent parameter is optional, if you don't want use ours you juste have to put an object which can response to handleError(error, req, res, next)
UserController must be a file like
var RF = require('rest-framework');
module.exports = function(app, config) {
return new Controller(app, config);
}
Controller = function(app, config) {
this.config = config;
this.app = app;
return this;
}
Controller.prototype.getUsersAction = function(req, res) {
var self = this;
var collection = RF.Collection();
var dataFunction = function(pagination) {
return self.app.db.getUsers(pagination);
};
var countFunction = function() {
return self.app.db.getUsersCount();
}
return collection.returnCollectionFirebase(req, res, dataFunction, countFunction, "id");
}
Action method can return many thing like
Anything else will throw an 500 error INTERNAL_ERROR
You can use routing with only app parameters, but you will use default rest-framework parameters. By default, parameters are writing for ours stack.
var Routing = RF.Routing(app);
// Find the file in ./controllers/user.js
var UserController = Routing.loadController('user', {});
// create an GET route on "localhost/users" which is behind an security rule named "user" and the name of action are users" located in user.js file
Routing.loadRoute('GET', '/users', 'user', 'user/users'); // security rules 'user' are http basic and oauth
If you want use validation-framework for an action, you must named your method
Rest-framework will use his dependency to validator-framework and validate each domains on req like
When validation rules are successfull, RF provide a simple way to get trust parameters.
Controller.prototype.getUpdateValidation = function(req, res) {
return [{
rules: {
username: {
required: { value: true, groups: ["create", "update"] }
}
},
on: 'body',
groups: 'update'
},{
rules: {
id: {
required: true
}
},
on: 'params'
},{
rules: {
gender: {
required: true
}
},
on: 'query'
}];
}
Controller.prototype.getUpdateAction = function(req, res) {
var self = this;
var userId = req.validatedValues.params("user_id");
var username = req.validatedValues.body("username");
var gender = req.validatedValues.query("gender");
return {
username: username,
id: userId,
gender: gender
}
})
To know how configure Rule, see validator-framework doc
Utils provide some usefull function like