decorator-module v0.1.6
Decorator pattern
This library implement 3 Symfony features for node without Babel:
Annotation in controller method. For example: @Route('/info', 'GET') create a route /info with GET verb. When you are calling the route, the method annotated is executed automatically.
All controller's methods receives request object in parameters and Must be return a Response object.
It is possible to add custom annotation. They could replace the express middleware for the annoted route
Usage
implementation
On server.js
const decorator = require('decorator-module');
//launch analyse of the controller directory
decorator.launch(__dirname + '/src/');
// add manual route (optional)
decorator.router.add('get', '/test', 'Main', 'test');
//inject the router inside your app
app.use(CONF.APIURL, decorator.router.router);
on src/ directory
The controllers must be named with a specific syntax:
src/
----MainController.js
----AuthController.js
All methods must be wrote with 'Action' suffix (getCustmerAction...)
All methods must be returned a new Response object
All methods must be static
Response signature:
constructor(success: boolean, code: number = 200, result: object = {})
example (ES6):
const Response = require('decorator-module').response;
/**
* Main controller class
*/
class MainController {
/**
* route annotation
* @Route('/info', 'GET')
*
* @param req
* @returns {Response}
*/
static mainAction(req) {
return new Response(true, 200, { message: 'api ok' });
}
/**
* Route added manually on main.js
* @param req
* @returns {Response}
*/
static testAction(req) {
return new Response(true, 200, { message: 'test action' });
}
}
module.exports = MainController;
example (ES5):
const Response = require('decorator-module').response;
module.exports = {
/**
* @Route('/init', 'POST')
*
* @param req
*/
mainAction: function(req) {
return new Response(true, 200, {action : 'init'})
}
};
It's possible to bind method params with a decorator.
To bind a new parameter, the Response instance returned by the decorator must have an typescript additionalCallParams : array<any>
property.
It's possible to bind unlimited number of new params
Here, we have an example with user fetching.
The decorator:
const Response = require('decorator-module').response;
const User = require('../model/user');
class FetchUser {
static async execute(controller, method, req) {
const user = await User.findOne({ id : req.body.user_id });
return new Response(true, null, {
additionalCallParams: [user],
});
}
}
FetchUser.inBuild = false;
module.exports = FetchUser;
Inside the controller:
/**
* @Route('/customer', 'GET')
* @FetchUser()
* @param user User
* @param req
*/
static getInfoAction(req, user) {
return new Response(true, 200, { result: user });
}
Response listener
v0.1.3 added a response listener, onDecoratorResponse and onControllerResponse.
This listener uses the Decorator response and Controller response, the callback has two parameters.
The response from Decorator or Controller and the express res object.
It's a nice feature to standardize the API returns.
On server.js
const decorator = require('decorator-module');
//launch analyse of the controller directory
decorator.launch(__dirname + '/src/');
//The two listeners
decorator.responseListener.onDecoratorResponse((response, res) => res.status(response.code).send({
error: true,
message : response.result.error
}));
decorator.responseListener.onControllerResponse((response, res) => res.status(response.code).send({
error: false,
customResult: response.result
}));
// add manual route (optional)
decorator.router.add('get', '/test', 'Main', 'test');
//inject the router inside your app
app.use(CONF.APIURL, decorator.router.router);
Application example
https://gitlab.com/ThomasDupont/empty_node_api.git
Author
Thomas Dupont https://gitlab.com/ThomasDupont