hapi-holiday
v0.4.6
Published
Rapidly create REST API with hapi
Downloads
4
Maintainers
Readme
hapi-holiday
Create REST API with hapi
Usage
$ npm install hapi-holiday --save
- Configures hapi-swagger by default
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 definedrouteName
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
- function(err, result, reply)
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
- function(err, result, reply)
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
- function(err, result, reply)
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
- function(err, result, reply)
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
- function(err, result, reply)
// 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 associationscheme
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
- done(err, result)
- function(Model, request, done) {}
// 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
- function(err, result, reply)
// 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