Building RESTful Api With Node.js, Express.Js And PostgreSQL the Right way
By: Blessing Krofegha
Tags: Postgresql, API, Nodejs, Expressjs, Jwt

After my article about “Generating a Pdf with Nodejs and Cloudinary” i got few feedbacks from folks requesting that i write an article on Building RESTful Api’s with NodeJs. So i decided to put this piece with the hope that it will help somebody.

What we will build?

You’ll learn how to build a public bus transportation booking API — Such that Users book tickets for their trips, can see all their bookings and have the right to cancel any booking.

The only impossible journey is the one you never begin. 🙌— Tony Robbins

Table of Content

Getting Started

Prerequisite

Project Setup

Project Structure

Setting up Database(PostgrelSQL)

Server Helpers

Authentication & Authorization with JWT

Setup Controllers

Setup Routes

Server Setup

Testing with POSTMAN

Conclusion

Getting Started

In this post, I’ll explain how to connect and use PostgreSQL Database to store data. We will also learn how to write some basic [SQL](Structure Query Language) queries. SQL is a standard language for storing, manipulating and retrieving data in databases. To make this simple and so that we can have a better understanding of how SQL works, I’m not going to make use ORM(Object Relational Mapping) in this post. Check out this answer on stackoverflow to get a better understanding of ORM. ORM is basically a technique that allows us to query and manipulate data from the database with little knowledge of SQL. ORM packages expose some methods needed to query and manipulate the data in the database. We have several ORM packages that could be used with our database e.g Sequelize. Instead of using an ORM, we will use PG NodeJS package directly — PG is a NodeJs package for interfacing with the PostgreSQL database. Using PG alone will also give us the opportunity to understand some basic SQL queries as we will be querying and manipulating data in the DB using raw SQL queries.

Prerequisite

Although I’ll try to keep things simple. However, having some basic Knowledge about Nodejs before diving into this Tutorial is important, this post assumes that you have Nodejs and Npm installed in your PC, if you don’t kindly follow this guide.

Project Setup

Create a new project directory on your system, you can call it transportApi

Change working directly to the project and run npm init on your terminal or command prompt if you're using a window system - Running npm init will prompt you with some questions to help set up your project

When that is done, you should see package.json file in your project and it contains basic information about your project.

{ "name": "transportapi", "version": "1.0.0", "description": "", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Beveloper", "license": "ISC" }

Installation of all dependencies for the project:

We are going to install the required dependencies needed for this project no fancy external packages e.g Morgan e.t.c.

expressjs — Expressjs is a nodejs web application framework that gives us the ability to create quick and easy APIs.

PG— PG is a NodeJs package for interfacing with the PostgreSQL database.

JSON Web Token (JWT)— is an open standard for securely transmitting information between parties as a JSON object. It’s pronounced jot, or as our Dutch friends would say, yaywaytay. JWT is commonly used for authorization. JWTs can be signed using a secret or a public/private key pair. Once a user is logged in, each subsequent request will require the JWT, allowing the user to access routes, services, and resources that are permitted with that token.

Body Parser — Parse incoming request bodies in a middleware before your handlers, available under the req.body property.

property. Moment — Is a lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.

Dotenv — Is a zero-dependency module that loads environment variables from a .env file into process.env

file into CORS (Cross Origin Resource Sharing) — Is a node.js package that allows requests to skip the Same-origin policy and access resources from remote hosts.

Bcryptjs — is a secured way to help you hash passwords.

@babel/polyfill — is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.

to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments. babel watch — This is needed for development. One thing that babel watch package does is to compile our code and reload the server each time we make changes to our code.

Run the following command to install all the above packages

$ npm install --save express pg moment body-parser dotenv jsonwebtoken cors make-runnable bcryptjs npm install --save express pg moment body-parser dotenv jsonwebtoken cors make-runnable bcryptjs @babel/polyfill npm-run-all $ npm install --save-dev babel-core babel-cli babel-preset-env babel-watch babel-preset-es2015 babel-register

If all went well, you should see something similar to this

You’ll notice that express and moment etc is under dependencies , that is because those are needed by the time we deploy our code to production. babel-cli, babel-preset-env and babel-watch etc are only needed during development.

Project Structure

Install PostgreSQL on your system. If you don’t have it installed on your PC walk through this guide

Set up your project structure using the following format;

TransportApi |-app

|-controllers

|-db

|-helpers

|-middlewares

|-routes

|-node_modules

|-.babelrc

|-.env

|-env.js

|-package-lock.json

|-package.json

|-server.js

Set Up Database

Lets create our DB and name it transportApi . To create the DB, we can make use of any PostgreSQL client such as POSTICO for Mac Users or PgAdmin4 for window users.

If you need a guide on out to setup PostgrelSQL on your PC checkout this easy to read guide

Create TransportApi Table

First, let save our Database URL in the system environment. Your Database URL should be in the following format

postgres://{db_username}:{db_password}@{host}:{port}/{db_name}

e.g postgres://transportUser:develop@localhost:5235/transport

If you were unable to set your DB locally, the easy way out is to make use of any PostgreSQL cloud DB such as ElephantSQL. If you use cloud PostgreSQL DB, copy the URL and use it instead.

My port may differ from yours, so ensure you use the correct p.

ENVIRONMENT VARIABLE SETUP

Open the .env file located in the root directory, copy and paste the codes into it.

#.env DATABASE_URL=postgres://transportUser:develop@localhost:5235/transport PORT=5253

We defined a few environment variables ( DATABASE_URL AND PORT ) so we can use them later across our project.

Next, we need to create transportApi table in our DB. This is where we will start making use of pg package with basic SQL query to create the table.

Inside our db folder create a folder called dev and create three files named dbConnection.js, dbQuery.js and pool.js respectively.

The files should look like this.

Code Steps:

Import Pool object from pg . Check pg documentation to read more on pooling . We use this to connect to our PostgreSQL Db. Pool is the easiest and common way of using pg. You can also make use of their Client API to connect to the DB.

object from . Check pg documentation to read more on . We use this to connect to our PostgreSQL Db. Pool is the easiest and common way of using pg. You can also make use of their Client API to connect to the DB. Import dotenv from dotenv and load it using dotenv.config() - what this does is to search for .env file in our project and load its content into the system environment so we can use node process.env to access those variables.

from and load it using - what this does is to search for file in our project and load its content into the system environment so we can use node to access those variables. We create a new instance of Pool and pass in connectionString to its constructor. We use process.env.DATABASE_URL to get DATABASE_URL variable from the system environment.

and pass in to its constructor. We use to get variable from the system environment. We listened to pool connect event and console log connected to the db

Code Steps:

We created a new method query that takes in two arguments text - query text and params - values required by text . These two arguments are what is needed to query the DB. The method returns a promise and we will call it in our controller. Click here to read more about JavaScript Promise.

Code Steps:

Import Pool object from pg . Check pg documentation to read more on pooling . We use this to connect to our PostgreSQL Db. Pool is the easiest and common way of using pg. You can also make use of their Client API to connect to the DB.

object from . Check pg documentation to read more on . We use this to connect to our PostgreSQL Db. Pool is the easiest and common way of using pg. You can also make use of their Client API to connect to the DB. We listened to pool connect event and console log connected to the db

event and console log We set up a createTables() function, inside the function is a query that creates userTbale, busTable, tripTable and bookingTable respectively with unique fields.

const createUserTable = () => { const userCreateQuery = `CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, email VARCHAR(100) UNIQUE NOT NULL, first_name VARCHAR(100), last_name VARCHAR(100), password VARCHAR(100) NOT NULL, created_on DATE NOT NULL)`;

What the above does is to tell PostgreSQL DB to create users table if users table does not exist with fields listed and the same goes for the rest of the tables respectively.

Using the first Table(usersTable) as Case study, we observe the following;

We call pool query method with userCreateQuery as an argument and it returns a promise .

We called pool.end() to close pool connection to the db.

query method with as an argument and it returns a . We called to close connection to the db. We created another function called dropTables() - What this does it to delete users table.

We set up a new query DROP TABLE IF EXISTS users , that drops users table if it exists in the DB.

- What this does it to delete table. We set up a new query , that drops users table if it exists in the DB. We use pool.on('remove') to listened to pool remove event and use process.exit(0) to exit the node process.

to listened to event and use to exit the node process. Lastly, we require make-runnable package - We need this to be able to call and any of our two functions from the terminal.

Note: You have to require make-runnable at the end. Remember we’d earlier installed make-runnable as a project dev-dependency.

You'll also notice that we used require instead of import , this is because we only want to run db.js file from the terminal alone and it is not directly part of our project so there is no point in compiling it.

Finally, lets run createTables function to create our tables. To do this we need to add a command in our Package.json file.

In your start script remove the test command and add this

"scripts": { "create-dev-tables": "babel-node ./app/db/dev/dbConnection createAllTables", "start": "nodemon --watch . --exec babel-node -- server", "setup": "npm-run-all -p start create-dev-tables" },

Your package.json should know look like this

Next, we run the command $ npm run setup

After running the above, you should see something similar below;

NOTE: Instead of going through the above process, you can also create tables directly either using any PostgreSQL client e.g pgAdmin, POSTICO or using PostgreSQL commands on the terminal.