A general purpose boilerplate for building APIs with hapi
In this example our project is called my-project 💧
$ curl -LOk https://github.com/devinivy/boilerplate-api/archive/master.zip
$ unzip master.zip
$ mv boilerplate-api-master/ my-project/
$ cd my-project/Now install the dependencies and start running the server 🌊
$ npm install
$ npm startIf everything goes well you should see this 🏄
> boilerplate-api@0.3.0 start /Users/maxfelker/my-project
> node server
Server started at http://0.0.0.0:3000Now your app is running at http://0.0.0.0:3000 🚰 hapi boiling!
Here are a list of tools we include in the project ![]()
| Name | Description |
|---|---|
| dogwater | Integrates the Waterline ORM |
| sails-disk | A local disk adapter for Waterline ORM |
| haute-couture | File-based hapi plugin composer |
| glue | Server composer for hapi.js |
| hoek | Node utilities shared amongst the extended hapi universe |
| joi | Object schema validation |
| bassmaster | Batch request plugin for hapi |
| boom | HTTP-friendly error objects |
| hapi-swagger | A Swagger interface for hapi |
| lab | Node.js test framework |
| labbable | No-fuss hapi server testing |
In this simple example, we're going show you how to setup an endpoint where we can get a list of dogs as well as
create and update dogs.
In order for the application to store and retrieve data from the database, we need to setup a model definition for dogs.
We place our model definition in lib/models/dogs.js. This model definition is simple - we'll
just save the name and type of dog for now.
We prefer model identities to be plural (e.g. dogs not dog) and dash-case (e.g. dog-houses not dogHouses or dog_houses). When possible, the filename containing a model definition should be named with the model identity, so lib/models/dog-houses.js will contain the dog-houses model definition. It should be noted that when dealing with Waterline, this means that you'll need to exercise special care when accessing models via request.collections() - fetching dog-houses requires you to type request.collections()['dog-houses'].
'use strict';
module.exports = {
identity: 'dogs',
connection:'diskDb',
attributes: {
name: {
type: 'string',
required: true
},
type: {
type: 'string',
required: true
}
}
};We need to create a route definition for our dogs. We do this by creating a file in lib/routes/dogs.js. haute-couture will find your plugin and start using it the next time the server is started.
We also prefer dash-casing of routes (e.g. dogs/change-houses not dogs/changeHouses) and the base of the route should be the same as the model identity (e.g. dogs/change-houses not dog/change-houses). When possible the route definitions should be in a file with the same name as the model the routes are interacting with, so lib/routes/dog-house.js will contain the routes for the dog-houses model.
Below you'll see a GET route that retrieves a list of dogs
by using dogwater to integrate with sails-disk DB. After that, we see a POST route that creates a dog with the specific type and name of the dog.
'use strict';
module.exports = [
{
method: 'get',
path: '/dogs',
config: {
tags: ['api'],
handler: (request, reply) => {
const Dogs = request.collections().dogs;
reply(Dogs.find());
}
}
},
{
method: 'post',
path: '/dogs',
config: {
tags: ['api'],
handler: (request, reply) => {
const Dogs = request.collections().dogs;
reply(Dogs.create({
type: request.payload.type,
name: request.payload.name
}));
}
}
},
];With both of these files in place, restart your server and browse to the dogs http://0.0.0.0:3000/dogs 🐶 You should get back an empty array.
Time to make a dog! Make a POST request to the dogs endpoint:
curl --data "name=Gus&type=Leonberger" http://0.0.0.0:3000/dogsNow browse back to http://0.0.0.0:3000/dogs and you should get a response like this:
[
{
"type":"Leonberger",
"name":"Gus",
"createdAt":"2016-06-15T15:11:58.477Z",
"updatedAt":"2016-06-15T15:11:58.477Z",
"id":1
}
]With hapi-swagger, it's easy to see your new routes, docs and test out what you just built:
