A suite of decorators built to wire up express controllers
$ npm install express express-marshal
Make sure you have decorators enabled through babel:
$ npm install --save-dev @babel/plugin-proposal-decorators
Add the plugin to your .babelrc:
{
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}
import express, { Router } from 'express'
import { mount, controller, param, validate, get, post } from 'express-marshal';
import Joi from 'joi';
@controller('/users')
class UserController {
// Add route parameters
@param('id')
preloadUser(req, res, next, id) {
const user = UserService.find({ id });
if (!user) {
res.sendStatus(404);
return;
}
req.user = user;
next();
}
// Add route-specific middleware
@get('/', [authenticator])
getUsers(req, res) {
res.json({ users: [] });
}
// Use the previously specified param
@get('/:id')
getUser(req, res) {
res.json({
user: req.user
});
}
// Validate user paylaods with Joi
@validate({
email: Joi.string().required(),
password: Joi.string().required()
})
@post('/')
createUser(req, res) {
res.json({ users: [] });
}
}
const app = express()
const router = new Router();
mount(router, [UserController]);
app.use(router);
app.listen(process.env.PORT || 3000);
-
An Express router
-
Array of decorated controllers
import express, { Router } from 'express';
import { mount } from 'express-marshal';
const app = express()
const router = new Router();
mount(router, [UserController]);
app.use(router);
app.listen(3000);
-
The basepath will be prepended to all controller routes
-
Middleware to be run for every route on the controller
import { controller, get } from 'express-marshal';
@controller('/example')
export default class ExampleController {
...
}
-
The desired HTTP method (get, post, etc.)
-
The endpoint to be appended to the parent controller's basepath
-
Array of middleware only to be run for this route
@get(path, middleware)
@post(path, middleware)
@put(path, middleware)
@patch(path, middleware)
@delete(path, middleware)
These are less verbose aliases for @route(method, path)
so you can use @get('/revoke')
instead of @route('get', '/revoke')
.
import { controller, get } from 'express-marshal';
@controller('/docs')
export default class DocsController {
@get('/')
index() {
...
}
}
-
A generic object containing Joi properties or a preconfigured Joi schema to validate an incoming payload against. A generic object will be converted to a Joi schema upon validation. A
GET
request will validate thereq.query
object while aPOST
request will validate thereq.query
object. Returns a 400 along with the Joi error if payload is invalid.
import { controller, validate, post } from 'express-marshal';
import Joi from 'joi';
@controller('/users')
export default class UsersController {
@validate({
username: Joi.string().required()
})
@post('/')
createUser() {
...
}
}
- https://github.com/stewartml/express-decorators
- https://github.com/knownasilya/hapi-decorators
- https://github.com/serhiisol/node-decorators/tree/master/express
MIT © Kyle Alwyn