DEV Community

Juan Rodrigo de Oliveira Pinheiro
Juan Rodrigo de Oliveira Pinheiro

Posted on • Edited on

Creating REST APIs with Node.js

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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!

Top comments (0)