How to build a REST API using Expressjs

In this tutorial, you will learn how to perform CRUD operations on two resources using REST, Express.js, PostgreSQL, and Sequelize ORM.

PREREQUISITES

  • A code and text editor

  • Pgadmin installed

  • Basic understanding of Node.js framework

  • Basic understanding of error handling, error codes, and request types

  • Understanding of environment variables

PROJECT SETUP

The very first step in building an application, especially for backend systems, is System Design.

It is the what and how of your project. ‘What am I building?’, ‘How will I build it?’, ‘What do I need?’ ‘What method or approach will I use for this requirement?’

For this article, you will be building a 'Politico' App. What does this app do? Well, it allows you to create your political parties and offices!

This is a simple, straightforward tutorial, teaching the basics of REST. Thus, there will be no extra logic for user authentication and authorization.

To achieve this project, you need to interact with a database for the storage of political offices and party records. You also need a framework for writing the server code and, finally, a tool for making SQL queries easier.

For this project, Postgres will be used for the database, Express.js framework for the server, and Sequelize ORM for SQL transactions.

We've now familiarized with the whys and hows.

What's next?

The next step in system design after requirements gathering is the database design and modeling.

DATABASE

Setting up your Sequelize configurations. This can be in your app.js file or a separate database.js file. It really depends on your preference. Personally, I’d go with a separate database file. It helps modularize your code. Copy and paste this code in the config file of your choice:

const { Sequelize } = require("sequelize");
require("dotenv").config();

const sequelize = new Sequelize(
  process.env.DB_NAME,
  process.env.DB_USER,
  process.env.DB_USER_PASSWORD,
  {
    host: process.env.DB_HOST,
    dialect: "postgres",
    storage: "./db.sqlite",
    logging: console.log,
  },
);

async function connect() {
  try {
    await sequelize.authenticate();
    await sequelize.sync({force: true});
  } catch (err) {
    console.log(err);
  }
}

module.exports = {sequelize, connect};

P.S., exporting the module is not needed if the code is already in your app.js file

Now that you’ve got the boring stuff out of the way, you can set up your database schemas! Create a folder named models and two files within that folder: Offices.js and Party.js.

The office table should have the following fields: ID(an auto-incremental integer) and Name(a string)

The Party table should have these fields: ID, partyName, acronym, and slogan. All fields other than ID will be of type STRING. The ID field here will have the same attributes as the ID field in the office table.

Once you're done, your Party model should look like this(don’t forget to import the sequelize configurations!)

const { Sequelize, DataTypes, Model } = require('sequelize');
const { sequelize } = require("../config/db.js");

class Party extends Model {}

Party.init(
  {
    id: {
         type: DataTypes.INTEGER,
         autoIncrement: true,
         primaryKey: true,
       },
    partyName: {
      type: DataTypes.STRING,
      unique: true,
      allowNull: false,
            },
    acronym: {
      type: DataTypes.STRING,
      unique: true,
      allowNull: false
    },
    slogan: {
      type: DataTypes.STRING,
      allowNull: false,
    }
  },
  {
    sequelize,
    modelName: 'Party',
  },
);


module.exports = Party;

The code for the Office model should be fairly similar to the code for the Party model.

To verify your database setup is working correctly, open up your pgAdmin and create a new database under Servers. This database should have the credentials you set while configuring your Sequelize ORM for PostgreSQL(name, user)

Once that database is created, navigate to the tables section in Schemas. Nothing is available, right? To view your created tables, run your express server and refresh the tables. Your table view should now look like this

And that's it! Your database is set up and ready to be used for transactions.

ROUTES

Before writing any code, you must identify all possible route definitions for our operations. You will be performing CRUD operations for both offices and parties. In a text editor, define how you want these routes to look. They should look similar to these:

Party

POST('/party')

GET('/party/:id')

GET('/party/:id')

PATCH('/party/:id')

DELETE('/party/:id')

Office

POST('/office')

GET('/office/:id')

GET('/office/:id')

PATCH('/office/:id')

DELETE('/office/:id')

Next up, create a routes folder in your Express project folder. Two files, Party.js and Office.js.

Add the skeleton setup for a routerfile. That is, importing and exporting the express router and importing the required model from the models folder

In your routes, create an async function with try and catch blocks within.

router.post('/party', async(req,res,next)=>{
try{
//application logic
}
catch(err){
//deal with any internal server error
}
});

Now it's time for the CRUD LOGIC

POST

This request handles the create functionality for a party/office. To create a new entity, use Sequelize’s create() function. Let's say you were creating a new party, your code should look similar to this.

router.post('/party', (req, res, next)=> {
  try {
    const party= await Party.create(req.body);
    res.json({status: 201, message: party});
  } catch (error) {
    res.json({status: 500, message: error.message });
  }
});

GET

This allows you to retrieve all available entities of that entity type in the database. This is done using the FindAll() function in Sequelize. Your code should mimic this

router.get('/party', async(req, res, next)=> {
  try {
     let parties = await Party.findAll();
     let code = 200;
     if (parties.length === 0) {
        code = 204;
     }
     res.json({status: code, message: parties });
  catch (error) {
    res.json({status: 500, message: error.message });
  }
});

GET by ID

This allows you to retrieve a single entity of a type using its ID. The id can be accessed using req.params. The FindOne() function is used here.

router.get('party/:id', async(req, res, next)=> {
  try {
    let party= await Party.findOne({where: {id: req.params.id}});
    if (!office) {
      return res.json({status: 404, message: 'party not found' });
    }
    res.json({status: 200, message: office });
  } catch (error) {
    res.json({status: 500, message: error.message });
  }
});

PATCH

This is for updating a single or multiple fields under a record by its ID. A user will submit a form on the frontend to update a specific field. Through express.json() and express.urlencoded(), this form is parsed as a JSON object to the backend endpoint. You can now access the submitted fields using req.body.

To patch an existing record, the update() function is used here.

router.patch('/party/:id', async(req, res, next)=>{
  try {
    let party = await Party.update(req.body, {where: {id: req.params.id}});
    res.json({status: 200, message: party });
  } catch (error) {
    res.json({status: 400, message: error.message });
  }
});

DELETE

Finally, to delete a record by a specific ID, the Sequelize delete() function is used.

router.delete('/party/:id', async(req, res, next)=>{
  try {
    let party = await Party.destroy({where: {id: req.params.id}});
    res.json({status: 204 });
  } catch (error) {
    res.json({status: 500, message: error.message });
  }
});

TESTING

Once you've completed the routing logic for both parties and offices, you can now test each endpoint. Postman will be used for this article, but you are free to use curl or even set up a frontend within your ExpressJS app!

For every route other than the patch and post, you can simply append the route definition to http:/localhost:PORT/. For example, the get all parties endpoint in Postman should look like this

For the case of PATCH or POST, first navigate to the headers tab. Set the Content-Type To application/json. Navigate to the body tab and select raw. Then pass the JSON object. Your request and response should look like this:

There you have it! Now you can easily set up a simple REST API for two resources using PostgreSQL as the database and Sequelize ORM for query transactions.

0
Subscribe to my newsletter

Read articles from Tiffany Ugwunebo directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Tiffany Ugwunebo
Tiffany Ugwunebo