- vừa được xem lúc

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

0 0 14

Người đăng: Dao Vinh Sơn

Theo Viblo Asia

NestJS là một trong những framework Node.js nổi bật và nó đã nhận được rất nhiều sự yêu thích cũng như sức hút của các lập trình viên. NestJS giúp dễ dàng xây dựng các ứng dụng web hiện đại thường đòi hỏi việc tạo ra các REST API để tương tác với dữ liệu từ các máy chủ.

Giới thiệu

NestJS là một framework phát triển ứng dụng Node.js có cấu trúc, dựa trên các nguyên lý của Angular. Nó sử dụng TypeScript, một phiên bản được cải tiến của JavaScript, giúp kiểm soát và dễ dàng triển khai mã nguồn. Với việc triển khai mô hình kiến trúc lõi (core architecture), cấu trúc module, dependency injection và một số tính năng mạnh mẽ khác, mục tiêu chính của NestJS là cung cấp một cấu trúc ứng dụng rõ ràng và dễ quản lý, giúp tăng tính bảo trì và sự tổ chức trong mã nguồn.

Nội dung bài viết này sẽ trình bày các bước cơ bản để chúng ta có thể tạo ra REST API với NestJS, Prisma, PostgreSQL.

Các công nghệ sẽ sử dụng:

  • Backend framework: NestJS
  • Object-Relational Mapper (ORM): Prisma
  • Database: PostgreSQL
  • Programming language: Typescript

Về cơ bản sẽ có các bước sau:

  1. Đầu tiên, tạo một dự án NestJS mới.
  2. Sau đó, khởi tạo máy chủ PostgreSQL và kết nối với nó bằng Prisma.
  3. Cuối cùng, xây dựng các API.

Các bước thực hiện

Setup môi trường

  • Cài đặt Node.js.
  • Cài đặt PostgreSQL.
  • Cài đặt Extension: Prisma VSCode. (không bắt buộc)

1. Generate NestJS Project

Đầu tiên, ta phải cài đặt NestJS CLI. Để bắt đầu, hãy chạy lệnh sau ở vị trí bạn muốn đặt dự án:

npx @nestjs/cli new nest-starter

CLI sẽ nhắc bạn chọn trình quản lý gói cho dự án - chọn cái bạn muốn. Mình sẽ chọn npm.

Sau đó, bạn sẽ có một dự án NestJS mới trong thư mục hiện tại. Bạn sẽ thấy các tập tin sau:

nest-starter ├── node_modules ├── src │ ├── app.controller.spec.ts │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ └── main.ts ├── test │ ├── app.e2e-spec.ts │ └── jest-e2e.json ├── README.md ├── nest-cli.json ├── package-lock.json ├── package.json ├── tsconfig.build.json └── tsconfig.json

Hầu hết code sẽ nằm trong thư mục src.

Một số trong những thành phần đáng chú ý là:

  • src/app.module.ts: Mô-đun gốc của ứng dụng.
  • src/app.controller.ts: Basic controller với route: /. Router này sẽ trả về 'Hello world!'.
  • src/main.ts: Entry point của ứng dụng. Nó sẽ khởi động NestJS.

Bạn có thể khởi động bằng cách sử dụng lệnh sau:

npm run start:dev

Lệnh này sẽ theo dõi các tập tin trong dự án, tự động biên dịch lại và reload server bất cứ khi nào thực hiện thay đổi.

Truy cập URL http://localhost:3000/. để tới trang 'Hello World!'.

2. Setup Prisma

Hãy đảm bảo Postgres của bạn đã sẵn sàng!

Initialize Prisma

Chạy command sau để cài đặt Prisma:

npm install -D prisma

Bạn có thể khởi tạo Prisma trong dự án của mình bằng cách chạy:

npx prisma init

Thao tác này sẽ tạo một thư mục prisma file schema.prisma. Đây là tệp config database. Lệnh này cũng tạo một tệp .env bên trong dự án.

Set env variable

Hãy config lại DATABASE_URL để kết nối với PostgreSQL. Ví dụ:

DATABASE_URL="postgresql://myuser:password@localhost:5432/mydb?schema=nest-db"

Các thành phần trong Prisma schema

// prisma/schema.prisma
generator client { provider = "prisma-client-js"
} datasource db { provider = "postgresql" url = env("DATABASE_URL")
}

Tệp này được viết bằng Prisma schema, đây là ngôn ngữ mà Prisma sử dụng để xác định schema cho database của bạn.

Tệp Schema.prisma có ba thành phần chính:

  • Data source: Chỉ định kết nối db. Config trên có nghĩa là nhà cung cấp db của bạn là PostgreSQL và chuỗi kết nối db có sẵn trong biến env DATABASE_URL.
  • Generator: Cho biết rằng bạn muốn tạo Prisma Client, trình tạo truy vấn loại an toàn cho cơ sở dữ liệu của bạn. Nó được sử dụng để gửi truy vấn đến cơ sở dữ liệu của bạn.
  • Data mode: Xác định các model của bạn. Mỗimodel sẽ được ánh xạ tới một bảng trong Database. Ví dụ trên chưa có chứa phần này, chúng ta sẽ tìm hiểu ở phần sau.

Data model

Project này chúng ta sẽ cùng thực hành xoay quanh model User. Bên trong file prisma/prisma.schema, thêm 1 model mới như sau: // prisma/schema.prisma

model User { id Int @id @default(autoincrement()) name String email String @unique address String? isActive Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt
}

Ở đây, ta đã tạo một model User với một số trường. Mỗi trường có một tên (id, name, v.v.), một kiểu dữ liệu (Int, String,v.v.) và các thuộc tính tùy chọn khác (@id, @unique, v.v.). Các trường có thể được đặt tùy chọn bằng cách thêm ? sau kiểu dữ liệu.

Trường id có một thuộc tính đặc biệt gọi là@id: khóa chính, @default(autoincrement()): sẽ được tự động tăng và gán cho bất kỳ bản ghi mới được tạo nào.

Hai trường DateTimecreateAtupdateAt, trong đó, thuộc tính @updatedAt sẽ tự động cập nhật bất cứ khi nào bản ghi được sửa đổi.

Migrate database

Với Prisma, ta sẽ chạy migrate để tạo các bảng trong cơ sở dữ liệu. Để tạo và migation đầu tiên, hãy chạy lệnh sau:

npx prisma migrate dev --name "init"

Lệnh này sẽ thực hiện các việc sau:

  • Lưu migration:Prisma Migrate sẽ chụp nhanh schema và tìm ra các lệnh SQL cần thiết để thực hiện migrate. Prisma sẽ lưu file migration chứa các lệnh SQL vào thư mục prisma/migrations mới được tạo.

  • Thực thi migration: Prisma Migrate sẽ thực thi SQL trong file migration để tạo các bảng trong db.

  • Generate Prisma Client: Prisma sẽ generate Prisma Client dựa trên schema mới nhất. Nếu chưa cài đặt thư viện Client, CLI cũng sẽ cài đặt nó. Bạn sẽ thấy gói @prisma/client bên trong package.json. Prisma Client là trình tạo query TypeScript được tạo tự động từ Prisma schema. Nó được điều chỉnh cho phù hợp Prisma schema hiện tại và sẽ được sử dụng để query đến db.

Sau khi hoàn thành, nó sữ trả về messages như sau:

Kiểm tra file migration đưọc tạo để biết Prisma Migrate đã làm những gì:

-- CreateTable
CREATE TABLE "User" ( "id" SERIAL NOT NULL, "name" TEXT NOT NULL, "email" TEXT, "address" TEXT, "isActive" BOOLEAN NOT NULL DEFAULT false, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);

Ta thấy đây là SQL để tạo bảng User bên trong PostgreSQL. Nó được Prisma tạo tự động và thực thi.

Seed database

Hiện tại, database đang không có dữ liệu nào. Vì vậy, ta có thể sử dụng seed để tạo dữ liệu mẫu. Đầu tiên, tạo file prisma/seed.ts.

touch prisma/seed.ts

Sau đó, thêm đoạn code sau:

// prisma/seed.ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient();
async function main() { const user1 = await prisma.user.upsert({ where: { email: 'nguyenvana@prisma.io' }, update: {}, create: { email: 'nguyenvana@prisma.io', name: 'Nguyen Van A', address: 'Ha Noi', }, }); const user2 = await prisma.user.upsert({ where: { email: 'nguyenvanb@prisma.io' }, update: {}, create: { email: 'nguyenvanb@prisma.io', name: 'Nguyen Van B', isActive: true, }, }); console.log({ user1, user2 });
}
main() .then(async () => { await prisma.$disconnect(); }) .catch(async (e) => { console.error(e); await prisma.$disconnect(); process.exit(1); });

Ta tạo hai users bằng hàmprisma.upsert(). Hàm upsert sẽ chỉ tạo một bản ghi mới nếu không có bản ghi nào phù hợp với điều kiện trong where. Ta sử dụng upsert thay vì truy vấn createupsert loại bỏ các lỗi liên quan đến việc vô tình thêm cùng một bản ghi hai lần.

Bạn cần cho Prisma biết tập lệnh nào sẽ thực thi khi chạy seeding. Có thể thực hiện việc này bằng cách thêm prisma.seed vào cuối file package.json:

// package.json // ... "scripts": { // ... }, "dependencies": { // ... }, "devDependencies": { // ... }, "jest": { // ... }, "prisma": { "seed": "ts-node prisma/seed.ts" }

Sau đó chỉ việc thực thi thôi:

npx prisma db seed

Ta nhận tạo ra được 2 bản ghi sau:

$ npx prisma db seed
Environment variables loaded from .env
Running seed command `ts-node prisma/seed.ts` ...
{
user1: { id: 1, name: 'Nguyen Van A', email: 'nguyenvana@prisma.io', address: 'Ha Noi', isActive: false, createdAt: 2024-04-23T14:05:21.618Z, updatedAt: 2024-04-23T14:05:21.618Z
},
user2: { id: 2, name: 'Nguyen Van B', email: 'nguyenvanb@prisma.io', address: null, isActive: true, createdAt: 2024-04-23T14:05:21.625Z, updatedAt: 2024-04-23T14:05:21.625Z
}
}

Tạo Prisma service

Trong NestJS, cách tốt nhất là loại bỏ Prisma Client API trong app. Để thực hiện việc này, tạo một dịch vụ chứa Prisma Client. Service này được gọi là PrismaService, sẽ chịu trách nhiệm khởi tạo PrismaClient và kết nối với CSDL.

Nest CLI cung cấp một cách dễ dàng để generate modulesservices trực tiếp từ CLI. Chạy lệnh sau trong terminal:

npx nest generate module prisma
npx nest generate service prisma
$ npx generate modlue prisma
CREATE src/generate/prismanpx/prismanpx.service.spec.ts (481 bytes)
CREATE src/generate/prismanpx/prismanpx.service.ts (93 bytes)
UPDATE src/app.module.ts (327 bytes)
$ ^C
$ npx nest generate service prisma
CREATE src/prisma/prisma.service.spec.ts (460 bytes)
CREATE src/prisma/prisma.service.ts (90 bytes)
UPDATE src/prisma/prisma.module.ts (163 bytes)
$

Note: Trong một số trường hợp, việc chạy command với server đang chạy có thể dẫn đến việc NestJS đưa ra một exception có nội dung: Error: Cannot find module './app.controller'. Nếu bạn gặp phải lỗi này, hãy chạy lệnh: rm -rf dist và khởi động lại server.

Nó sẽ tạo ra một folder mới ./src/prisma với file prisma.module.tsprisma.service.ts.

// src/prisma/prisma.service.ts import { INestApplication, Injectable } from '@nestjs/common';
import { PrismaClient } from '@prisma/client'; @Injectable()
export class PrismaService extends PrismaClient {}

Module Prisma sẽ chịu trách nhiệm tạo một singleton của PrismaService và cho phép chia sẻ service trong toàn bộ dự án. Để thực hiện việc này, cần khai báo PrismaService vào export trong prisma.module.ts:

// src/prisma/prisma.module.ts import { Module } from '@nestjs/common';
import { PrismaService } from './prisma.service'; @Module({ providers: [PrismaService], exports: [PrismaService],
})
export class PrismaModule {}

Giờ đây, bất kỳ module nào imports PrismaModule sẽ có thể sử dụng PrismaService . Đây là pattern phổ biến cho các ứng dụng NestJS.

Sơ kết

Ta đã hoàn tất thiết lập Prisma với việc tạo bảng User và data mẫu để phục vụ cho việc tiếp theo là viết các API CRUD cho User. Mình sẽ trình bày ở phần 2 nhé 😁😁

Cảm ơn vì đã theo dõi bài viết của mình

Hẹn gặp lại mọi người.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Áp dụng kiến trúc 3 Layer Architecture vào project NodeJS

The problem encountered. Các framework nodejs phổ biết như Express cho phép chúng ta dễ dàng tạo ra Resful API xử lí các request từ phía client một cách nhanh chóng và linh hoạt.

0 0 80

- vừa được xem lúc

Tìm hiểu về NestJS (Phần 2)

Trong bài viết trước, mình đã giới thiệu về NestJS và các thành phần cơ bản của framework này cũng như xây dựng demo một api bằng NestJS. Như mình đã giới thiệu, NestJS có một hệ sinh thái hỗ trợ cho chúng ta trong quá trình phát triển mà các framework khác như Express, Fastify,... phải tự build hoặ

0 0 170

- vừa được xem lúc

Xây dựng một REST API Skeleton với Node.js

Node.js đang dần trở nên phổ biến với những ứng dụng dạng microservice hay REST Api bới hiệu năng cực nhanh và tính bất đồng bộ của chúng.

0 0 44

- vừa được xem lúc

Xây dựng Restful Api bằng Nodejs

Mở đầu. Thực ra là không có mở đầu gì đâu mà hay làm ngay bước tiếp theo ! .

0 0 46

- vừa được xem lúc

CORS là gì? CORS với Nodejs

CORS (hay Cross-origin resource sharing) là gì . . Lỗi cors trên trình duyệt:. .

0 0 72

- vừa được xem lúc

[K8S] Phần 15 - Triển khai ứng dụng NodeJS lên K8S

Giới thiệu. Trong các phần trước mình đã giới thiệu về cách dựng một hệ thống Kubernetes Cluster với khá đầy đủ các thành phần cần thiết như:.

0 0 41