Create an API Rest With NestJS and PostgreSQL

Jose Luis Campos Bautista
The Startup
Published in
9 min readOct 27, 2020

In this tutorial, I will try to explain how to create an API Rest with NestJS framework.

NestJS

Before start

We are going to talk about some topics such as TypeScript, Promises, asyc, await and Docker commands which we will not be going in depth about but we will share information related to them.

Introduction

NestJS is a framework for building NodeJS server-side applications, it uses progressive JavaScript, is built and support TypeScript but let developers to code in pure JavaScript, but in this case we use TypeScript.

NestJS combine OOP(Oriented Object Programming), FP(Functional Programing), and FRP(Functional Reactive Programing).

NestJS makes use of the Express library, so every technique for using the MVC (Model-View-Controller) pattern in Express applies to NestJS as well.

Prerequisites

Please make sure that Node.js (>= v18.17.1) is installed on your operating system.

Installation

To start working with NestJS we need to install Nest CLI, it’s a command-line interface tool that will help you to maintain your Nest Applications, it assists in different manners, for example, scaffolding the project, serving the apps in development mode, and building the app for production distributions.

So let's start to create our project with the next command.

$ npm install -g @nestjs/cli

To scaffold a project with NestJS CLI, run the following command, the command going to create a new directory with the initial core configuration.

$ nest new tours-api

We can find core files in the src/ directory.

Initial configuration of Nest JS Application
Initial configuration of Nest JS Application
  • app.controller.ts: A basic controller with a simple route.
  • app.service.ts: A simple service.
  • app.module.ts: The root module of the application.
  • main.ts: The entry file of the application which uses the core function NestFactory to create a Nest application instance.
Entry file of the application.

To start the application type the nest commands.

$ cd tours-api
$ npm run start

Now you can open your browser and navigate to http://localhost:3000.

Controllers

The controllers are the most important in Api because they are in charge to handle requests and responses to the client and the routing mechanism controls which controller receives the request.

For our project we will use a module for each endpoint, it helps us to keep the code relevant to a specific feature organized, so type the following command which will create new directories above the module.

$ nest generate module country
Country module

The command adds the user module in the main application module.

New module added

The next step we goingto to create the country controller with the next command:

$ nest generate controller /country/country

The command will generate a basic controller with the next structure:

Basic controller

NestJS help us modifying the CountryModule adding the new controller.

CountryController added

A controller is a simple class with the decorator @Controller('country')which is required to define a controller and specifies the prefix country it allows us to easily group a set of related routes, and minimize repetitive code.

To handle the different methods NestJS provides us methods: @Get, @Post, @Put(), @Delete(), @Patch() and there is another decorator that handles all of them @All() .

In the next piece of code, we defined two methods with @Get, @Post decorators.

Basic controller with post and get methods

Now you can use postman and test the methods.

Testing get method

Service

Services are important because it is in charge of data storage and retrieve it, the service is designed to be used by the controller so lets to create a basic service with the next command.

$ nest generate service /country/country
Country service

As you can see we have the decorator @Injectable() marks a class as a provider, providers are a fundamental concept in nest, the main idea of a provider is that it can inject dependencies, this means that objects can create various relationships with each other and these instances be delegated to Nest runtime.

Providers can be injected into other classes via constructor parameter injection using Nest’s built-in Dependency Injection (DI) system.

The service was configured in UserModule.

CountryService configurated

To keep organized the data entries to our api we are going to use a DTO (Data Transfer Object) and for this we are going to create a class.

$ nest generate class /country/dto/country.dto

This DTO will help us to receive data in the post method of our api in each request, for this reason we need to add some validations, so we will use the class-validator libraty.

With install comman we will add the library in our project.

$ npm install class-validator
class-validator configured in package.json file

Now, for our case, to create a country we need two attributes iso and name.

Country DTO

The @IsNumber() and @IsString() decorators help us to validate the data type of the DTO, you can learn more about class-validator in the documentation.

We add two methods in our service, one returns the list of the countries, and the other add a new country.

New mehtods for country service

As I mentioned we inject user service into CountryController’s constructor and use the service methods to get data.

UserController injected CountryService

As you can see we add a new decorator @Body() to handle the body of the request, it extracts the entire body object from the request and populates the decorated parameter with the values of the body.

Now we can test our API with postman.

Post Method
Get method

Now in the next sections, we will configure our database, entities, and repositories to execute some queries.

Database configuration

NestJS allowing you to easily integrate with any SQL or NoSQL database for this reason is considered agnostic. It is simply a matter of loading an appropriate Node.js driver for the database.

For convenience Nest provides integration with TypeORM, Sequalize, and Mongose, those integrations provide us Nest JS features such as model/repository injection and testability.

In our case we will use TypeORM and PostgreSQL so we need to install the next dependencies.

$ npm install --save @nestjs/typeorm typeorm pg

For our database we are going to use a Docker container, so for this task we need to install Docker, once installed we are going to load a container with PostgreSql with the following command.

$ docker run -d -p 5444:5432 --name toursdb -e POSTGRES_USER=toursapi POSTGRES_DB=toursdb POSTGRES_PASSWORD=toursapi postgres

The flag -d indicates that the container going to execute in detach mode in the background.

The flag -p 5444:5432 specifies that the container will configure the port 5432 and we can access it with the 5444 from localhost.

— name toursdb specify the name of our container.

-e POSTGRES_PASSWORD, -e POSTGRES_DB and -e POSTGRES_USER we spesify environment variables of our data base.

Once the dependencies are installed and our container was configure we can import the TypeORM into root module.

Database configuration

The TypeOrmModule.forRoot() methods supports all the configurations bellow describe. You can learn more about this subject in the official documentation.

type: 'postgres',
host: 'localhost',
port: 5444,
username: 'toursapi',
password: 'toursapi',
database: 'toursdb',
entities: ['**/entity/*.entity.ts'],
synchronize: true,
autoLoadEntities: true

In this case we used a basic configiuration in the app.module.ts file.

Repository pattern

Repositories are classes or components that encapsulate the logic required to access data sources, this pattern decoupling the infrastructure or technology used to access databases from the domain model layer.

NestJS support repository pattern, for this task we need to create entities, n entity is a class that let us map to a database table or collection if you use MongoDB, you can create an entity by defining a new class and mark it with @Entity() decorator.

Each entity has its own repository that can be obtained from the database connection, to continue the example we create a class and configure a user entity, we create the class into entities directory.

$ nest generate class country/entity/country.entity

Once created the country class we add new attributes such as uuid, name, and iso.

Conutry entity

We configured different decorators:

@Entity(): This decorator is used to mark classes that will be an entity (table or document depend on database type). Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it.

@PrimaryGeneratedColumn(“uuid”): A column decorator is used to marking a specific class property as a table column.

@Column(): Column decorator is used to marking a specific class property as a table column. Only properties decorated with this decorator will be persisted in the database when the entity be saved.

You could learn more in TypeORM’s documentation.

In our database configuration have the synchronize: true value, this configuration let us automatically loaded models will be synchronized, so when we execute the command $ npm run start:dev TypeORM will create the table in our database, don’t used for prod environment.

And other important configuration that we did is the next:

entities: ['**/entity/*.entity.ts'],
autoLoadEntities: true

The last configuration permit TypeOrm find our entities and load the entities creating the database.

The next step is to configure the repository to access the database in the service, we are going to modify the service and implement a class Repository which helps us to work with our entity objects. Find entities, insert, update, delete, etc.

Now we use the instance of the repository to insert data and find the registers.

We are going to configure forFeature() a method in the CountryModule to define the repositories.

CountryEntity configuration

This module uses the forFeature() method to define which repositories are registered in the current scope. With that in place, we can inject the CountryRepository into the CountryService using the @InjectRepository() decorator:

Example of service.

As you can see we modified the types to return the service.

Conutry Cotroller

We used the async, await and promises in this part of the code, if you want to know more about these topics review the next post Introduction to async / await and the NestJS doumentation.

It’s time to test our API with Postman.

Conclusion

Let’s look at what we have learned.

  • How to create an API Rest with NestJS using CLI.
  • Some important NestJS decorators.
  • How to configure controllers, services, and repositories.
  • How to configure the database connection.
  • How to configure PostgreSQL Docker container.

Thanks for reading and I hope this little tutorial will help you.

Kindest Regards.

--

--