Working with databases is a crucial part of modern backend development, and TypeORM makes it easier when using NestJS. NestJS, a progressive Node.js framework, is highly versatile and scalable, and combining it with TypeORM – an Object-Relational Mapping (ORM) tool – brings numerous benefits to the development process. Let's dive right in!
What is TypeORM?
TypeORM is an ORM for TypeScript and JavaScript (ES7, ES6, ES5) that allows you to interact with databases easily. It supports various databases like MySQL, PostgreSQL, and SQLite among others. With TypeORM, you can use TypeScript decorators to define your data models, making the database interaction more intuitive and less error-prone.
Setting Up a NestJS Project with TypeORM
Step 1: Create a New NestJS Project
You can create a new NestJS application using the Nest CLI. If you haven’t installed it yet, run the following command:
npm i -g @nestjs/cli
Next, create your new project:
nestjs new nestjs-typeorm-demo cd nestjs-typeorm-demo
Step 2: Install TypeORM and Database Driver
Depending on the database you choose, you'll need to install TypeORM alongside the respective database driver. Here, we’ll use PostgreSQL as an example:
npm install --save @nestjs/typeorm typeorm pg
Step 3: Configure TypeORM in your Application
Now that you have TypeORM installed, it’s time to configure it. Open the app.module.ts
file and set up the TypeORM module:
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'postgres', host: 'localhost', port: 5432, username: 'your_username', password: 'your_password', database: 'your_database', entities: [__dirname + '/**/*.entity{.ts,.js}'], synchronize: true, // Note: Don't use synchronize in production! }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
This configuration connects your NestJS app to a PostgreSQL database. The synchronize
option, set to true
, automatically creates the database tables based on your entities, which is useful during development.
Creating Entities
Entities in TypeORM define your database tables. Each class that represents a table should be decorated with @Entity()
, and its properties should be decorated with relevant TypeORM decorators.
Step 4: Create a Post Entity
Create a new folder named posts
and within it a file named post.entity.ts
:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity() export class Post { @PrimaryGeneratedColumn() id: number; @Column() title: string; @Column() content: string; }
This Post
class defines a posts
table with three columns: id
, title
, and content
.
Creating a Service to Handle Business Logic
Services in NestJS handle the business logic of your application. Here, we'll create a simple service to manage our Post entities.
Step 5: Generate the Posts Service
Use the Nest CLI to generate a new service:
nestjs generate service posts/posts
Now, modify the generated posts.service.ts
to use TypeORM's repository pattern:
import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Post } from './post.entity'; @Injectable() export class PostsService { constructor( @InjectRepository(Post) private postsRepository: Repository<Post>, ) {} create(post: Partial<Post>): Promise<Post> { const newPost = this.postsRepository.create(post); return this.postsRepository.save(newPost); } findAll(): Promise<Post[]> { return this.postsRepository.find(); } findOne(id: number): Promise<Post> { return this.postsRepository.findOne(id); } async remove(id: number): Promise<void> { await this.postsRepository.delete(id); } }
Breakdown of Service Methods:
- create(): Creates and saves a new post.
- findAll(): Retrieves all posts from the database.
- findOne(): Fetches a post based on the
id
. - remove(): Deletes a post from the database.
Creating a Controller
To connect our service to the NestJS application’s routes, we’ll create a controller.
Step 6: Generate the Posts Controller
Run the following command:
nestjs generate controller posts/posts
Now modify your posts.controller.ts
:
import { Controller, Get, Post, Body, Param, Delete } from '@nestjs/common'; import { PostsService } from './posts.service'; import { Post as PostEntity } from './post.entity'; @Controller('posts') export class PostsController { constructor(private readonly postsService: PostsService) {} @Post() create(@Body() post: Partial<PostEntity>): Promise<PostEntity> { return this.postsService.create(post); } @Get() findAll(): Promise<PostEntity[]> { return this.postsService.findAll(); } @Get(':id') findOne(@Param('id') id: number): Promise<PostEntity> { return this.postsService.findOne(id); } @Delete(':id') remove(@Param('id') id: number): Promise<void> { return this.postsService.remove(id); } }
Breakdown of Controller Methods:
- POST /posts: Creates a new post.
- GET /posts: Fetches all posts.
- GET /posts/:id: Fetches a single post by
id
. - DELETE /posts/:id: Deletes a post by
id
.
Testing the API
At this point, your RESTful API for managing posts is set up. You can test the API using tools like Postman or Insomnia.
-
Create a Post: Send a POST request to
http://localhost:3000/posts
with JSON body:{ "title": "My First Post", "content": "This is the content of my first post." }
-
Get All Posts: Send a GET request to
http://localhost:3000/posts
. -
Get a Single Post: Send a GET request to
http://localhost:3000/posts/1
. -
Delete a Post: Send a DELETE request to
http://localhost:3000/posts/1
.
Conclusion
With this guide, you’ve learned how to set up a NestJS application using TypeORM for managing a PostgreSQL database. You’ve created entities, services, and controllers that together form a basic RESTful API. As you continue your journey with NestJS and TypeORM, you can explore more advanced features such as pagination, DTOs, and validation to enhance your application. Get creative and start building robust applications using NestJS!