# Mastering REST API Development with Node.js and Sequelize ORM

## ***STEP 0*: *Creating an empty Nodejs repository***

Go to your desired directory and run the below command to setup an empty directory with **package.json**

```bash
npm init -y
```

## *STEP 1: Creating a server*

To create an express server we have to install [**express**](https://www.npmjs.com/package/express)

### *STEP 1.1: Installing Express*

```bash
npm i express
```

the above command will install the express library to your project.

### *STEP 1.2: Setting up the server*

Create a new javascript file - you can name it anything, for the sake of simplicity let's call it **server.js** A node server can be set up by just three lines of code as

```javascript
const express = require("express");
const app = express();

app.listen(3000, () => {
    console.log(`App is up and running at port 3000`);
})
```

### *STEP 1.3: Install and configure dotenv*

we will be using some high confidentiality passwords/keys in the project, so it will be beneficial to not save them as such in the project but to create a non-versioned file and store them in that.

to have this kind of feature we have to install [**dotenv**](https://www.npmjs.com/package/dotenv)

```bash
npm i dotenv
```

after that create a **.env** file in your project and for now, add the value of PORT there, we will use the value of port from there.

**.env** will look something like this, it stores data in key-value format.

```bash
PORT=1667
```

now to use this value of PORT from **.env**, we have to configure dotenv in the **server.js** file and use the value.

```javascript
const express = require("express");
// This line is setting up the .env so that we can use it in our code
require("dotenv").config();

const app = express();
const port = process.env.PORT // This is how we can use it

app.listen(port, () => {
    console.log(`App is up and running at port ${port}`);
})
```

## *STEP 2: Sequelize and MySQL*

### *STEP 2.1: Installing Sequelize and mysql2*

we will be downloading two npm packages that will help us use MySQL with nodejs, they are - [sequelize](https://www.npmjs.com/package/sequelize) and [mysql2](https://www.npmjs.com/package/mysql2)

```javascript
npm i sequelize mysql2
```

### *STEP 2.2: Creating a database on the local machine*

Depending on how you are managing the SQL Server on your machine, the steps for creating a new database may vary.

If you are running SQL Server on Windows using XAMPP, you can create a new database by following the instructions provided in the [link](https://www.javatpoint.com/creating-mysql-database-with-xampp).

However, if you are using Ubuntu or Mac, you will need to follow these steps

1. Open Terminal and open your SQL server using this command
    
    ```bash
    mysql -u root -p
    ```
    
2. You will be prompted to write a password, write your SQL server password, and you will be inside the SQL server.
    
3. now create a database using this command
    
    ```sql
    CREATE DATABASE demon_slayer;
    ```
    

### *STEP 2.3: Configuring Sequelize*

open **.env** and add the database credentials that we have just created above, **.env** will look something like this

```bash
PORT=1667

DATABASE=demon_slayer
USERNAME=root
HOST=127.0.0.1
DIALECT=mysql
PASSWORD=**********
```

Create a new folder named **configs**. Inside the **configs** folder, create a new file named **index.js**. In this file, you will set up sequelize so that it can be used throughout the project.

```javascript
const { Sequelize } = require('sequelize');

// creating a new sequelize object by the name of DB
const db = new Sequelize(process.env.DATABASE, process.env.USERNAME, process.env.PASSWORD, {
    host: process.env.HOST,
    dialect: process.env.DIALECT
})

// authenticating the db, so that it can be connected to the local DB // that we have made.
try {
    db.authenticate();
    console.log(`database connected 💪`);
} catch(error) {
    console.error(`database connection failed: ${error}`)
}

module.exports = db;
```

## *STEP 3: Models*

### *STEP 3.1: Creating the Model*

Models are an essential part of Sequelize. They represent the structure of a table for a particular entity.

To create a new model, let's create a **models** folder in our project directory. Inside this folder, create a new file called **Hashira.js**. The model for this entity should look something like this

```javascript
// This is a standard way of declaring a model.
// Datatypes are required from sequelize package, and db is the 
// sequelize object that we instantiated above.

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

const Hashira = db.define('Hashira', {
  name: {
    type: DataTypes.STRING,
    allowNull: false
  },
  age: {
    type: DataTypes.INTEGER,
    allowNull: false
  },
  gender: {
    type: DataTypes.ENUM('Male', 'Female'),
    allowNull: false
  },
  breathing_technique: {
    type: DataTypes.STRING,
    allowNull: false
  }
}, {
  tableName: 'hashiras', // the name of table
  timstamps: true // it will add createdAt, updatedAt in tables
});

module.exports = Hashira;
```

Next, create another file called **index.js** in the same folder as your models. In this file, we will import all of our models and sync them with the database. The contents of this file should look something like this

```javascript
const Hashira = require("./Hashira");

Hashira.sync();
```

We now need to modify the code in **server.js** to only call the **index.js** file of the **models** folder. That's all that is required.

```javascript
require("dotenv").config();

const express = require("express");
// requiring index.js from models folder, which in turn sync the 
// tables with all the existing database
require("./models/index");

const app = express();
app.use(express.json());
const port = process.env.PORT

app.get("/", (req, res) => {
    res.send("Hello World");
})

app.listen(port, () => {
    console.log(`App is up and running at ${port}`);
})
```

## *STEP 4: Creating Routes and Controllers*

### *STEP 3.1: Creating the Controller*

The controller is the place where the basic logic resides, so create a **controller** folder and inside that folder create a file named **HashiraController.js**

```javascript
// These are the basic skeleton of all the methods that we will be 
// writing now, i.e. to create, update, get and delete Hashiras from 
// table.
const createHashira = async (req, res) => {}

const updateHashira = async (req, res) => {}

const getHashira = async (req, res) => {}

const getAllHashira = async (req, res) => {}

const deleteHashira = async (req, res) => {}

module.exports = {
    createHashira: createHashira,
    updateHashira: updateHashira,
    getHashira: getHashira,
    getAllHashira: getAllHashira,
    deleteHashira: deleteHashira
}
```

### *STEP 3.2: Creating the Route*

We will now create a new folder called **routes**. Inside this folder, we will create a new file named **HashiraRoute.js**. This file will contain all the APIs related to Hashiras. The code for this file should look something like this

```javascript
const express = require("express");
// fetching router from the express
const router = express.Router();

// fetching all the controller methods, to call and create API for 
// each one of them
const { 
    createHashira, 
    updateHashira, 
    getHashira, 
    getAllHashira, 
    deleteHashira 
} = require("../controllers/HashiraController");

router.post("/", createHashira);
router.put("/:id", updateHashira);
router.get("/:id", getHashira);
router.get("/", getAllHashira);
router.delete("/:id", deleteHashira);

// exporting the router as hashiraRoute so that it can be easily 
// identified in server.js
module.exports = {
    hashiraRoute: router
}
```

### *STEP 3.3: Server.js modification*

**server.js** will look something like this -

```javascript
require("dotenv").config();
const express = require("express");
const { hashiraRoute } = require("./routes/HashiraRoute");
require("./models/index");

const app = express();
const port = process.env.PORT

app.use(express.json());
// imported the route here - all the apis will have a prefix of 
// hashira.
app.use("/hashira", hashiraRoute);

app.listen(port, () => {
    console.log(`App is up and running at ${port}`);
})
```

## *STEP 4: Validations*

Validations are used to ensure that the data being sent to or retrieved from the server is accurate, complete, and conforms to a set of predefined rules or criteria.

We will be using [validatorjs](https://www.npmjs.com/package/validatorjs) in our project for this. It can be installed as follows -

```javascript
npm i validatorjs
```

To use this we will create a folder named validators, in that folder we will create separate files for each API, the getAll API would not need any validations, so skipping that.

### *STEP 4.1: The Create Validator*

create a file named **createHashiraValidator.js,** and define the rules for data of creating Hashira API

```javascript
const validator = require("validatorjs");

// creating a method which will take the incoming data and based on 
// rules, it will tell whether it is passed or failed. 
const createHashiraValidator = (data) => {
    return new validator(data, {
        name: "required|string",
        age: "required|integer",
        gender: "required|in:Male,Female",
        breathing_technique: "required|string"
    })
}

module.exports = createHashiraValidator
```

### *STEP 4.2: The Update Validator*

create a file named **updateHashiraValidator.js,** and define the rules for data of updating Hashira API

```javascript
const validator = require("validatorjs");

const updateHashiraValidator = (data) => {
    return new validator(data, {
        id: "required|integer",
        name: "string",
        age: "integer",
        gender: "in:Male,Female",
        breathing_technique: "string"
    })
}

module.exports = updateHashiraValidator
```

### *STEP 4.3: The get Validator*

create a file named **getHashiraValidator.js,** and define the rules for data of getting Hashira API

```javascript
const validator = require("validatorjs");

const getHashiraValidator = (data) => {
    return new validator(data, {
        id: "required|integer"
    })
}

module.exports = getHashiraValidator
```

### *STEP 4.4: The Delete Validator*

create a file named **deleteHashiraValidator.js,** and define the rules for data of deleting Hashira API

```javascript
const validator = require("validatorjs");

const deleteHashiraValidator = (data) => {
    return new validator(data, {
        id: "required|integer"
    })
}

module.exports = deleteHashiraValidator
```

## *STEP 5: Filling up the Controllers*

### *STEP 5.1: The Create Method*

This method will create a new Hashira in the database. The following steps should be followed

1. Get the request object from the API.
    
2. Validate the request object. If it is incorrect, throw an error.
    
3. Create a new database entry with the validated request object.
    
4. Return the response for the newly created Hashira.
    

```javascript
const createHashira = async (req, res) => {
    const payload = req.body;

    // everything wrapped inside try - catch to catch the error at 
    // each point
    try {
        const validator = await createHashiraValidator(payload)
        if (validator.fails()) {
            // return error code 422 and the errors along with it
            return res.status(422).json({ 
                error: validator.errors.all() 
            })
        }

        // code will be here only if passed the above validation

        // creating the database entry using the model created, since 
        // the request payload is similar to model keys, we can simply
        // pass the whole object inside create method of model.
        const hashira = await Hashira.create(payload);

        // return status code 200, and the newly created hashira
        return res.status(200).json({ data: hashira })
    } catch(e) {
        // return status code 500, and the error something went wrong
        return res.status(500).json({ error: `something went wrong` })
    }
}
```

### *STEP 5.2: The Update Method*

This method will update an existing Hashira in the database. The following steps should be followed

1. Get the request object from the API and the ID of the Hashira to be updated.
    
2. Check if a Hashira with that ID exists in the database. If it does not exist, throw an error.
    
3. Validate the request body. If it is incorrect, throw an error.
    
4. Update the database entry for the Hashira with the validated request body.
    
5. Return the response for the updated Hashira.
    

```javascript
const updateHashira = async (req, res) => {
    const payload = req.body;
    // adding the id of hashira in payload, so that it can also be 
    // validated.
    payload["id"] = req.params.id;

    try {
        const validator = await updateHashiraValidator(payload)
        if (validator.fails()) {
            return res.status(422).json({ 
                error: validator.errors.all() 
            })
        }

        // findByPk is used to find By primary key which is id
        const hashira = await Hashira.findByPk(payload.id)

        if (!hashira) {
            return res.status(422).json({ 
                error: `Hashira with given id does not exist in system` 
            })
        }
        
        // deleting the id from payload, because it is not updatable
        delete payload.id

        // updating the hashira with given payload
        await hashira.update(payload)
        return res.status(200).json({ data: hashira })
    } catch(e) {
        return res.status(500).json({ error: `something went wrong` })
    }
}
```

### *STEP 5.3: The Get Method*

This method will retrieve a Hashira from the database if it exists. The following steps should be followed

1. Get the ID of the Hashira to be fetched.
    
2. Check if a Hashira with that ID exists in the database. If it does not exist, throw an error.
    
3. Return the response for the requested Hashira.
    

```javascript
const getHashira = async (req, res) => {
    const payload = req.body;
    payload["id"] = req.params.id;

    try {
        const validator = await getHashiraValidator(payload)
        if (validator.fails()) {
            return res.status(422).json({ 
                error: validator.errors.all() 
            })
        }

        const hashira = await Hashira.findByPk(payload.id)

        if (!hashira) {
            return res.status(422).json({ 
                error: `Hashira with given id does not exist in system` 
            })
        }
        return res.status(200).json({ data: hashira })
    } catch(e) {
        return res.status(500).json({ error: `something went wrong` })
    }
}
```

### *STEP 5.4: The Get All Method*

This method will retrieve all Hashiras from the database. The following steps should be followed

1. Retrieve all Hashiras from the database.
    
2. Return the response with all the Hashiras.
    

```javascript
const getAllHashira = async (req, res) => {
    try {
        
        // findAll method will return all hashiras present in DB
        const hashiras = await Hashira.findAll()
        return res.status(200).json({ data: hashiras })
    } catch(e) {
        return res.status(500).json({ error: `something went wrong` })
    }
}
```

### *STEP 5.5: The Delete Method*

This method will delete a Hashira from the database if it exists. The following steps should be followed

1. Get the ID of the Hashira to be deleted.
    
2. Check if a Hashira with that ID exists in the database. If it does not exist, throw an error.
    
3. Delete the Hashira from the database.
    
4. Return the response indicating that the Hashira has been deleted successfully.
    

```javascript
const deleteHashira = async (req, res) => {
    const payload = req.body;
    payload["id"] = req.params.id;

    try {
        const validator = await deleteHashiraValidator(payload)
        if (validator.fails()) {
            return res.status(422).json({ 
                error: validator.errors.all() 
            })
        }

        const hashira = await Hashira.findByPk(payload.id)

        if (!hashira) {
            return res.status(422).json({ 
                error: `Hashira with given id does not exist in system` 
            })
        }

        // destroy method deletes the particular entity from DB
        await hashira.destroy();
        return res.status(200).json({ data: "deleted successfully" })
    } catch(e) {
        return res.status(500).json({ error: `something went wrong` })
    }
}
```

## *STEP 6: Time to test*

### *STEP 6.1: The Create Method*

***STEP 6.1.1: Success***

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682797807532/83aef960-25fa-4252-9e30-1a3a6ec7e47d.png align="center")

***STEP 6.1.2: Fail***

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682798101746/00ef05b1-1948-40e4-9990-e8d6d481b8d3.png align="center")

### *STEP 6.2: The Update Method*

***STEP 6.2.1: Success***

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682798230130/ee47d55e-3b45-4e04-91ea-0cd01599f40b.png align="center")

***STEP 6.2.2: Fail***

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682798261878/91c1a01c-6bfc-4c3c-af90-bee5a188ef2d.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682798305907/5bf45215-4b04-4c98-a3fe-35794bf438a5.png align="center")

### *STEP 6.3: The Get Method*

***STEP 6.3.1: Success***

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682798399107/6d625c35-2a46-4239-b564-35baebdc7f35.png align="center")

***STEP 6.3.2: Fail***

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682798406523/65dd4a13-69be-4ce6-80b6-64c7dca0a565.png align="center")

### *STEP 6.4: The Get all Method*

***STEP 6.4.1: Success***

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682798456493/f2fd2999-765b-4155-a6da-9e7034262011.png align="center")

### *STEP 6.5: The Delete Method*

***STEP 6.5.1: Success***

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682798517663/e6d21f41-51b0-4aaf-aa29-50f319593954.png align="center")

***STEP 6.5.2: Failure***

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682798525521/680d2727-c3b1-4bb8-969a-5f5ead1f55cc.png align="center")

That's all, folks! I hope this tutorial gave you a basic idea of how to create a simple REST API using **Node.js**, **Sequelize**, and **MySQL**.

Thank you for reading! Please feel free to follow me on social media.

%[https://tenor.com/view/thank-you-tanjiro-demon-slayer-kimetsu-no-yaiba-smile-gif-24421777]
