nestjs-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNestJS Patterns
NestJS 模式实践
Module Structure
模块结构
src/modules/users/
├── users.module.ts
├── users.controller.ts
├── users.service.ts
├── dto/
│ ├── create-user.dto.ts
│ └── update-user.dto.ts
├── entities/
│ └── user.entity.ts
└── guards/
└── user-owner.guard.tssrc/modules/users/
├── users.module.ts
├── users.controller.ts
├── users.service.ts
├── dto/
│ ├── create-user.dto.ts
│ └── update-user.dto.ts
├── entities/
│ └── user.entity.ts
└── guards/
└── user-owner.guard.tsKey Patterns
核心模式
Module Definition
模块定义
typescript
@Module({
imports: [PrismaModule],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}typescript
@Module({
imports: [PrismaModule],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}DTOs with Validation
带校验的DTO
typescript
import { IsEmail, IsString, MinLength } from 'class-validator'
export class CreateUserDto {
@IsEmail()
email: string
@IsString()
@MinLength(8)
password: string
}typescript
import { IsEmail, IsString, MinLength } from 'class-validator'
export class CreateUserDto {
@IsEmail()
email: string
@IsString()
@MinLength(8)
password: string
}Service Pattern
服务模式
typescript
@Injectable()
export class UsersService {
constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateUserDto) {
return this.prisma.user.create({ data: dto })
}
async findOne(id: string) {
const user = await this.prisma.user.findUnique({ where: { id } })
if (!user) throw new NotFoundException()
return user
}
}typescript
@Injectable()
export class UsersService {
constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateUserDto) {
return this.prisma.user.create({ data: dto })
}
async findOne(id: string) {
const user = await this.prisma.user.findUnique({ where: { id } })
if (!user) throw new NotFoundException()
return user
}
}Controller Pattern
控制器模式
typescript
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
@HttpCode(HttpStatus.CREATED)
create(@Body() dto: CreateUserDto) {
return this.usersService.create(dto)
}
@Get(':id')
@UseGuards(JwtAuthGuard)
findOne(@Param('id') id: string) {
return this.usersService.findOne(id)
}
}typescript
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
@HttpCode(HttpStatus.CREATED)
create(@Body() dto: CreateUserDto) {
return this.usersService.create(dto)
}
@Get(':id')
@UseGuards(JwtAuthGuard)
findOne(@Param('id') id: string) {
return this.usersService.findOne(id)
}
}Guards
守卫(Guards)
typescript
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
@Injectable()
export class ResourceOwnerGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest()
return request.user.id === request.params.id
}
}typescript
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
@Injectable()
export class ResourceOwnerGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest()
return request.user.id === request.params.id
}
}Custom Decorators
自定义装饰器
typescript
export const CurrentUser = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest()
return data ? request.user?.[data] : request.user
},
)
// Usage: @CurrentUser() user or @CurrentUser('id') idtypescript
export const CurrentUser = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = context.switchToHttp().getRequest()
return data ? request.user?.[data] : request.user
},
)
// 用法:@CurrentUser() user 或 @CurrentUser('id') idForbidden Patterns
禁用模式
- Business logic in controllers
- Returning sensitive data (passwords)
- No validation on inputs
- Hardcoded secrets
- Skipping error handling
- 在控制器中编写业务逻辑
- 返回敏感数据(如密码)
- 不对输入进行校验
- 硬编码密钥
- 跳过错误处理