💻 Build a CRUD Express API In ⌚ five minutes!
Tags: javascript, webdev, beginners, tutorial
Published: 2020-10-19 09:45:31

Interested in **Express**? Unsure how to get started with the **MERN** (MongoDB, Express.js, React.js, Node.js) ? This tutorial will get you up and running with a full **CRUD** *(Create, Read, Update, DELETE)* REST *(Representational State Transfer)* API in **FIVE minutes!** :panda_face:

## **Getting Started**

This tutorial assumes you have `nodejs` and `npm` installed and configured, along with MongoDB. *If not, leave a comment and I'll personally forward you my follow up post on* ***Installing and Running Node.js***

### **MVC** :gem:

Our application is going to follow the MVC (Model, View, Controller) ***design pattern***

I will talk about design patterns In a later post but, for now, all you need to know is that the MVC pattern is divided In to three sections :memo: :

- **Model** - Model represents an object carrying data. It can also have logic to update the controller if its data changes.
- **View** - View represents the visualization of the data that model contains.
- **Controller** - Controller acts on both model and view. It controls the data flow into model object and updates the view whenever data changes. It keeps view and model separate.

### **The Beginning** :arrow_lower_left:

To begin, let's create a new directory to work from:
- Navigate to your desired directory
- Run `mkdir my-express-app` (to create your project folder)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/inx9qb96lvxzg6b6ucjk.JPG)
- Run `npm init -y` (To initialize your node project)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8d5310f3x4tq2bscz8to.JPG)
- Create the following folders/files (or copy and paste the commands provided!)
 - `mkdir -p ./server/models; mkdir ./server/controllers; mkdir ./server/routes`
 - Then `touch ./server/index.js; touch ./server/models/user.model.js; touch ./server/controllers/user.controller.js; touch ./server/routes/user.routes.js`

#### **Now your project should look like this!** :eyes:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7oyqt6auvx7ozn43t2gy.JPG)

### **Creating the Server!** :cyclone:

The server needs three things to get running:
- Create a server application
- Consume route middleware
- Listen for requests

Let's break this down part by part

#### Create a server application

To begin with, we will need to install a few dependencies.

Open your terminal in the root of your project and run the following command:
`npm install express mongoose`
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ryw9kg5sxk1vldgyvzgr.JPG)
This installs two package dependencies. What are package dependencies? They are ***packages*** are APIs that can be used by your application to write code with. Your project then ***depends*** on this package to work (if you use the package).

`Express` is the API we are going to use to create our server, routes and controllers.
`mongoose` is an API that functions similarly to an ORM (Object Relational-mapper) that we are going to use to create our database model.


Open your `./server/index.js` file and paste the following code
```c
const express = require('express');

const app = express();

app.use(express.json());

app.get('/', (req, res) => {
    res.status(200).json({message: "Hello from my-express-app!"});
});

const PORT = 8080;

app.listen(PORT, () => {
    console.log(`Server listening at http://localhost:${PORT}`);
});
```

Line by line:
```c
const express = require('express');
```
Imports the Express API so that we can use it's features in our application.
```c
const app = express();
```
Constructs a new Express application that functions as our server.
```c
app.use(express.json());
```
Tells the Express application to use the JSON middleware (This is so we can see our request bodies with JSON)
```c
app.get('/', (req, res) => {
    res.status(200).json({message: "Hello from my-express-app!"});
});
```
Creates a `GET` route and sends an initial response.

Lastly, In our `package.json` file we need to add a script!
`"server": "node server/index.js"`
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/aa6gxdb4cscw71abtdy4.JPG)

Running 
```c
npm run server
```
In a terminal at the root of the project, then navigating to `http://localhost:8080/` should show us:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/bb7o6cj95w6rivi9e6bi.JPG)

### **The Controllers!** :wrench:

As we are creating a `CRUD` API, we need to create at least four controllers:
- create
- read
- update
- delete
Go ahead and add the following code to `./server/controllers/user.controller.js`
```c
exports.createOneRequest = (req, res) => {
    res.status(201).json({message: "New resource created!"});
}

exports.readOneRequest = (req, res) => {
    res.status(302).json({message: "Resource found!"});
}

exports.updateOneRequest = (req, res) => {
    res.status(301).json({message: "Resource updated!"});
}

exports.deleteOneRequest = (req, res) => {
    res.status(202).json({message: "Resource deleted!"});
}
```

Each function is responsible for a corresponding HTTP request, and returns the following appropriate response status code, along with some JSON data to look at!
- 201 - Resource Created
- 302 - Resource Found
- 301 - Resource Moved Permanently
- 202 - Resource Accepted

These are the controllers that will handle our requests!

### **The Routes!** :bike:

Now we have our controllers, we need some routes for them to handle. We are going to use Express router to handle our CRUD routes!
In your `./server/routes/user.routes.js` add the following:
```c
const express = require('express');
const urlRoutes = express.Router();

const controller = require('../controllers/user.controller');

urlRoutes.post('/', controller.createOneRequest);
urlRoutes.get('/:id', controller.readOneRequest);
urlRoutes.put('/:id', controller.updateOneRequest);
urlRoutes.delete('/:id', controller.deleteOneRequest);

module.exports = urlRoutes;

```
Then add the following to your `./server/index.js` file:
```c
const userRouter = require('./routes/user.routes');
...
app.use('/users', userRouter);
...
```

This mounts our newly created router to the `/users` sub route. Meaning any path we specify must be prepended with `/users` in order for the URL to be correct.

For example: `http://localhost:8080/<SOME_OBJECT_ID>` would be an example of a URL that would not work given our current project structure. 
`http://localhost:8080/users/<SOME_OBJECT_ID>` ***Would*** be a correct URL as it has the `/users` prepended!

Now, navigating to any of the URLs should return a response that looks something like this!
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/eyey6shmp7i35s9qjpik.JPG)


### **Build and integrate the Models!** :octocat:

We're almost at the final section of this tutorial. If you made it this far, congratulations! you're one step away from an awesome REST API :wink:

Add the following code to your `./server/models/user.model.js` file:
```c
const mongoose = require('mongoose');

const UserModel = mongoose.model('User', 
    mongoose.Schema(
        {
            name: {
                type: String
            },
        },
        {timestamps: true}
    )
);

module.exports = UserModel;
```

This creates a User Schema in your local MongoDB instance to be used.

Then, back in the `./server/controllers/user.controller.js` file:

Replace the contents of the createOneRequest request with:
```c
exports.createOneRequest = async (req, res) => {
    // req.body is for POST requests. Think 'body of the postman'
    // destruct the name value from the request body
    const {name} = req.body;

    // check if database already contains this name
    const foundUser = await UserModel.find({name});

    // if no user is found, we can add this user to the database.
    if(!foundUser || foundUser.length == 0) {
        const user = new UserModel({name});
        const response = await user.save();
        res.status(201).json(response);
    } else {
        res.status(409).json({message: "User already exists!"});
    }
}
```
This controller now handles three things!
- Check if a user already exists by the name provided.
- If no user exists, create one
- return response to client

Do the same for the `readOneRequest`:
```c
exports.readOneRequest = async (req, res) => {
    // Best request is GET, we can get the ID from the request 
    // parameters.
    const {id} = req.params;

    // attempt to retrieve user
    const foundUser = await UserModel.findOne({_id: id});

    // return 404 if no user found, return user otherwise.
    if(!foundUser || foundUser.length == 0) {
        res.status(404).json({message: "User not found!"});
    } else {
        res.status(302).json(foundUser);
    }
}
```

And for the `putOneRequest`:
```c

exports.updateOneRequest = async (req, res) => {
    const {id} = req.body;
    const foundUser = await UserModel.findOne({_id: id});
    if(foundUser || foundUser.length == 0) {
        const response = await foundUser.updateOne({_id: id});
        res.status(301).json(response);
    } else {
    res.status(404).json({message: `User not found...`});
    }
}
```

And lastly, the `deleteOneRequest`:
```c
exports.deleteOneRequest = async (req, res) => {
    const {id} = req.params;
    const foundUser = await UserModel.findOne({_id: id});
    if(foundUser || foundUser.length == 0) {
        const response = await foundUser.deleteOne({_id: id});
        res.status(202).json(response);
    } else {
        res.status(404).json({message: `User not found...`});
    }
}
```

Now that we have our CRUD operations built, all we need to do is configure the database and we are ready to go!

### **The Database connection!** :mailbox:

We need to open a connection to our Mongo Database so that our application can communicate with the database!

To do this, open your `./server/index.js` script and add the following code:
```c
...
const mongoose = require('mongoose');

const db = mongoose.connect('mongodb://localhost:27017/db', {
    useCreateIndex: true,
    useNewUrlParser: true,
    useUnifiedTopology: true
}).then((response) => {
    console.log('Connected to the database...');
    return response;
});
...
```

Run `npm run server` and sit back and relish in the brand new Full CRUD Rest API you have majestically built! :raised_hands:

### **Summary** :wave:

There you have it! a fully functioning, full featured CRUD methods Restful API! We went through constructing an express application, consuming middleware and routes, route controllers and finally database models. A very bus tutorial! :tired_face:

Feel free to leave comments below, any feedback is welcome! Link me to some of the apps you've built from this!

*I hope you enjoyed this tutorial and feel like checking out my other social media! This is my first post on this site to please be kind* :smile: