TypeScript CRUD Rest API: Building a Robust Application with Nest.js, TypeORM, Postgres, Docker, and Docker Compose

Building a Robust TypeScript CRUD Rest API with Nest.js, TypeORM, Postgres, Docker, and Docker Compose

As the development world evolves, the need for reliable and scalable applications grows. Today, building robust applications requires an understanding of multiple programming languages and technologies. TypeScript is one such language that has gained popularity in recent years due to its type-safe features, which enable developers to write code with fewer errors. In this article, we will dive into how to build a TypeScript CRUD Rest API using Nest.js, TypeORM, Postgres, Docker, and Docker Compose.

Introduction to TypeScript

TypeScript is a strongly typed superset of JavaScript that compiles to plain JavaScript. It was developed by Microsoft and has gained popularity due to its ability to catch errors at compile time, resulting in fewer errors at runtime. TypeScript is compatible with any JavaScript library or framework, making it easy to integrate into existing projects.

What is Nest.js?

Nest.js is a popular framework for building scalable Node.js applications. It uses modern JavaScript features and incorporates ideas from other frameworks such as Angular, Express, and React. Nest.js is built on top of the Express framework, making it easy to integrate existing Express middleware. It also comes with built-in support for WebSocket servers and GraphQL.

TypeORM and its Benefits

TypeORM is an Object-Relational Mapping (ORM) library that allows developers to interact with databases using TypeScript or JavaScript. It supports a variety of databases such as MySQL, PostgreSQL, MongoDB, and more. With TypeORM, developers can write queries using TypeScript or JavaScript, making it easier to manage database interactions. It also allows for the creation of database schemas using TypeScript classes.

PostgreSQL Database

PostgreSQL is a powerful open-source relational database management system. It supports complex queries, transactions, and concurrency control. It is widely used in web applications due to its reliability and scalability.

Docker and Docker Compose

Docker is a popular platform for developing, shipping, and running applications in containers. Containers are lightweight and can be easily moved from one environment to another. Docker Compose is a tool for defining and running multi-container Docker applications. It simplifies the process of running multiple containers by defining them in a single file.

Creating the Project

The first step in building a TypeScript CRUD Rest API is to create the project. We will use the Nest.js CLI to create the project structure.

Step 1: Installing Nest.js CLI

To install Nest.js CLI, open the terminal and run the following command:

npm i -g @nestjs/cli

Step 2: Creating the Project

Once the Nest.js CLI is installed, run the following command to create the project:

nest new project-name

This command will create a new Nest.js project with the given name.

Step 3: Installing Dependencies

We will now install the required dependencies for our project. Run the following command in the terminal:

npm install --save @nestjs/typeorm typeorm pg

This command installs the required dependencies for Nest.js and TypeORM.

Setting up the Database

The next step is to set up the PostgreSQL database. We will use Docker and Docker Compose to create a PostgreSQL container.

Step 1: Creating a Docker Compose File

Create a file named docker-compose.yml in the root directory of the project and paste the following code:

version: '3'
services:
  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    ports:
      - 5432:5432

This code defines a PostgreSQL container with a default username and password.

Step 2: Starting the Container

To start the PostgreSQL container, run the following command in the terminal:

docker-compose up -d

This command will start the PostgreSQL container in detached mode.

Step 3: Creating the Database

We will now create a database named nest_crud in the PostgreSQL container. Run the following command in the terminal:

docker exec -it <container-id> psql -U postgres

Replace <container-id> with the container ID of the PostgreSQL container. This command opens a psql shell.

Run the following command in the psql shell to create the nest_crud database:

CREATE DATABASE nest_crud;

Step 4: Configuring TypeORM

The next step is to configure TypeORM to use the PostgreSQL database. Open the app.module.ts file and add the following code:

typescriptCopy codeimport { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot(),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'postgres',
      password: 'postgres',
      database: 'nest_crud',
      autoLoadEntities: true,
      synchronize: true,
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

This code imports the TypeOrmModule and configures it to use the PostgreSQL database.

Creating the API

The next step is to create the API. We will create a basic CRUD API for managing products.

Step 1: Creating the Product Entity

Create a file named product.entity.ts in the src folder and add the following code:

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Product {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  description: string;

  @Column()
  price: number;
}

This code defines a Product entity with the necessary columns.

Step 2: Creating the Product Service

Create a file named product.service.ts in the src folder and add the following code:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Product } from './product.entity';

@Injectable()
export class ProductService {
  constructor(
    @InjectRepository(Product)
    private readonly productRepository: Repository<Product>,
  ) {}

  async findAll(): Promise<Product[]> {
    return this.productRepository.find();
  }

  async findOne(id: number): Promise<Product> {
    return this.productRepository.findOne(id);
  }

  async create(product: Product): Promise<Product> {
    return this.productRepository.save(product);
  }

  async update(id: number, product: Product): Promise<Product> {
    await this.productRepository.update(id, product);
    return this.productRepository.findOne(id);
  }

  async delete(id: number): Promise<void> {
    await this.productRepository.delete(id);
  }
}

This code defines a ProductService with the necessary CRUD methods.

Step 3: Creating the Product Controller

Create a file named product.controller.ts in the src folder and add the following code:

import { Controller, Get, Post, Put, Delete, Body, Param } from '@nestjs

import { ProductService } from './product.service';
import { Product } from './product.entity';

@Controller('products')
export class ProductController {
constructor(private readonly productService: ProductService) {}

@Get()
async findAll(): Promise<Product[]> {
return this.productService.findAll();
}

@Get(':id')
async findOne(@Param('id') id: number): Promise<Product> {
return this.productService.findOne(id);
}

@Post()
async create(@Body() product: Product): Promise<Product> {
return this.productService.create(product);
}

@Put(':id')
async update(
@Param('id') id: number,
@Body() product: Product,
): Promise<Product> {
return this.productService.update(id, product);
}

@Delete(':id')
async delete(@Param('id') id: number): Promise<void> {
return this.productService.delete(id);
}
}

This code defines a ProductController with the necessary CRUD endpoints.

Step 4: Creating the Nest Application

Create a file named main.ts in the src folder and add the following code:

typescript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

Step 5: Testing the API

To test the API, run the following command in the terminal:

npm run start

This command starts the Nest application.

Open Postman and create the following requests:

  • GET /products - Get all products

  • GET /products/{id} - Get a specific product

  • POST /products - Create a new product

  • PUT /products/{id} - Update an existing product

  • DELETE /products/{id} - Delete an existing product

Test the requests to ensure that the API is working correctly.

Conclusion

In this article, we have learned how to create a TypeScript CRUD REST API using Nest.js, TypeORM, PostgreSQL, Docker, and Docker Compose. We have covered how to set up the development environment, configure the database, and create the API. We have also learned how to test the API using Postman. With this knowledge, you can now create your own CRUD APIs using these technologies.