hapi-holiday

0.4.6 • Public • Published

hapi-holiday

Circle CI dependencies

Create REST API with hapi

NPM

Usage

$ npm install hapi-holiday --save

Example usage

Holiday.define(schemeName, scheme);

Define a scheme for the API routes.

  • schemeName string (required)
  • scheme object (required)
    • scheme.index function(Model, request, done) {} (required)
    • scheme.show function(Model, request, done) {} (required)
    • scheme.save function(Model, request, done) {} (required)
    • scheme.update function(Model, request, done) {} (required)
    • scheme.destroy function(Model, request, done) {} (required)
Example scheme using sequelize
Holiday.define('sequelize', {
 
  // GET all records
  index: (Model, request, done) => {
    Model.findAll({
      offset: request.query.offset,
      limit: request.query.limit,
    })
    .then((records) => {
      done(null, records);
    })
    .catch((err) => {
      done(err, null);
    });
  },
 
  // GET one record
  show: (Model, request, done) => {
    Model.findById(request.params.id)
    .then((records) => {
      done(null, records);
    })
    .catch((err) => {
      done(err, null);
    });
  },
 
  // POST a new record
  save: (Model, request, done) => {
    Model.create(request.payload).then((result) => {
      done(null, result);
    })
    .catch((err) => {
      done(err, null);
    });
  },
 
  // PUT an updated record
  update: (Model, request, done) => {
    Model.update(request.payload, {
      where: {
        id: request.params.id,
      },
    })
    .then((result) => {
      done(null, result);
    })
    .catch((err) => {
      done(err, null);
    });
  },
 
  // DELETE a record
  destroy: (Model, request, done) => {
    Model.destroy({
      where: {
        id: request.params.id,
      },
    })
    .then((affected) => {
      done(null, affected);
    })
    .catch((err) => {
      done(err, null);
    });
  },
});

Holiday.configure(config);

Optional. Overrides default configurations for hapi routes.

// Set default hapi route configs(optional)
Holiday.configure({
  tags: ['api'],
  auth: ['jwt'],
  ...etc.
});

Create routes

new Holiday(schemeName, routeName, Model);

Creates a new instance of routes.

  • schemeName string (required) - name of scheme defined
  • routeName string (required) - name of routes (i.e. /routeName/{id})
  • Model Any (required) - Any kind of model to use
An example for posts model
const PostApi = new Holiday('sequelize', 'posts', Models.Posts);

Validation

Api.validate.index(validationObj)

Api.validate.show(validationObj)

Api.validate.save(validationObj)

Api.validate.update(validationObj)

Api.validate.destroy(validationObj)

Set custom validations for specific route type.

  • validationObj Object (required)
method validates on
Api.validate.index() request.query
Api.validate.show() request.query
Api.validate.save() request.payload
Api.validate.update() request.payload
Api.validate.destroy() request.query
// Example validation to use on 'save'
PostApi.validate.save({
  title: Joi.string().required(),
  content: Joi.string().required(),
});
 
// Example validation to use on 'update'
PostApi.validate.update({
  title: Joi.string(),
  content: Joi.string(),
});

See hapi's validation tutorial for more information.

Mount routes on hapi

Api.all();

Get all routes

Api.index(config, schemeOverride, callback);

Get route for index

  • config object (optional)
  • schemeOverride function (optional) - overrides scheme
    • function(Model, request, done)
  • callback function (optional)
    • function(err, result, reply)
      • err - error from model
      • result - result from Model
      • reply - reply object of hapi

Api.show(config, schemeOverride, callback);

Get route for show

  • config object (optional)
  • schemeOverride function (optional) - overrides scheme
    • function(Model, request, done)
  • callback function (optional)
    • function(err, result, reply)
      • err - error from model
      • result - result from Model
      • reply - reply object of hapi

Api.save(config, schemeOverride, callback);

Get route for save

  • config object (optional)
  • schemeOverride function (optional) - overrides scheme
    • function(Model, request, done)
  • callback function (optional)
    • function(err, result, reply)
      • err - error from model
      • result - result from Model
      • reply - reply object of hapi

Api.update(config, schemeOverride, callback);

Get route for update

  • config object (optional)
  • schemeOverride function (optional) - overrides scheme
    • function(Model, request, done)
  • callback function (optional)
    • function(err, result, reply)
      • err - error from model
      • result - result from Model
      • reply - reply object of hapi

Api.destroy(config, schemeOverride, callback);

Get route for destroy

  • config object (optional)
  • schemeOverride function (optional) - overrides scheme
    • function(Model, request, done)
  • callback function (optional)
    • function(err, result, reply)
      • err - error from model
      • result - result from Model
      • reply - reply object of hapi
// mount routes
server.route(PostApi.all());
 
// same as...
server.route([
  PostApi.index(),
  PostApi.show(),
  PostApi.save(),
  PostApi.update(),
  PostApi.destroy(),
]);
 

Example above creates:

  • GET /posts
  • GET /posts/{id}
  • POST /posts
  • PUT /posts/{id}
  • DELETE /posts/{id}

Customizing specific routes

server.route([
  PostApi.index({
    /* can override any configuration here */
    tags: ['api', 'get'],
    auth: ['jwt'],
    // ...
  }, (Model, request, done) => {
    /* can override scheme for this route only */
    // Model = Model given as third param of 'new Holiday()'
    // request = request object of hapi
    // done = callback function to execute when done
  }, (err, result, reply) => {
    /* can customize replies and status codes here */
    // err = error of model
    // result = result of model
    // reply = reply object of hapi
  }),
  PostApi.show({
    /* can override any configuration here */
    tags: ['api', 'post'],
    auth: ['jwt'],
    // ...
  }, (Model, request, done) => {
    /* can override scheme for this route only */
    // Model = Model given as third param of 'new Holiday()'
    // request = request object of hapi
    // done = callback function to execute when done
  }, (err, result, reply) => {
    /* can customize replies and status codes here */
    // err = error of model
    // result = result of model
    // reply = reply object of hapi
  }),
 
  // ... and so on
]);

Adding a route for 1:1 or 1:n models

Api.has(resourceName, scheme);

Creates a new route under GET /modelName/{id}/resourceName

Cannot use index, show, save, update, destroy for resourceName

  • resourceName string (required) - name for the association
  • scheme function (required)
    • function(Model, request, done) {}
      • Model - error from model
      • request - request object of hapi
      • done - a function to execute when done.
        • done(err, result)
          • err - Error message or null
          • result - result of model
// This adds GET /posts/{id}/author
PostApi.has('author', (Models, request, done) => {
  Model.find({
    where: {id: request.params.id},
    include: ['Author']
  })
  .then((records) => {
    done(null, records);
  })
  .catch((err) => {
    done(err, null);
  });
});

Api.validate.resource[resourceName](validationObj);

Set validations for association routes.

Validation set with this method validates on request.query

// NOTE: always validate after executing Api.has()
PostApi.validate.resource.author({
  name: Joi.string(),
  // ...
});

Api.resource[resourceName](config, schemeOverride, callback)

Get route for association

  • config object (optional)
  • schemeOverride function (optional) - overrides scheme
    • function(Model, request, done)
  • callback function (optional)
    • function(err, result, reply)
      • err - error from model
      • result - result from Model
      • reply - reply object of hapi
// mount association route
server.route(PostApi.resource.author());
 
// all routes including resource gets mounted by using Api.all()
server.route(PostApi.all());

More examples...

var Hapi = require('hapi');
var Holiday = require('hapi-holiday');
var Joi = require('joi');
 
var server = new Hapi.Server();
server.connection({ port: 3000 });
 
Holiday.define('testScheme', {
  index: function(Model, request, done) {
    done(null, {test: 'index'});
  },
  show: function(Model, request, done) {
    done(null, {test: 'show', id: request.params.id});
  },
  save: function(Model, request, done) {
    done(null, {test: 'save'});
  },
  update: function (Model, request, done) {
    done(null, {test: 'update', id: request.params.id});
  },
  destroy: function(Model, request, done) {
    done(null, {test: 'destroy', id: request.params.id});
  },
});
 
var Api = new Holiday('testScheme', 'test', {a: 'model'});
 
Api.has('photo', function(Model, request, done) {
  done(null, {
    a: 'photo',
    name: request.query.name,
    someId: request.query.someId,
  });
});
 
Api.validate.resource.photo({
  name: Joi.string(),
  someId: Joi.number(),
});
 
server.route(Api.all());
 
server.start(function () {
  console.log('Server running at:', server.info.uri);
});
 
// GET http://localhost:3000/test
// will return...
// {
//   "test": "index"
// }
// with a status code 200 OK
 
// GET http://localhost:3000/test/11
// will return...
// {
//   "test": "show",
//   "id": 11
// }
// with a status code 200 OK
 
// POST http://localhost:3000/test
// will return...
// {
//   "test": "save"
// }
// with a status code 201 Created
 
// PUT http://localhost:3000/test/22
// will return...
// {
//   "test": "update",
//   "id": 22
// }
// with a status code 200 OK
 
// DELETE http://localhost:3000/test/33
// will return nothing with a status code 204 No Content
 
// GET http://localhost:3000/test/1/photo?name=nano&someId=100
// will return...
// {
//   "a": "photo",
//   "name": "nano",
//   "someId": 100
// }
// with a status code 200 OK
 
// GET http://localhost:3000/test/1/photo?name=nano&someId=hello
// will return...
// {
//   "statusCode": 400,
//   "error": "Bad Request",
//   "message": "child \"someId\" fails because [\"someId\" must be a number]",
//   "validation": {
//     "source": "query",
//     "keys": [
//       "someId"
//     ]
//   }
// }
// with a status code 400 Bad Request

Dependencies

dependencies

devDependencies

License

MIT

Dependencies (3)

Dev Dependencies (5)

Package Sidebar

Install

npm i hapi-holiday

Weekly Downloads

4

Version

0.4.6

License

MIT

Last publish

Collaborators

  • nanopx