├── 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

所處理的大部分代碼都會存放在?src?目錄中。NestJS CLI 已經為您預先創建了一些基礎文件,其中幾個尤為關鍵:

要啟動項目,您可以執行以下命令:

npm run start:dev

該命令將監視您的文件,每當您進行更改時自動重新編譯和重新加載服務器。要驗證服務器是否正在運行,請轉到URL http://localhost:3000/。您應該會看到一個空頁面,其中包含消息'Hello World!'

注意:在學習本教程時,您應該保持服務器在后臺運行。

創建 PostgreSQL 實例

本教程將指導您如何在計算機上通過 Docker 容器安裝并運行 PostgreSQL,以作為 NestJS 應用的數據庫。

注意:若您不打算使用 Docker,還可以選擇在本地搭建 PostgreSQL 實例,或在 Heroku 上獲取托管的 PostgreSQL 數據庫服務。

首先,在項目的主文件夾中創建一個docker-compose.yml文件:

touch docker-compose.yml

這個 docker-compose.yml 文件是一個配置文件,它將包含運行docker容器的規范,其中包含PostgreSQL設置。在文件中創建以下配置:

# docker-compose.yml

version: '3.8'
services:

postgres:
image: postgres:13.5
restart: always
environment:
- POSTGRES_USER=myuser
- POSTGRES_PASSWORD=mypassword
volumes:
- postgres:/var/lib/postgresql/data
ports:
- '5432:5432'

volumes:
postgres:
volumes: postgres:

關于此配置,需要了解以下幾點:

請確保您的機器上沒有其他服務正在使用 5432 端口。要啟動 postgres 容器,請打開一個新的終端窗口,并在項目的主文件夾中運行以下命令:

docker-compose up

如果一切正常,新的終端窗口應顯示數據庫系統已準備好接受連接的日志。您應該會在終端窗口中看到類似于以下內容的日志:

...
postgres_1 | 2022-03-05 12:47:02.410 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
postgres_1 | 2022-03-05 12:47:02.410 UTC [1] LOG: listening on IPv6 address "::", port 5432
postgres_1 | 2022-03-05 12:47:02.411 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres_1 | 2022-03-05 12:47:02.419 UTC [1] LOG: database system is ready to accept connections

恭喜 ??。您現在已成功擁有了自己的 PostgreSQL 數據庫!

注意:若您關閉終端窗口,容器也會隨之停止。為避免這種情況,您可以在命令末尾添加 -d 選項,例如:docker-compose up -d。這樣容器就會在后臺持續運行,不會因終端關閉而中斷。

設置 Prisma

既然數據庫已經準備就緒,接下來就該配置 Prisma 了!

初始化 Prisma

首先,您需要將 Prisma CLI 安裝為項目的開發依賴項。Prisma CLI 提供了多種命令,方便您與項目進行交互。

npm install -D prisma

您可以通過運行以下命令在項目中初始化 Prisma:

npx prisma init

這將創建一個新的 Prisma 目錄和一個 schema.prisma 文件。這是包含數據庫模式的主配置文件。這個命令也會在你的項目中創建一個.env 文件。

設置環境變量

在?.env?文件中,您會發現一個名為?DATABASE_URL?的環境變量,它包含一個虛擬的連接字符串。您需要將這個虛擬的連接字符串替換為您 PostgreSQL 實例的實際連接字符串。

// .env
DATABASE_URL="postgres://myuser:mypassword@localhost:5432/median-db"

注意:如果您沒有使用 docker(如上一節所示)來創建 PostgreSQL 數據庫,則您的連接字符串將與上面顯示的連接字符串不同。關于PostgreSQL 的連接字符串格式,您可以在 Prisma 官方文檔中查閱到。

了解 Prisma 架構

如果打開 prisma/schema.prisma,您應該看到以下默認模式:

// prisma/schema.prisma

generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

schema.prisma 文件是使用 Prisma Schema 語言編寫的,這是 Prisma 用于定義數據庫架構的專有語言。該文件主要包含以下三個核心組成部分:

注意:有關 Prisma 架構的更多信息,請查看 Prisma 文檔。

對數據進行建模

現在,是時候為您的應用程序定義數據模型了。在本教程中,我們僅需要一個名為?Article?的模型,用以代表博客上的每一篇文章

請打開 prisma/schema.prisma 文件,并向其中添加一個全新的 Article 模型:

// prisma/schema.prisma

model Article {
id Int @id @default(autoincrement())
title String @unique
description String?
body String
published Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

您已經成功創建了一個功能完備的?Article?模型。該模型包含多個字段,如?idtitle?等,每個字段都具備名稱、類型以及可選的特殊屬性(例如?@id@unique?等)。通過在字段類型后添加??,您可以輕松地將某個字段設置為可選。

id字段被賦予了@id的特殊屬性,這標志著它是該模型的主鍵。而?@default(autoincrement())?屬性則確保每當有新記錄創建時,該字段都會自動遞增并分配一個唯一的值。

published字段是指示文章是已發布還是處于草稿模式的標志。@default(false)屬性表示默認情況下該字段應設置為false

兩個DateTime 字段?createdAt?updatedAt 將跟蹤文章的創建時間和上次更新時間。@updatedAt屬性會自動將該字段更新為當前時間戳,無論何時文章被修改,這個字段都會與當前時間同步更新。

遷移數據庫

定義 Prisma 架構后,您將運行遷移以在數據庫中創建實際表。要生成并執行您的第一個遷移,請在終端中運行以下命令:

npx prisma migrate dev --name "init"

此命令將執行三項操作:

  1. 保存遷移:Prisma Migrate會首先捕捉您數據庫模式的當前快照,并據此分析出將您的數據庫模式更新到最新狀態所需的SQL命令。隨后,Prisma會將這些SQL命令封裝進遷移文件中,并將這些文件保存到新創建的 prisma/migrations 文件夾中。這個過程為您的數據庫模式變更提供了詳細的記錄和步驟。
  2. 執行遷移:一旦遷移文件被創建,Prisma Migrate就能夠執行這些文件中的SQL命令,從而在數據庫中實際創建或更新底層表結構。這個過程確保了您的數據庫模式與Prisma模式文件中的定義保持一致。
  3. 生成Prisma客戶端:在遷移執行完畢后,Prisma會根據您最新的數據庫模式自動生成Prisma客戶端。如果您尚未安裝客戶端庫,Prisma CLI也會為您自動安裝。您可以在 package.json 文件的 dependencies 部分找到名為 @prisma/client 的包。Prisma Client是一個功能強大的TypeScript查詢生成器,它根據您的Prisma模式文件自動生成與數據庫交互的代碼。這個客戶端是為您的特定Prisma模式量身定制的,它將大大簡化您向數據庫發送查詢的過程。

注意:您可以在 Prisma 文檔中了解有關 Prisma Migrate 的更多信息。

如果成功完成,您應該會看到如下消息:

The following migration(s) have been created and applied from new schema changes:

migrations/
└─ 20220528101323_init/
└─ migration.sql

Your database is now in sync with your schema.
...
? Generated Prisma Client (3.14.0 | library) to ./node_modules/@prisma/client in 31ms

檢查生成的遷移文件,了解 Prisma Migrate 在幕后的作用:

-- prisma/migrations/20220528101323_init/migration.sql

-- CreateTable
CREATE TABLE "Article" (
"id" SERIAL NOT NULL,
"title" TEXT NOT NULL,
"description" TEXT,
"body" TEXT NOT NULL,
"published" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "Article_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "Article_title_key" ON "Article"("title");

注意:遷移文件的名稱將略有不同。

這是在PostgreSQL數據庫中創建 Article 表所需的SQL。它是由Prisma根據您的Prisma模式自動生成和執行的。

種子數據庫

目前,數據庫為空。因此,您將創建一個種子腳本,該腳本將使用一些虛擬數據填充數據庫。

首先,創建一個名為prisma/seed.ts的文件,這個文件將包含初始化數據庫種子所需的模擬數據和查詢。

touch prisma/seed.ts

然后,在seed文件中添加以下代碼:

// prisma/seed.ts

import { PrismaClient } from '@prisma/client';

// initialize Prisma Client
const prisma = new PrismaClient();

async function main() {
// create two dummy articles
const post1 = await prisma.article.upsert({
where: { title: 'Prisma Adds Support for MongoDB' },
update: {},
create: {
title: 'Prisma Adds Support for MongoDB',
body: 'Support for MongoDB has been one of the most requested features since the initial release of...',
description:
"We are excited to share that today's Prisma ORM release adds stable support for MongoDB!",
published: false,
},
});

const post2 = await prisma.article.upsert({
where: { title: "What's new in Prisma? (Q1/22)" },
update: {},
create: {
title: "What's new in Prisma? (Q1/22)",
body: 'Our engineers have been working hard, issuing new releases with many improvements...',
description:
'Learn about everything in the Prisma ecosystem and community from January to March 2022.',
published: true,
},
});

console.log({ post1, post2 });
}

// execute the main function
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
// close Prisma Client at the end
await prisma.$disconnect();
});

在這個腳本中,首先需要初始化Prisma客戶端。接著,使用prisma.upsert()函數來創建兩個項目。upsert函數只會在沒有文章符合where條件時才創建一個新文章。您選擇使用upsert查詢而不是create查詢,這是因為upsert可以避免因意外嘗試兩次插入相同記錄而產生的錯誤。

您需要指定Prisma在執行種子命令時運行哪個腳本。您可以通過在 package.json 文件的末尾添加 prisma.seed 鍵來實現這一點:

// package.json

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

seed 命令將執行您之前定義的 prisma/seed.ts 腳本。由于ts-node已經作為開發依賴安裝在您的package.json中,這個命令應該能夠自動運行。

請使用以下命令來執行數據庫的種子數據初始化:

npx prisma db seed

您應該會看到以下輸出:

Running seed command ts-node prisma/seed.ts ...
{
  post1: {
    id: 1,
    title: 'Prisma Adds Support for MongoDB',
    description: "We are excited to share that today's Prisma ORM release adds stable support for MongoDB!",
    body: 'Support for MongoDB has been one of the most requested features since the initial release of...',
    published: false,
    createdAt: 2022-04-24T14:20:27.674Z,
    updatedAt: 2022-04-24T14:20:27.674Z
  },
  post2: {
    id: 2,
    title: "What's new in Prisma? (Q1/22)",
    description: 'Learn about everything in the Prisma ecosystem and community from January to March 2022.',
    body: 'Our engineers have been working hard, issuing new releases with many improvements...',
    published: true,
    createdAt: 2022-04-24T14:20:27.705Z,
    updatedAt: 2022-04-24T14:20:27.705Z
  }
}

??  The seed command has been executed.

注意:您可以在 Prisma Docs 中了解有關種子設定的更多信息。

創建 Prisma 服務

在NestJS應用程序中,將Prisma Client API從應用邏輯中抽象出來是一個好習慣。為此,您將創建一個新的服務來封裝Prisma Client。這個服務名為 PrismaService,它負責創建一個 PrismaClient 實例并連接到您的數據庫。

Nest CLI提供了一種方便的方法,可以直接從命令行界面(CLI)生成模塊和服務。在終端中運行以下命令:

npx nest generate module prisma
npx nest generate service prisma

注 1:如有需要,請參考 NestJS 文檔了解服務和模塊的介紹。

注 2:在某些情況下,在服務器已經運行的情況下運行 nest generate 命令可能會導致NestJS拋出異常:Error: Cannot find module './app.controller'。如果您遇到此錯誤,請從終端運行以下命令:rm -rf dist并重新啟動服務器。

這應該會生成一個新的帶有./src/prismaprisma.module.ts 文件的文件夾 prisma.service.ts。服務文件應包含以下代碼:

// src/prisma/prisma.service.ts

import { INestApplication, Injectable } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient {}

Prisma模塊將負責創建 PrismaService 的單例實例,并允許在整個應用程序中共享服務。要做到這一點,你需要將 PrismaService 添加到 exports 文件中的 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 {}

現在,任何導入PrismaModule的模塊都可以訪問PrismaService,并將其注入到自己的組件/服務中。這是NestJS應用程序的常見模式。

完成后,您就完成了 Prisma 的設置!您現在可以開始構建 REST API。

設置 Swagger

Swagger 是一個基于 OpenAPI 規范來記錄 API 的工具。Nest 提供了一個專門的 Swagger 模塊,您很快就會用到它。

首先安裝所需的依賴項:

npm install --save @nestjs/swagger swagger-ui-express

現在打開 main.ts 并使用 SwaggerModule 類初始化Swagger:

// src/main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

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

const config = new DocumentBuilder()
.setTitle('Median')
.setDescription('The Median API description')
.setVersion('0.1')
.build();

const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);

await app.listen(3000);
}
bootstrap();

當應用程序運行時,打開瀏覽器并導航到 http://localhost:3000/api. 您應該能夠看到 Swagger UI 界面。

Swagger 用戶界面

為Article模型實現 CRUD 操作

在本節中,您將為Article模型實現創建(Create)、讀取(Read)、更新(Update)和刪除(Delete)操作,以及任何相關的業務邏輯。

生成 REST 資源

在您能夠實現REST API之前,您需要為Article模型生成REST資源。這可以通過Nest CLI快速完成。在終端中運行以下命令

npx nest generate resource

您將收到一些 CLI 提示。請相應地回答問題:

  1. 您想為這個資源使用什么名稱(復數形式,例如,“users”)? articles
  2. 您使用的傳輸層是什么? REST API
  3. 您是否希望生成CRUD入口點? 是

現在您應該在src/articles目錄下找到了所有REST端點的樣板代碼。在src/articles/articles.controller.ts文件中,您將看到不同路由(也稱為路由處理器)的定義。處理每個請求的業務邏輯封裝在src/articles/articles.service.ts文件中。目前,這個文件包含一些虛擬實現。

如果您再次打開 Swagger API 頁面,您應該會看到如下內容:

自動生成的 “articles” 端點


SwaggerModule會搜索所有路由處理器上的@Body()、@Query()和@Param()裝飾器,以生成這個API頁面。

將PrismaClient添加到Articles模塊

要在Articles模塊內訪問PrismaClient,您必須將PrismaModule作為一個導入添加。在ArticlesModule中添加以下導入:

// src/articles/articles.module.ts

import { Module } from '@nestjs/common';
import { ArticlesService } from './articles.service';
import { ArticlesController } from './articles.controller';
import { PrismaModule } from 'src/prisma/prisma.module';

@Module({
controllers: [ArticlesController],
providers: [ArticlesService],
imports: [PrismaModule],
})
export class ArticlesModule {}

您現在可以將 PrismaService 注入到 ArticlesService 中,并使用它來訪問數據庫。為此,您需要在articles.service.ts文件中添加一個構造函數,如下所示:

// src/articles/articles.service.ts

import { Injectable } from '@nestjs/common';
import { CreateArticleDto } from './dto/create-article.dto';
import { UpdateArticleDto } from './dto/update-article.dto';
import { PrismaService } from 'src/prisma/prisma.service';

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

// CRUD operations
}

定義 GET /articles 終端節點

該端點的控制器名為 findAll。此端點將返回數據庫中所有已發布的文章。findAll 控制器的實現如下所示:

// src/articles/articles.controller.ts

@Get()
findAll() {
return this.articlesService.findAll();
}

您需要更新 ArticlesService.findAll()以返回數據庫中所有已發布文章的數組:

// src/articles/articles.service.ts

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

create(createArticleDto: CreateArticleDto) {
return 'This action adds a new article';
}

findAll() {
return This action returns all articles; return this.prisma.article.findMany({ where: { published: true } }); }

findMany 查詢將返回與 article 條件匹配的所有 where 記錄。

您可以通過訪問 http://localhost:3000/api 并點擊 GET /articles 菜單來測試這個端點。點擊“Try it out”,然后點擊“Execute”按鈕來查看結果。

注意:您也可以直接在瀏覽器中運行所有請求,或者通過REST客戶端(如Postman)運行所有請求。Swagger還為每個請求生成curl命令,以防您希望在終端中運行HTTP請求。

定義 GET /articles/drafts 終端節點

您將定義一個新的路由來獲取所有未發布的文章。NestJS 沒有為這個端點自動生成控制器路由處理器,因此您需要自行編寫它。

// src/articles/articles.module.ts

import { Module } from '@nestjs/common';
import { ArticlesService } from './articles.service';
import { ArticlesController } from './articles.controller';
import { PrismaModule } from 'src/prisma/prisma.module';

@Module({
controllers: [ArticlesController],
providers: [ArticlesService],
imports: [PrismaModule],
})
export class ArticlesModule {}

你的編輯器應該顯示一個錯誤,提示沒有名為articlesService.findDrafts()的函數存在。要解決這個問題,請在 findDrafts 中實現 ArticlesService 方法:

// src/articles/articles.service.ts

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

create(createArticleDto: CreateArticleDto) {
return 'This action adds a new article';
}

findDrafts() {
return this.prisma.article.findMany({ where: { published: false } });
}

// ...

}

GET /articles/drafts 端點現在應該已經在 Swagger API 頁面中可用了。

注意:我建議您在完成實施后通過 Swagger API 頁面測試每個終端節點。

定義 GET /articles/:id 終端節點

此端點的控制器路由處理器名為findOne。它的實現如下所示:

// src/articles/articles.controller.ts

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

路由接受一個動態的id參數,該參數被傳遞給findOne控制器路由處理程序。由于Article模型具有整數id字段,因此需要使用id運算符將+參數轉換為數字。

現在,更新 findOne 中的 ArticlesService 方法,以返回具有給定id的文章:

// src/articles/articles.service.ts
@Injectable()
export class ArticlesService {
constructor(private prisma: PrismaService) {}

create(createArticleDto: CreateArticleDto) {
return 'This action adds a new article';
}

findAll() {
return this.prisma.article.findMany({ where: { published: true } });
}

findOne(id: number) {
return This action returns a #${id} article; return this.prisma.article.findUnique({ where: { id } }); } }

請訪問 http://localhost:3000/api,然后點擊 GET /articles/{id} 下拉菜單。點擊“Try it out”(試用),在 id 參數中輸入一個有效的值,接著點擊“Execute”(執行)來查看結果。

定義POST /articles終端節點

這是創建新文章的端點,此端點的控制器路由處理程序稱為 create。它的實現如下所示:

// src/articles/articles.controller.ts

@Post()
create(@Body() createArticleDto: CreateArticleDto) {
return this.articlesService.create(createArticleDto);
}

請注意,它在請求體中期望一個類型為CreateArticleDto的參數。DTO(Data Transfer Object,數據傳輸對象)是一個定義數據如何通過網絡發送的對象。目前,CreateArticleDto是一個空類。您需要向其中添加屬性,以定義請求正文的結構。復制再試一次分享

// src/articles/dto/create-article.dto.ts

import { ApiProperty } from '@nestjs/swagger';

export class CreateArticleDto {
@ApiProperty()
title: string;

@ApiProperty({ required: false })
description?: string;

@ApiProperty()
body: string;

@ApiProperty({ required: false, default: false })
published?: boolean = false;
}

需要使用 @ApiProperty 裝飾器來使類屬性對 SwaggerModule 可見。更多關于這方面的信息可以在NestJS文檔中找到。

現在,您應該在Swagger API頁面的Schemas下定義 CreateArticleDtoUpdateArticleDto 的結構是從 CreateArticleDto 定義中自動推斷出來的。因此,UpdateArticleDto 也在Swagger中進行了定義。

現在更新create中的ArticlesService方法,在數據庫中創建一個新項目:

// src/articles/articles.service.ts

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

create(createArticleDto: CreateArticleDto) {
return 'This action adds a new article';
return this.prisma.article.create({ data: createArticleDto });
}

// ...
}

定義 PATCH /articles/:id 終端節點

此端點用于更新現有文章,此端點的路由處理程序稱為 update。它的實現如下所示:

// src/articles/articles.controller.ts

@Patch(':id')
update(@Param('id') id: string, @Body() updateArticleDto: UpdateArticleDto) {
return this.articlesService.update(+id, updateArticleDto);
}

updateArticleDto 定義被定義為 PartialType 中的 CreateArticleDto。所以它可以擁有 CreateArticleDto 的所有屬性。

// src/articles/dto/update-article.dto.ts

import { PartialType } from '@nestjs/swagger';
import { CreateArticleDto } from './create-article.dto';

export class UpdateArticleDto extends PartialType(CreateArticleDto) {}

與之前一樣,您必須更新此操作對應的服務方法:

// src/articles/articles.service.ts

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

// ...

update(id: number, updateArticleDto: UpdateArticleDto) {
return This action updates a #${id} article; return this.prisma.article.update({ where: { id }, data: updateArticleDto, }); } // ... }

article.update 操作將嘗試使用給定的 Article 查找 id 記錄,并使用 updateArticleDto的數據更新它。

如果在數據庫中找不到此類 Article 記錄,Prisma 將返回錯誤。在這種情況下,API 不會返回用戶友好的錯誤消息。您將在以后的教程中學習NestJS的錯誤處理。

定義DELETE /articles/:id終端節點

此端點用于刪除現有文章,此端點的路由處理程序稱為 remove。它的實現方法如下所示:

// src/articles/articles.controller.ts

@Delete(':id')
remove(@Param('id') id: string) {
return this.articlesService.remove(+id);
}

就像之前一樣,轉到 ArticlesService 并更新相應的方法:

// src/articles/articles.service.ts

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

// ...

remove(id: number) {
return This action removes a #${id} article; return this.prisma.article.delete({ where: { id } }); } }

這是針對 articles 端點的最后一個操作。恭喜您的API即將就緒!??

在 Swagger 中將終端節點分組在一起

@ApiTags 類中添加一個ArticlesController裝飾器,以便在Swagger中將所有articles端點分組在一起:

// src/articles/articles.controller.ts

import { ApiTags } from '@nestjs/swagger';

@Controller('articles')
@ApiTags('articles')
export class ArticlesController {
// ...
}

現在,該API頁面已將articles端點分組在一起。

更新 Swagger 響應類型

如果您查看 Swagger 中每個端點下的“Responses”選項卡,您會發現“Description”是空的。這是因為 Swagger 還不知道任何端點的響應類型。您將使用一些裝飾器來解決這個問題。

首先,您需要定義一個實體,Swagger 可以使用它來標識返回的實體對象的結構。為此,請更新 articles.entity.ts 文件中的 ArticleEntity 類,如下所示:

// src/articles/entities/article.entity.ts

import { Article } from '@prisma/client';
import { ApiProperty } from '@nestjs/swagger';

export class ArticleEntity implements Article {
@ApiProperty()
id: number;

@ApiProperty()
title: string;

@ApiProperty({ required: false, nullable: true })
description: string | null;

@ApiProperty()
body: string;

@ApiProperty()
published: boolean;

@ApiProperty()
createdAt: Date;

@ApiProperty()
updatedAt: Date;
}

這是Prisma Client生成的Article類型的實現,每個屬性都添加了@ApiProperty裝飾器。

現在,是時候使用正確的響應類型對控制器路由處理程序進行注釋了。NestJS 有一組用于此目的的裝飾器。

// src/articles/articles.controller.ts

import { ApiCreatedResponse, ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { ArticleEntity } from './entities/article.entity';

@Controller('articles')
@ApiTags('articles')
export class ArticlesController {
constructor(private readonly articlesService: ArticlesService) {}

@Post()
@ApiCreatedResponse({ type: ArticleEntity })
create(@Body() createArticleDto: CreateArticleDto) {
return this.articlesService.create(createArticleDto);
}

@Get()
@ApiOkResponse({ type: ArticleEntity, isArray: true })
findAll() {
return this.articlesService.findAll();
}

@Get('drafts')
@ApiOkResponse({ type: ArticleEntity, isArray: true })
findDrafts() {
return this.articlesService.findDrafts();
}

@Get(':id')
@ApiOkResponse({ type: ArticleEntity })
findOne(@Param('id') id: string) {
return this.articlesService.findOne(+id);
}

@Patch(':id')
@ApiOkResponse({ type: ArticleEntity })
update(@Param('id') id: string, @Body() updateArticleDto: UpdateArticleDto) {
return this.articlesService.update(+id, updateArticleDto);
}

@Delete(':id')
@ApiOkResponse({ type: ArticleEntity })
remove(@Param('id') id: string) {
return this.articlesService.remove(+id);
}
}

您為 @ApiOkResponseGETPATCH 端點添加了 DELETE ,為 @ApiCreatedResponse 端點添加了 POSTtype屬性用于指定返回類型,您可以在NestJS文檔中找到NestJS提供的所有響應裝飾器。

現在,Swagger 應該正確定義 API 頁面上所有端點的響應類型。

總結和結束語

恭喜!您已經成功使用NestJS構建了一個基礎的REST API。在本教程中,您完成了以下內容:

本教程的一個重要收獲是,使用NestJS和Prisma構建REST API是多么的簡單。這是一個非常高效的堆棧,用于快速構建結構良好、類型安全且可維護的后端應用程序。

您可以在GitHub上找到本項目的源代碼。如果您在使用過程中遇到任何問題,歡迎隨時在倉庫中提出問題或提交PR。

原文鏈接:https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0

上一篇:

設計和開發Web API的最佳實踐

下一篇:

使用NestJS和Prisma構建REST API:處理關系型數據
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費