安裝TypeORM
透過 Nest 官方支援的 TypeORM 來建立 DB。 首先安裝 TypeORM 相關的內容,並使用 typeorm init 來快速建立 typeorm 專案。
1 2
| $ yarn add @nestjs/typeorm typeorm@0.2 mysql2 $ yarn typeorm init
|
此時你的目錄結構會變成這樣
接著配置Mysql
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UserModule } from './user/user.module';
@Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: '123456', database: 'test', autoLoadEntities: true, synchronize: true, }), UserModule, ], controllers: [], providers: [], }) export class AppModule {}
|
Note: 這邊注意,一般來說不會直接將資料庫帳密填入,因為是DEMO,我們直接在code中配置
我這邊透過docker-compose啟動mysql,如果需要,可參考 Andy’s Dev Tool
1
| $ docker-compose -f docker-compose.yaml up -d mysql
|
開始進行簡單的CRUD
Nest CLI可以自動產生範本,跟許多知名的framework一樣,可以快速產生CRUD,我們就先透過這方式,並添加之前所述的API Doc描述吧。
1 2 3
| # $ nest g resource [xxxx] # xxxx 我習慣使用table name, 這邊就用user當範例吧 $ nest g resource user
|
CLI會問你要產生怎樣的API,這邊先選REST吧,並且透過Nest CLI產生範本。
你會看到產生了許多檔案,我會將一些檔案刪除掉,因為有些是透過typeorm init產生的,但我們並不需要,刪除後結果如下~
首先我們先編輯 user.entity.ts,為了示範,把基本的型態都建立一個
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity() export class User { @PrimaryGeneratedColumn() id: number;
@Column() name: string;
@Column() phone: string;
@Column() age: number;
@Column() createTime: Date;
@Column() updateTime: Date;
@Column() isDelete: boolean; }
|
接著我們修改一下dto,這邊有兩個檔案,一個是新增一個是更新。
dto,因為api的request需要要進行驗證~所以我們先安裝一下所需套件
1
| $ yarn add class-validator class-transformer
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import { IsNotEmpty, IsOptional, IsString } from 'class-validator'; import { Column } from 'typeorm';
export class CreateUserDto { @IsString() @IsNotEmpty() name: string;
@IsString() @IsNotEmpty() phone: string;
@Column() @IsNotEmpty() age: number;
@Column() createTime: Date;
@Column() updateTime: Date;
@Column() @IsOptional() isDelete: boolean; }
|
編輯module
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { Module } from '@nestjs/common'; import { UserService } from './user.service'; import { UserController } from './user.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './entities/user.entity';
@Module({ imports: [TypeOrmModule.forFeature([User])], controllers: [UserController], providers: [UserService], }) export class UserModule {}
|
這時候我們重新啟動一下,就會看到db裡面幫你建立了user table,且裡面的欄位都建立好了,而針對User的CRUD的路由也都出現了唷~
接下來修改一下service拉,準備把Repository注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import { Injectable } from '@nestjs/common'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { InjectRepository } from '@nestjs/typeorm'; import { User } from './entities/user.entity'; import { Repository } from 'typeorm';
@Injectable() export class UserService { constructor( @InjectRepository(User) private userRepository: Repository<User>, ) {} create(createUserDto: CreateUserDto) { createUserDto.createTime = createUserDto.updateTime = new Date(); createUserDto.isDelete = false; return this.userRepository.save(createUserDto); }
findAll() { return this.userRepository.find(); }
findOne(id: number) { return this.userRepository.findByIds([id]); }
update(id: number, updateUserDto: UpdateUserDto) { return this.userRepository.update(id, updateUserDto); }
remove(id: number) { return this.userRepository.delete(id); } }
|
接下來為了API DOC進行小微調,controller 的微調是為了定義DOC的描述和指定dto,這邊就進行POST的示範
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| import { Controller, Get, Post, Body, Patch, Param, Delete, } from '@nestjs/common'; import { UserService } from './user.service'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { ApiOperation, ApiTags, ApiQuery, ApiBody, ApiResponse, } from '@nestjs/swagger';
@Controller('user') @ApiTags('User') export class UserController { constructor(private readonly userService: UserService) {}
@Post() @ApiOperation({ description: '新增一筆user使用' }) @ApiBody({ type: CreateUserDto, description: '新增user' }) create(@Body() createUserDto: CreateUserDto) { return this.userService.create(createUserDto); }
@Get() @ApiOperation({ description: '取得user使用' }) @ApiBody({ type: CreateUserDto, description: '取得user' }) findAll() { return this.userService.findAll(); }
@Get(':id') @ApiOperation({ description: '獲取一個user' }) @ApiBody({ type: CreateUserDto, description: '獲取一個user' }) findOne(@Param('id') id: string) { return this.userService.findOne(+id); }
@Patch(':id') @ApiOperation({ description: '更新user' }) @ApiBody({ type: UpdateUserDto, description: '更新user' }) update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) { return this.userService.update(+id, updateUserDto); }
@Delete(':id') @ApiOperation({ description: '刪除user' }) @ApiBody({ type: CreateUserDto, description: '刪除user' }) remove(@Param('id') id: string) { return this.userService.remove(+id); } }
|
dto也要進行微調,dto的微調是為了進行參數驗證
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import { IsNotEmpty, IsOptional, IsString } from 'class-validator'; import { Column } from 'typeorm'; import { ApiProperty } from '@nestjs/swagger';
export class CreateUserDto { @IsString() @IsNotEmpty() @ApiProperty({ description: '姓名' }) name: string;
@IsString() @IsNotEmpty() @ApiProperty({ description: '手機' }) phone: string;
@Column() @IsNotEmpty() @ApiProperty({ description: '年齡', type: Number, minimum: 18, default: 20, }) age: number;
@Column() createTime: Date;
@Column() updateTime: Date;
@Column() @IsOptional() isDelete: boolean; }
|
透過API DOC新增一筆資料~並確認~
結論
透過NestJs可以快速產生CRUD,以及API DOC,算是頗方便的~其實還有很多東西可以說,例如Auth和其他重要功能,這之後有空再說吧~
參考連結