+5

Xây dựng REST API với NestJS và Prisma (Phần 2)

Link phần 1

Giới thiệu

Ở phần 1, mình đã thực hiện các bước khởi tạo nestjs project, cài đặt Prisma để quản lý database, tạo bảng User và data mẫu.

Ở phần 2 này, mình sẽ tới bước viết API CRUD cơ bản cho dự án nestjs nhé. 🤩

3. Triển khai API CRUD cho model User

Trong phần này, mình sẽ triển khai các hoạt động Create, Read, Update và Delete (CRUD) cho model User mà chúng ta đã tạo thành công ở phần 1.

Tạo REST resources

Trước khi có thể triển khai API REST, bạn sẽ cần tạo REST resources cho model User đã. Việc này có thể được thực hiện nhanh chóng bằng cách sử dụng Nest CLI. Chạy lệnh sau trong terminal của bạn:

npx nest generate resource

CLI sẽ hiển thị các câu hỏi sau.

$ npx nest generate resource
? What name would you like to use for this resource (plural, e.g., "users")? 
// Điền users
? What transport layer do you use?
// Chọn option REST API
? Would you like to generate CRUD entry points? (Y/n)
// Y

CLI sẽ tự động tạo User resources và các thành phần bên trong nó image.png

Bây giờ bạn sẽ tìm thấy một thư mục src/users mới. Bên trong filesrc/users/users.controller.ts, bạn sẽ thấy định nghĩa của các routes khác nhau (còn được gọi là route handlers) . Logic xử lý sẽ được viết trong file src/users/users.service.ts.

image.png

Thêm PrismaClient vào User module

Để truy cập PrismaClient bên trong module User, ta phải import PrismaModule như sau

import { PrismaModule } from './../prisma/prisma.module';
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';

@Module({
  controllers: [UsersController],
  providers: [UsersService],
  imports: [PrismaModule]
})
export class UsersModule {}

Bây giờ ta có thể đưa PrismaService vào trong UsersService và sử dụng nó để truy cập vào DB. Để thực hiện việc này, hãy thêm constructor ở User.service.ts như thế này:

// src/users/users.service.ts

@Injectable()
export class UsersService {
  constructor(private prisma: PrismaService) {}

  create(createUserDto: CreateUserDto) {
    return 'This action adds a new user';
  }

  findAll() {
    return `This action returns all users`;
  }

  findOne(id: number) {
    return `This action returns a #${id} user`;
  }

  update(id: number, updateUserDto: UpdateUserDto) {
    return `This action updates a #${id} user`;
  }

  remove(id: number) {
    return `This action removes a #${id} user`;
  }
}

Xong bước này thì chúng ta có thể bắt tay vào việc viết API rồi.

Define GET /users endpoint

Controller cho endpoint này là findAll. Endpoint này sẽ trả về tất cả các Users có trong cơ sở dữ liệu.

// src/users/users.controller.ts

    @Get()
    findAll() {
        return this.usersService.findAll();
    }
 // src/users/users.service.ts

  findAll() {
    return this.prisma.user.findMany();
  }

findMany() sẽ trả về tất cả các bản ghi users

Truy cập endpoint http://localhost:8000/users và đây là kết quả: image.png

Define GET /users/:id

Controller cho endpoint này là findOne. Endpoint này sẽ trả về users có id tương ứng

// src/users/users.controller.ts

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }

Router nhận tham số id động, được chuyển đến và thực thi bởi findOne controller. Vì User model có id là integer nên tham số id cần được chuyển thành một số bằng toán tử +

 // src/users/users.service.ts

  findOne(id: number) {
    return this.prisma.user.findUnique({where: {id}});
  }

Kết quả:

image.png

Define POST /users endpoint

Đây là endpoint để tạo 1 user mới tưong ứng với create:

// src/users/users.controller.ts

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

Nó mong đợi các đối số phù hợp với CreateArticleDto trong phần request body.

DTO(Data Transfer Object)) là một đối tượng xác định cách dữ liệu sẽ được gửi qua mạng. Ban đầu, CreateArticleDto là một class trống. Ta sẽ thêm các thuộc tính vào nó để xác định định dạng của dữ liệu đầu vào.

Ở đây mình sẽ import package class-validatorclass-transformer để dùng các hàm validate có sẵn:

yarn add class-validator class-transformer
// src/users/dto/create-user.dto.ts
import { IsString, IsEmail, MaxLength, IsBoolean } from 'class-validator';

export class CreateUserDto {
    @IsString()
    @MaxLength(255)
    name: string;
  
    @IsEmail()
    email: string;
  
    @IsString()
    address?: string;

    @IsBoolean()
    isActive?: boolean = false;
}
// user service

  create(createUserDto: CreateUserDto) {
    this.prisma.user.create({ data: createUserDto });
  }

Define PATCH /users/:id endpoint

Dùng để cập nhật các User hiện có:

// src/users/users.controller.ts
  @Patch(':id')
  update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
    return this.usersService.update(+id, updateUserDto);
  }
/// file user service
  update(id: number, updateUserDto: UpdateUserDto) {
    return this.prisma.user.update({ where: { id }, data: updateUserDto });
  }

File update-user.dto.ts rule tương tự như create, hoặc bạn có thể thêm rule mới vào.

Kết quả update user 2 image.png

Define DELETE /users/:id endpoint

Dùng để xóa các User hiện có:

// src/users/users.controller.ts
  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.usersService.remove(+id);
  }
  remove(id: number) {
    return this.prisma.user.delete({where: { id }});
  }

Sau khi call api xóa user: DELETE: http://localhost:8000/users/1, ta gọi api getAll sẽ chỉ có còn 1 user

image.png

Tổng kết

Chúc mừng! Bạn đã xây dựng API REST đơn giản nhất bằng NestJS. Trong 2 bài viết này, chúng ta đã đi qua các nội dung:

  • Tổng quan về NestJS
  • Khởi tạo 1 project NestJS
  • Các bước xây dựng API REST với NestJS
  • Tích hợp Prisma với NestJS

Một trong những điều có thể thấy là việc xây dựng API REST với NestJS và Prisma rất là đơn giản. Đây là một framework nodejs cực kỳ hiệu quả để nhanh chóng xây dựng các ứng dụng web có cấu trúc tốt, an toàn và và dễ bảo trì.

Cảm ơn các bạn đã đọc bài viết của mình. Hẹn gặp lại mọi người ở những chủ đề khác nhé. 👋👋👋


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí