# NestJS 常用装饰器速查

## Controller 装饰器

### 路由装饰器
```typescript
@Controller('api/v1/users')        // 定义路由前缀
@Get()                            // GET 请求
@Post()                           // POST 请求
@Put(':id')                       // PUT 请求，带参数
@Patch(':id')                     // PATCH 请求
@Delete(':id')                    // DELETE 请求
```

### 参数装饰器
```typescript
@Param('id')                      // 路径参数
@Query()                          // 查询参数
@Body()                           // 请求体
@Headers('authorization')         // 请求头
@Req()                           // 原始 request 对象
@Res()                           // 原始 response 对象（慎用）
```

### 守卫装饰器（IAM 四层模型，PR #138）
```typescript
@UseGuards(JwtAuthGuard, PermissionsGuard)  // controller 顶部
@RequirePermissions('user:read')            // ✅ 权限码 'resource:action'
@RequirePermissions('user:read', 'user:update')  // 多权限 = AND
```

**已废弃，禁用（导出已删，import 会编译报错）**：
- `@RequireOrganizationPermissions(...)` — 数据范围由 DataScope 管理，不再用 Scope 装饰器
- `@RequireGlobalPermissions(...)` — 同上
- `@Roles('admin', 'hr')` — 角色判定改用 `isAdministrator(user)` util；细粒度判断走权限码

### 拦截器装饰器
```typescript
@UseInterceptors(TransformInterceptor)  // 统一封包 success/data/message/timestamp/path
@UseInterceptors(FileInterceptor('file')) // 文件上传
@UseInterceptors(CacheInterceptor)     // 缓存
```

### IAM 治理装饰器（PR #138）
```typescript
// Controller / handler 级
// 强制：凡 POST/PUT/PATCH/DELETE 必标 @Auditable()。漏标会被 pre-commit
// (scripts/ops/check-controller-auditable.sh) 告警；过渡期 warn-only，后续阻断。
@Auditable()                  // 该方法走 AuditLogInterceptor，自动记 audit_log
@Sensitive()                  // 敏感操作（密码/权限/删除）叠加：5 年保留
@Financial()                  // 财务操作（支付/退款）叠加：7 年保留 + isFinancial 标记

// Service 级
@DataScope({ resource: 'order' })   // 列表方法注入数据权限 where 子句（DataScopeInterceptor 全局接住）
@SkipAssertAccess('显式理由')       // service 按 ID 取资源但不需 IDOR 校验时必标
```

## Service 装饰器

```typescript
@Injectable()                     // 标记为可注入服务
```

## DTO 验证装饰器

### 字符串验证
```typescript
@IsString()                       // 是字符串
@IsNotEmpty()                     // 非空
@MinLength(8)                     // 最小长度
@MaxLength(255)                   // 最大长度
@Matches(/^[a-zA-Z0-9]+$/)        // 正则匹配
```

### 数字验证
```typescript
@IsNumber()                       // 是数字
@IsInt()                         // 是整数
@Min(0)                          // 最小值
@Max(100)                        // 最大值
@IsPositive()                    // 正数
```

### 邮箱和 URL
```typescript
@IsEmail()                        // 邮箱格式
@IsUrl()                         // URL 格式
```

### 日期验证
```typescript
@IsDate()                        // 是日期
@Type(() => Date)                // 类型转换
```

### 数组验证
```typescript
@IsArray()                       // 是数组
@ArrayMinSize(1)                 // 数组最小长度
@ArrayMaxSize(10)                // 数组最大长度
```

### 可选字段
```typescript
@IsOptional()                    // 字段可选
```

### 嵌套对象
```typescript
@ValidateNested()                // 验证嵌套对象
@Type(() => NestedDto)           // 类型转换
```

## 示例 DTO

```typescript
export class CreateUserDto {
  @IsString()
  @IsNotEmpty()
  @MinLength(3)
  @MaxLength(50)
  username: string;

  @IsEmail()
  @IsNotEmpty()
  email: string;

  @IsString()
  @IsNotEmpty()
  @MinLength(8)
  @Matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, {
    message: '密码必须包含大小写字母和数字'
  })
  password: string;

  @IsArray()
  @ArrayMinSize(1)
  @IsString({ each: true })
  roles: string[];

  @IsOptional()
  @IsString()
  department?: string;
}
```

## 常用 HTTP 状态码

```typescript
HttpStatus.OK                    // 200
HttpStatus.CREATED               // 201
HttpStatus.NO_CONTENT            // 204
HttpStatus.BAD_REQUEST           // 400
HttpStatus.UNAUTHORIZED          // 401
HttpStatus.FORBIDDEN             // 403
HttpStatus.NOT_FOUND             // 404
HttpStatus.CONFLICT              // 409
HttpStatus.INTERNAL_SERVER_ERROR // 500
```
