lindyhop
Express router with doc generation, validation and improved middleware support. See an example:
var express = var lindyhop = var app = var lindy = lindyhop var users = lindy users
Installation
npm install lindyhop --save
Configuring an express app
var express = var lindyhop = var app = var lindy = lindyhop
Routers
A router is a group of endpoints. You just need to specify the path in which these endpoints will be mounted. For example
var users = lindy
Routes
You can create routes from an existing router using the .get()
, .post()
, .put()
, .delete()
and .patch()
methods. All these methods require two arguments. First the path of the route and then the description of the route for documentation purposes.
Routes have a .params()
method where you validate the request parameters and a .run()
method where you put your business logic and which receives the validated parameters.
users
The returned data from the .run()
method is automatically serialized to JSON.
Validations
Validations are described in the .params()
method. An object is passed to the callback function of this method that allows you to describe validations. The structure is validate.[type](fieldName, description).specificMethod()
.
There are two built-in validators: string
and number
with the following methods:
String validations
.notEmpty()
will return an error if the value is an empty string.trim()
will trim the value.lowerCase()
will lowercase the value.upperCase()
will uppercase the value
Number validations
.min(minValue)
will return an error if the value passed is lower than that minimum value.max(maxValue)
will return an error if the value passed is higher than that maximum value
Additionally any validator has these methods:
.as()
allows you to rename the parameter.optional()
makes the parameter optional, so no error will be returned if the parameter is not in the request.array()
will accept a single value or multiple values for this parameter while returning always an array to you
By default any GET
or DELETE
request gets the parameters from the query string, and in any other case it gets the values from the body. If you want to override this behavior you can specify a different source with .in()
for each parameter.
.in('query')
will look for the parameter in the query string.in('header')
will look for the parameter in a request header.in('path')
will look for the parameter in the URL (such as/users/:userId
).in('formData')
will look for the parameter in a request body
Custom validators
You can also create your custom validators. For example, let's see how to create a custom validation that reads objects by id using an ORM.
AbstractValidator // custom method { thisclazz = clazz return this } // mandatory method { return thisclazz } // register the validatorlindyhop
Then you can use it like this:
events
All validations are executed in parallel, so in our case the user
and the event
are read from the database in parallel.
Middleware
You can add your own middleware like this:
lindyhop
You need to specify the name of the middleware and then a function with the following parameters:
req
: the requestres
: the responseoptions
: we will see this laterparams
: the params object that will be passed to therun()
method of the controller
Then you can use it this way:
users
You can optionally pass an options object to middleware()
like this: .middleware('pagination', someOptions)
. That object will be passed to the middleware function as third parameter.
HTML output
By default JSON is always returned, but you can also render HTML this way:
// app is your express appappapp users
This endpoint will render the index.pug
template passing { message: 'Hello world' }
as render options. So your template could contain:
h1= message
Redirects
If you need to do an HTTP redirect you can do it with lindyhop.redirect(url, [permanent])
router router
Custom output serializers
You can create custom serializers easily:
lindyhop
Error responses
You can create meaningful errors with the rejects
utility. For example:
var rejects = lindyhoprejects users
The available error types are:
rejects.internalError()
: will return a 500 status coderejects.forbidden()
: will return a 403 status coderejects.badRequest()
: will return a 400 status coderejects.notFound()
: will return a 404 status coderejects.unauthorized()
: will return a 401 status code
All these methods can be used with one or two arguments.
With one string, such as rejects.internalError('Your message')
it will return
Passing two strings, such as rejects.internalError('DatabaseError', 'Your message')
will return a response like this:
If the controller throws an Error
, it will return a response like this:
And the error will be printed to the stderr
with console.error()
.
If the controller returns a regular promise rejected, created with a string like Promise.reject('Your message')
it will return a response like this:
But if the rejection reason is not a string, like Promise.reject({ fail: 'reason' })
, the rejection object will be serialized directly:
Validation errors contain an array of errors
, each one containing a field
with the name of the field that filed validation and a message
describing the reason:
Documentation
Calling lindy.docs()
you will get a valid Swagger API description document. You can save the result in a file and use swagger-codegen to generate documentation or even generate an SDK for your API. Here's for example how you can generate static docs for your API:
swagger-codegen generate -i api.json -l html -o docs/
When configuring your express app you can pass an optional info
object for swagger. Example
var lindy = lindyhop