Design a solid MVC REST API with node.js express and ORM Part 1

Create a functional and reusable template that will save you time.

Recently I had a home assignment as a part of a job interview, and I was asked to create a REST API. I wanted to build a solid REST API with best practices and a well-organized structure using sequlize as ORM with SQL database. So I ended up creating this template I wanted to share with you.

Sometimes creating such apps requires a lot of configurations and different libraries. It was vital for me to understand each stage and configuration and to be able to explain them to my interviewer in case I am asked to. In this guide, I will try to explain every step in the process rather than just posting CLI commands and add a little background before each step.
This article is pretty basic, so if you are already familiar with CRUD, REST, and ORMs, you can jump to the git project straight away or go over the parts you need from this article.

What will we cover up?

I will split this guide into two parts.

  1. Basic Infrastructure:
  • Create the app.
  • Define folder structure.
  • Implement REST API.
  • Test our API with Postman.

2. Database and MVC.

  • Add logs to our server.
  • Add configuration file and .env file.
  • Add DB connection (SQL).
  • Add ORM to our project (sequelize).
  • Define controllers and Models.

Prerequisites

  • Node.js installed on your machine- download from here (I’m using version 12+)
  • Your favorite IDE (I’m using Intellij).
  • npm -node package manager installed (yarn is fine too but I’ll be using npm commands).
  • Postman-like app for testing our API.

If you want to understand better what a Restful API is and how you should implement it, I recommend you read my following article restful API explained.

Let’s get started…

1. Create a Node app

First, let’s create a folder and open our CLI there.
I named my mvc-rest-api.
Now we want to create our package.json file. use the following command

npm init -y

the -y will create the file without asking any questions using our folder as the project name.

Now let’s add our web framework express

npm install express

express will help us create a robust API within an easy and flexible way and allow us to utilize middleware.

Next we want to add nodemon

npm install --save-dev nodemon

Nodemon is a tool that helps develop node.js based applications by automatically restarting the node application when file changes in the directory are detected.

2. Create our folder structure

  • Create src folder in our root folder.
  • Inside src folder create index.js file and routes folder.
  • Inside routes folder we will create a route for a resource named users by creating a users.js file.
it should look like this

Now let’s edit our package.json,

  • Change “main” to point to our API’s entry point by pointing it to:
"main": "./src/index.js",
  • Add start command that will execute our code:
"scripts": {
"start": "nodemon",
}

Start will run when we’re using the npm start command in CLI.

it should look like this:

// package.json{
"name": "mvc-rest-api",
"version": "1.0.0",
"description": "",
"main": "./src/index.js",
"scripts": {
"start": "nodemon",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"nodemon": "^2.0.3"
}
}

3. Implementing our API

Initiate express framework by editing index.js file

//src/index.jsconst express = require('express');
const app = express();

const PORT = 3000;


function onStart(){
console.log(`Server running on port ${PORT}`);
}

app.listen(PORT, onStart);

module.exports = app;

Add some middleware

Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle. The next middleware function is commonly denoted by a variable named next.

Middleware functions can perform the following tasks:
* Execute any code.
* Make changes to the request and the response objects.
* End the request-response cycle.
* Call the next middleware function in the stack.

If we want our API calls to accept JSON content, we need to add some middleware to make it work.

//src/index.js
...
const PORT = 3000

/**
* Express middleware.
*/
// parses incoming requests with JSON payloads
app.use(express.json());
// parses incoming requests with urlencoded payloads
// extended: true - parsing the URL-encoded data with the querystring library
app.use(express.urlencoded({extended: true}));
...

You can now try run the app by using the following command:

npm start

If you get a Server running on port 3000 in your CLI, you’r code works great!

Adding routes

Express Router is also a middleware that allows us to make our routes neat and modular.
Let’s create our user route:

//src/routes/users.jsconst router = require('express').Router();router.route('/users')
// to create new resources
.post(function(req, res, next) {

})
// to retrieve resource
.get(function(req, res, next) {

})
;
router.route('/users/:userId')
// to retrieve a single resource
.get(function(req, res, next) {

})
module.exports = router;

First, we get our router from express, then we use the route function to state that a URL of the host followed by /users or /users/1 will end up using this route and return whatever we will return in this function as an HTTP response body (res).
The req parameter will represent our user HTTP request.

Next, we want to add the router middleware to our app. go ahead and edit index.js and add the following code:

//src/index.js...
const PORT = 3000;
/**
* Routes.
*/
const usersRouter = require('./routes/users');
...
// Add this after the middleware part
app.use('/api', usersRouter);

After the last middleware, adding app.use(‘/api’, usersRouter) is crucial. Those middleware mini-apps are running sequentially, and if we process one before the other, it will not always work as expected.

This part tells express to create the following URL path:

localhost:3000/api/users

We are adding the /api/ just so it’s clear we are communicating with a RESTful API it is also possible to add versioning to the URL path like so:

localhost:3000/api/v1/users

4. Now lets test our API.

Testing our API will require some data to pass from the browser to our server and the other way around. I will add some logs and dummy data to the post and get the functions that we’ve implemented.

//src/routes/users.js...const usersData = {
1: {id:1, firstName: 'Ralph', lastName: 'Woods'},
2: {id:2, firstName: 'Ronnie', lastName: 'Moore'},
3: {id:3, firstName: 'Koko', lastName: 'Kennedy'}
}
router.route('/users')
// to create new resources
.post(function(req, res, next) {
// Return our request body and return status OK
res.json(req.body).status(200).send();
})
// to retrieve resource
.get(function(req, res, next) {
// Respond with some data and return status OK
res.json(usersData);
res.status(200).send();
});
router.route('/users/:userId').get(function(req, res, next) {
const id = req.params.userId;
if(id && usersData[id]) {
res.json(usersData[id]);
res.status(200).send();
} else {
// Not Found
res.status(404).send();
}
})
...

I use Postman to generate an HTTP GET request to our API.
the URL we should turn to is localhost:3000/api/users
Our HTTP verb should be GET (blue marker).

Get all resources

As you can see, we get from our API the dummy JSON that we added and a status code of 200.

Let’s proceed to our POST request.
We need to change our HTTP verb to POST, and our URL stays the same.
Add a JSON to your request body and ensure that your request is set to JSON; otherwise, express might not process your request.

Since we are returning the body of our request, this POST request should result in a response JSON that contains whatever you put on the request, just like I got in this screenshot.

Last part, GET for a single id:

That’s it for this part, we understood REST, CRUD principles and created a Node.js app with express and a basic route to our users resource.
In the next part, I will add a DB connection, ORM and create Models and controllers that will make our API comply with the MVC design pattern.

Thanks for reading!

Software Developer