vivocha/arrest

Name: arrest

Owner: Vivocha

Description: Swagger REST framework for Node.js, with support for MongoDB and JSON-Schema

Created: 2013-06-03 14:10:54.0

Updated: 2017-06-17 20:50:45.0

Pushed: 2017-12-04 11:23:07.0

Homepage:

Size: 275

Language: JavaScript

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

arrest

Swagger REST framework for Node.js, with support for MongoDB and JSON-Schema

travis build Coverage Status npm version

Arrest lets you write RESTful web services in minutes. It automatically generates a Swagger description of the API and support input validation using JSON-Schemas.

Highlight features:

Note for 1.3 users: arrest 3.x is a complete rewrite of the old module and it's not backwards compatible.

How to Install
install arrest
Super Simple Example

The following sample application shows how to create a simple REST API, using a MongoDB collection as the data store. In the sample, the path /tests is linked to a tests collection on a MongoDB instance running on localhost:

t arrest = require('arrest');
t api = new arrest.API();

addResource(new arrest.MongoResource('mongodb://localhost:27017', { name: 'Test' }));

listen(3000);

The Swagger specification of the API you just created is available at http://localhost:3000/swagger.json

Now you can query your data collection like this:

 "http://localhost:3000/tests"

You can add a new item:

 "http://localhost:3000/tests" -H "Content-Type: application/json" -X POST -d '{ "name": "Jimbo", "surname": "Johnson" }'

You can query a specific item by appeding the identifier of the record (the _id attribute):

 "http://localhost:3000/tests/51acc04f196573941f000002"

You can update an item:

 "http://localhost:3000/tests/51acc04f196573941f000002" -H "Content-Type: application/json" -X PUT -d '{ "name": "Jimbo", "surname": "Smith" }'

And finally you can delete an item:

 "http://localhost:3000/tests/51acc04f196573941f000002" -X DELETE
Creating an API

An API is a collection of Resources, each supporting one or more Operations.

In arrest you create an API by creating an instance of the base API class or of a derived class. You then add instances of the Resource class or a derived one. Each resource contains its supported Routes, that is a collection of instances of classes derived from the abstract Operation, which represents an operation to be executed when an HTTP method is called on a path.

The following code demonstrates this three level structure:

t arrest = require('arrest');
t api = new arrest.API();

t operation1 = function(req, res, next) {
s.json({ data: 'this is operation 1' });

t operation2 = function(req, res, next) {
s.json({ data: 'this is operation 2' });

t operation3 = function(req, res, next) {
s.json({ data: 'this is operation 3' });

t resource1 = new arrest.Resource({
me: 'SomeResource',
utes: {
'/': {
  get: operation1,
  post: operation2
},
'/some-path': {
  put: operation3
}



addResource(resource1);
listen(3000);

The API above supports the following operations:

Please note how the some-resources path was automatically constructed using the name of the resource SomeResource, making it plural and converting the camelcase in a dash-separated name. This default behaviour can be changed specifying the namePlural and path when creating the resource (e.g. new Resource({ name: 'OneResource', namePlural: 'ManyResources', path: 'my_resources' }))

Another other way to produce the same result is:

t arrest = require('arrest');
t api = new arrest.API();

t resource1 = new arrest.Resource({ name: 'SomeResource' });

urce1.addOperation('/', 'get', function(req, res, next) {
s.json({ data: 'this is operation 1' });

urce1.addOperation('/', 'post', function(req, res, next) {
s.json({ data: 'this is operation 2' });

urce1.addOperation('/some-path', 'put', function(req, res, next) {
s.json({ data: 'this is operation 3' });


addResource(resource1);
listen(3000);

In real world applications, where resources and operation are in fact more complex, you will want to create class that extend the basic classes in arrest, like in the next example:

t arrest = require('arrest');

s MyOperation extends arrest.Operation {
nstructor(resource, path, method) {
super('op1', resource, path, method);

ndler(req, res, next) {
res.json({ data: 'this is a custom operation' });



s MyResource extends arrest.Resource {
nstructor() {
super();
this.addOperation(new MyOperation(this, '/', 'get'));



s MyAPI extends arrest.API {
nstructor() {
super({
  info: {
    title: 'This is a custom API',
    version: '0.9.5'
  }
});
this.addResource(new MyResource());



t api = new MyAPI();
listen(3000);

The API above supports GETs on http://localhost/my-resources (note how the path was in this case constructed automatically from the name of the class MyResource).

By the default, arrest APIs add a special route /swagger.json that returns the Swagger description of the API: the Swagger object is populated with the properties of the API object, Resources are converted into Swagger Tags and Operations are mapped to Swagger Operations.

Data validation

arrest supports JSON-Schema for data validation. Validation rules are set using the Swagger specification. For instance, the following code show how to validate the body of a POST and the query paramters of a GET:

s MyOperation1 extends arrest.Operation {
nstructor(resource, path, method) {
super('op1', resource, path, method);
this.setInfo({
  parameters: [
    {
      name: 'body',
      in: 'body',
      required: true,
      schema: {
        type: 'object',
        required: [ 'name' ],
        additionalProperties: false,
        properties: {
          name: {
            type: 'string'
          },
          surname: {
            type: 'string'
          }
        }
      }
    }
  ]
});

ndler(req, res, next) {
res.json({ data: 'this is a op1' });



s MyOperation2 extends arrest.Operation {
nstructor(resource, path, method) {
super('op2', resource, path, method);
this.setInfo({
  parameters: [
    {
      name: 'lang',
      in: 'query',
      type: 'string',
      required: true
    },
    {
      name: 'count',
      in: 'query',
      type: 'integer'
    }
  ]
});

ndler(req, res, next) {
res.json({ data: 'this is a op2' });



s MyResource extends arrest.Resource {
nstructor() {
super();
this.addOperation(new MyOperation1(this, '/', 'post'));
this.addOperation(new MyOperation2(this, '/', 'get'));


Omitting the body or passing an invalid body (e.g. an object without the name property) when POSTing to http://localhost/my-resources will return an error. Likewise GETting without a lang parameter or with a count set to anything other than a number will fail.

Scopes and security validators

TBA

Creating an API with a MongoDB data store

TBA (default api routes)

Using arrest with express

TBA

Debugging

TBA

API documentation

TBA


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.