How to build APIs using hapi.js in Node.js

By reading this tutorial you can build RESTful APIs using Node, hapi.js, and Sequelize ORM. We gonna use the different HTTP methods during the REST API development, quick introduction to each method and route details along with the description of each endpoint you can find in the below table.

# Route Method Description
1 /todos GET Get all todos data
2 /todo/{id} GET Get a single todo data
3 /create POST Create new todo record in database
4 /update/{id} PUT Update an todo record
5 /delete/{id} DELETE Delete an todo record
6 /todos/search/{term} GET Search for todo, ex: php

Each method as a purpose isn’t it?. Let me give an introduction to the app which you are going to build is a TODO application. You can add a todo to list, update, delete todos and you can even search for todos.

Install sequelize-cli

Following npm command installs sequelize-cli globally. It means you can access from anywhere via terminal.

npm install -g sequelize-cli

Project setup

Lets create a folder for the project, for example todo-app. And change the directory to newly created directory(Ex: todo-app) and issue npm init --yes command to generate package.json in your project folder. Once it is done, then install the project npm depencies called hapi, mysql2, sequelize with follging command npm install hapi mysql2 sequelize

Command which we have exectired in the preceeding text

$ mkdir todo-app
$ cd todo-app
$ npm init --yes
$ npm install hapi mysql2 sequelize

And your final package.json file should look something like below shown

{
  "name": "hapijs-reset-api",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "hapi": "^17.5.5",
    "mysql2": "^1.6.1",
    "sequelize": "^4.38.1"
  }
}

Initializes sequelize

let use the Sequelize CLI to generate migrations, seeders, config and models directories and config file.

$ sequelize init // Initializes project with sequelize cil

Ternamil output:
Sequelize CLI [Node: 8.11.1, CLI: 4.1.1, ORM: 4.39.0]
Created "config/config.json"
Successfully created models folder at "/Volumes/projects/workspace/todo-app/models".
Successfully created migrations folder at "/Volumes/projects/workspace/todo-app/migrations".
Successfully created seeders folder at "/Volumes/projects/workspace/todo-app/seeders".

After executing sequelize init command, your folder structure should be similar to below shown

hapi js rest tutorial | arjunphp.com

If you are windows user correct the config file path in models/index.js by changing
var config = require(__dirname + '/..\config\config.json')[env]; to var config = require(__dirname + '/../config/config.json')[env];

Database Configurations

Now config.json file which is located at config\config.json and updates your database details

{
  "development": {
    "username": "root",
    "password": "",
    "database": "arjunphp_node_rest",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
.......
.......
  },
  "production": {
.......
.......
  }
}

Create Models and Migrations

Again we gonna use sequelize cli command to generate model and migrations files.

sequelize model:create --name Todo --attributes title:string,description:string

Terminal output:
New model was created at /Volumes/projects/workspace/todo-app/models/todo.js .
New migration was created at /Volumes/projects/workspace/todo-app/migrations/20180928035740-Todo.js .

Above command generates a todo.js file in the PROJECT_ROOT/models folder as well as a -create-todo.js migration file in the PROJECT_ROOT/migrations folder. will be the date the model was generated.

Create Models and Migrations ArjunPHP

PROJECT_ROOT/models/todo.js

Here is the generated model code, you can add or remove columns to it, make sure to update migration file as for your changes on this model.

'use strict';
module.exports = function(sequelize, DataTypes) {
  var Todo = sequelize.define('Todo', {
    title: DataTypes.STRING,
    description: DataTypes.STRING
  }, {
    classMethods: {
      associate: function(models) {
        // associations can be defined here
      }
    }
  });
  return Todo;
};

PROJECT_ROOT/migrations/20180928035740-create-todo.js

Here is the generated migration code, you can add or remove columns to it, make sure to update model file as for your changes on this migration file.

'use strict';
module.exports = {
  up: function(queryInterface, Sequelize) {
    return queryInterface.createTable('Todos', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      title: {
        type: Sequelize.STRING
      },
      description: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: function(queryInterface, Sequelize) {
    return queryInterface.dropTable('Todos');
  }
};

Run Migrations

You can create database tables by running migrations with:

sequelize db:migrate

That’s it, now you can check your database, you should able to see new tables in your database.

Implementing the API calls with HapiJs

Create a file called server.js in the project root folder with below code:

const Hapi = require('hapi');

const server = Hapi.server({
    port: 3000,
    host: 'localhost'
});

const routes = require('./routes');
server.route(routes);

const init = async () => {

    await server.start();
    console.log(`Server running at: ${server.info.uri}`);
};

process.on('unhandledRejection', (err) => {
    console.log(err);
    process.exit(1);
});

init();

Now create a folder called routes in the root of the project along with index.js file and place following code inside it.

const todos = require('./todos');
module.exports = [].concat(todos);

Now create a file called todos.js as imported in routes/index.js file and copy following code to it.

const Models = require('../models/index')

const todosHandler = async (request, h) => {
    try {
        const todos = await Models.Todo.findAll({})
        return { data: todos }
    } catch (error) {
        return h.response({ error: error.message }).code(400)
    }
}

const createTodoHandler = async (request, h) => {
    try {
        const { title, description } = request.payload;
        const todo = await Models.Todo.create({
            title: title,
            description: description
        })
        return {
            data: todo,
            message: 'New todo has been created.'
        }
    } catch (error) {
        return h.response({
            error: error.message
        }).code(400)
    }
}

const updateTodoHandler = async (request, h) => {
    try {
        const todo_id = request.params.id;
        const { title, description } = request.payload;
        const todo = await Models.Todo.update({
            title: title,
            description: description
        }, {
                where: {
                    id: todo_id
                }
            })
        return {
            message: 'Todo has been updated.'
        }

    } catch (error) {
        return h.response({
            error: error.message
        }).code(400)
    }
}

const deleteTodoHandler = async (request, h) => {
    try {
        const todo_id = request.params.id;
        await Models.Todo.destroy({
            where: {
                id: todo_id
            }
        })
        return { message: 'Todo has been deleted.' }
    } catch (error) {
        return h.response({
            error: error.message
        }).code(400)
    }
}

module.exports = [
    { method: 'GET', path: '/todos', handler: todosHandler },
    { method: 'POST', path: '/todo', handler: createTodoHandler },
    { method: 'PUT', path: '/todo/{id}', handler: updateTodoHandler },
    { method: 'DELETE', path: '/todo/{id}', handler: deleteTodoHandler }
];

That’s it, hapi.js Rest server is ready, you can start the server with node server.js and you can access it at http://localhost:3000 as metioned in server.js file.

I hope you like this Post, Please feel free to comment below, your suggestion and problems if you face - we are here to solve your problems.

DMCA.com Protection Status