Creating REST APIs with Node.js
Published: 2023-10-20 21:30:15

Hey! Welcome back, you. Hope you enjoyed my last post about creating a Rest API with and without TypeScript. As you may have noticed, I'm an enthusiast for back-end development. I really like organizing projects into MVCs.

So, today we're going to build an Rest API just with Node.js, with Express and Nodemon too. I am going to teach the very basics to start a project with these building tools. You'll see here some things about Node.js, Express and Docker too!

First, we're going to do our extreme basic:

```
npm init -y
```
This command will start your little project. Make sure you have it into a directory that relates to your project, k?

Also, this command will give us our package.json and our package-lock.json. Into these, we can create our own command lines for what we're doing today.

You'll see what was created with npm init. Then we're going to use:

```
npm install express --save-dev
```
Notice we're using a '--save-dev' flag to make sure we're installing express for development purposes only.

Right after that use:

```
npm install nodemon --save-dev
```
This package allows us to see our upgrades in real time. It gives us the benefit of not having to take our server down and up all the time (pretty anoying, right?).

Ok. We've done much so far, right? Congrats for your efforts until here. If you have any doubts, check the documentations for Node.js first and then Express and then Nodemon, alright?

In my case, I had the opportunity to learn about DevOps too. So I'm going to teach some basic things. First:

```
touch docker-compose.yaml
```
If you're using Linux like I am, you know that this command creates files. Just that.

Int docker-compose.yaml write some things such as:
`version: '3'
services:
  database:
    image: mysql:8.0.29
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: dev_to_example_db
    ports:
      - "3306:3306"`

This in an example of docker compose. Its useful to start writing and creating DBs for your project. Check the documentation on https://docs.docker.com/get-started/overview/

Did you notice that we're not using .env in this small project? This is because using Express and Node.js raw as this, is the very basic to start a Rest API. They say happiness resides on simplicity, right? I agree.

Now, to use Docker containers, we also have to create a Dockerfile. Use:

```
touch Dockerfile
```
And then write in your Dockerfile:
`FROM node:16


// the definition of our port chosen is on docker compose, remember?
EXPOSE 3001
// this expose setting is to serve as a signal to Docker understand which port we want to use

WORKDIR /app

// here we copy our .json's created with our npm init.
// by doing that, we're assuring that the dependencies installed will remain the same version
COPY package*.json ./

RUN npm install

COPY . .

CMD [ "npm", "start" ]`

Since we created a Node.js application in this container, we have to set configs to this app on our docker compose too. Before our first service created, we're going to write:
`version: '3'
services:
  node:
    // it makes docker build an custom image based on our Dockerfile
    build: 
      dockerfile: ./Dockerfile
      context: .
    // naming our container makes it easier
    container_name: dev_to_example_api
    // it restarts our container in case something makes it stop
    restart: always
    // default directory for our execution
    working_dir: /app
    // list of volumes (directories) mapped from the outside in
    volumes:
      // mounts the current directory with all the data of our project into the /app directory
      - ./:/app
    ports:
      // exposes our default port for our app
      // always remember that the first is the outside door and second one, our door (in our computer)
      - 3001:3001
    environment:
      // here we're setting our enviroment settings. This is not a good practice because it can expose some important infos about your projects.
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_HOST: database
      MYSQL_PORT: 3306
    // informs docker that the app has to be initiated after our database
    depends_on:
      - "database"

  database:
    image: mysql:8.0.29
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: devtoapidb
    ports:
      - "33060:3306"`

Alrighty! You're practically an DevOps now! After setting your configs for docker use:

```
docker-compose up -d #this -d flag indicates that we're going to set our container to be working on background
```
But something we'd like to our database to be created right after running our container, right? This makes our life easy. Write on your docker compose, right after your ports line in our Node app service:
` volumes:
        - ./dev_to_example.sql:/docker-entrypoint-initdb.d/dev_to_example.sql`

Now do:

```
docker-compose down && docker-compose up -d
```
This is for you to get your docker compose down and up again, with our new settings.

Let's connect express to our database now so we can create our Rest API at last.

Before that let's install our dialect for creating our DB. Use:

```
npm install mysql2@2.3.3 --save-exact
```
This command establishes our dialect exactly, just as the flag alerts. Using another dialect will get our db to have a conflict.

Create a file called 'connection.js' and write on it:
`const mysql = require('mysql2/promise');

const connection = mysql.createPool({
  host: process.env.MYSQL_HOST || 'localhost',
  port: process.env.MYSQL_PORT || 3306,
  user: process.env.MYSQL_USER || 'root',
  password: process.env.MYSQL_PASSWORD || 'root',
  database: process.env.DB_NAME || 'dev_to_example_db',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0,
});

module.exports = connection;`

This is a pool of connections. It makes our app easier to understand. As name implies it connects many times to many things. Makes it easy to connect. Those connections demand time to execute each one.

Create an app.js file:

```
touch app.js
```
Now write in it:
`const express = require('express');

const app = express();

app.use(express.json());

module.exports = app;`

Then create an server.js:

```
touch server.js
```
And write in it:
`const app = require('./app');
const connection = require('./db/connection');

const PORT = 3001;

app.listen(PORT, async () => {
  console.log(`Dev.to API executed in ${PORT}`);`

And now... be happy! After that, you can start to use your database commands. As you've seen, I'm using MySQL to create this API. From now on, you can see your database created on your MySQL Workbench. Make more robust coding with SQL commands, k? From now on you can check MySQL documentation.

Many thanks and see you next time!