NestJS — Create a CRUD API using TypeORM and PostgreSQL
By: Ferrel John Fernando
Tags: Postgresql, Postgres, Typeorm, Nestjs, Typescript

In this post I want to show you how I set up my NestJS projects and we will learn to build our first CRUD REST API application using TypeORM and PostgreSQL. We will build To-Do List API in this section.

Prerequisites

I am assuming that you already know how to install a local development environment for Node.js, have PostgreSQL installed, and @nestjs/cli installed. If you not installed @nestjs/cli yet, you can read my previous post.

Create a NestJS Project

Let’s create a new project by run the following command:

$ nest new todo-list-app

$ cd todo-list-app

Environment Variables

There is a crucial thing to running our application is to set up environment variables. By using them to keep configuration data (database credentials, etc.), we can make configuration easily. It’s easier to keep sensitive data from being committed to repository.

In NestJS, we have a ConfigModule that we can use for read the configuration data. It uses dotenv behind the scene. To use ConfigModule , we need to install @nestjs/config . Use the following command to install:

$ npm install @nestjs/config

or if you using yarn :

$ yarn add @nestjs/config

After that, we need to create a .env file at the root of our application, so we can inject them into our ConfigService .

And then, we need to add ConfigModule.forRoot() at app.module.ts.

To prevent any error when our application run, we need to validating our environment variables. We gonna use Joi to define a validation schema.

$ npm install joi @types/joi

if you using yarn :

$ yarn add joi @types/joi

Let’s modification app.module.ts for adding validation schema.

Connecting application with PostgreSQL using TypeORM

To connecting the application with our database, we need to define a connection between application and database. To do that, we need to install TypeORM and PostgreSQL dependencies. Use the following command to install:

$ npm install @nestjs/typeorm typeorm pg

if you using yarn :

$ yarn add @nestjs/typeorm typeorm pg

I recommend you to create a database.module.ts, so it would be easier to make config for database. It will look like this:

After that, we need to import our DatabaseModule at app.module.ts.

Entity

In ORM technique, we need entity. Entity is a class maps to database table. To create it, we use the @Entity() decorator.

@PrimaryGeneratedColumn() is a decorator from TypeORM that will create an integer primary key for id column and generate the value automatically as a sequence.

@Column() decorator marks property as a column.

DTO

We need to create DTO (Data Transfer Object) for help us have an easy access to request body. DTO defines the format of data that sent in a request. We gonna create DTO class for create and update our Todo.

Repository

With Repository, we can manage particular entity. Repository has some functions to interact with entity. Repository are handled by TypeORM, so we just need use the class as constructor at our TodosService module. Our TodosService will look like this:

Controller

Controller have responsibility to handle incoming requests and return responses to client. Let’s create our TodosController . Our controller will look like this:

After that, we need to import our services to TodosModule . Let’s create and it will look like this:

And for the last step, we import our TodosModule to app.module.ts just like we import our DatabaseModule before.

Running and testing the apps

Let’s running the application with command yarn run start .

Output of yarn run start.

After that, we can test our apps using Postman.

Create Todo.

Get all Todos.

Create another Todo.

Get all Todos (again).

Get spesific Todo using id.

Update Todo.

Delete Todo.

When delete a record, our application doesn’t send any response body. So how we know that the record already deleted? In this example, we just get feedback HttpStatus 200 which is the API is working well and delete the record.

After first record already deleted, and second record already modified, our latest data look like this:

Our latest Todo data.

So, all function on our apps already tested, and it works well. You can test for negative cases by yourself so you will know how the apps gonna act when it happens.