@hestjs/validation 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +326 -0
- package/package.json +2 -2
package/README.md
ADDED
@@ -0,0 +1,326 @@
|
|
1
|
+
# @hestjs/validation
|
2
|
+
|
3
|
+
HestJS 验证模块,基于 TypeBox 提供强类型验证功能。
|
4
|
+
|
5
|
+
## 特性
|
6
|
+
|
7
|
+
- 🔥 基于 TypeBox 的类型安全验证
|
8
|
+
- 🎯 装饰器语法,简洁易用
|
9
|
+
- 🚀 自动类型推断和转换
|
10
|
+
- 🛡️ 内置常用验证规则
|
11
|
+
- 📦 轻量级,零额外依赖
|
12
|
+
- ⚡ 高性能验证引擎
|
13
|
+
|
14
|
+
## 安装
|
15
|
+
|
16
|
+
```bash
|
17
|
+
npm install @hestjs/validation
|
18
|
+
# 或者
|
19
|
+
yarn add @hestjs/validation
|
20
|
+
# 或者
|
21
|
+
pnpm add @hestjs/validation
|
22
|
+
```
|
23
|
+
|
24
|
+
## 快速开始
|
25
|
+
|
26
|
+
### 基础用法
|
27
|
+
|
28
|
+
```typescript
|
29
|
+
import { IsString, IsNumber, IsEmail, IsOptional } from '@hestjs/validation';
|
30
|
+
|
31
|
+
class CreateUserDto {
|
32
|
+
@IsString()
|
33
|
+
name: string;
|
34
|
+
|
35
|
+
@IsEmail()
|
36
|
+
email: string;
|
37
|
+
|
38
|
+
@IsNumber()
|
39
|
+
@IsOptional()
|
40
|
+
age?: number;
|
41
|
+
}
|
42
|
+
|
43
|
+
// 在控制器中使用
|
44
|
+
import { Body, Controller, Post } from '@hestjs/core';
|
45
|
+
|
46
|
+
@Controller('/users')
|
47
|
+
export class UserController {
|
48
|
+
@Post()
|
49
|
+
async createUser(@Body() createUserDto: CreateUserDto) {
|
50
|
+
// createUserDto 已经被自动验证
|
51
|
+
return { message: 'User created', user: createUserDto };
|
52
|
+
}
|
53
|
+
}
|
54
|
+
```
|
55
|
+
|
56
|
+
### 自定义验证
|
57
|
+
|
58
|
+
```typescript
|
59
|
+
import { IsCustom, ValidationUtils } from '@hestjs/validation';
|
60
|
+
|
61
|
+
class ProductDto {
|
62
|
+
@IsString()
|
63
|
+
name: string;
|
64
|
+
|
65
|
+
@IsCustom((value) => value > 0, '价格必须大于0')
|
66
|
+
price: number;
|
67
|
+
}
|
68
|
+
```
|
69
|
+
|
70
|
+
### 验证工具类
|
71
|
+
|
72
|
+
```typescript
|
73
|
+
import { ValidationUtils } from '@hestjs/validation';
|
74
|
+
|
75
|
+
// 验证对象
|
76
|
+
try {
|
77
|
+
const validatedUser = await ValidationUtils.validateObject(CreateUserDto, userData);
|
78
|
+
console.log('验证成功:', validatedUser);
|
79
|
+
} catch (error) {
|
80
|
+
console.log('验证失败:', error.message);
|
81
|
+
}
|
82
|
+
|
83
|
+
// 检查是否有效
|
84
|
+
const isValid = await ValidationUtils.isValid(CreateUserDto, userData);
|
85
|
+
|
86
|
+
// 获取验证错误
|
87
|
+
const errors = await ValidationUtils.getValidationErrors(CreateUserDto, userData);
|
88
|
+
|
89
|
+
// 批量验证
|
90
|
+
const { valid, errors: batchErrors } = await ValidationUtils.validateBatch(
|
91
|
+
CreateUserDto,
|
92
|
+
[userData1, userData2, userData3]
|
93
|
+
);
|
94
|
+
|
95
|
+
// 部分验证
|
96
|
+
const partialUser = await ValidationUtils.validatePartial(CreateUserDto, {
|
97
|
+
name: 'John' // 只验证提供的字段
|
98
|
+
});
|
99
|
+
```
|
100
|
+
|
101
|
+
## 可用装饰器
|
102
|
+
|
103
|
+
### 基础类型验证
|
104
|
+
|
105
|
+
- `@IsString()` - 字符串验证
|
106
|
+
- `@IsNumber()` - 数字验证
|
107
|
+
- `@IsBoolean()` - 布尔值验证
|
108
|
+
- `@IsArray()` - 数组验证
|
109
|
+
- `@IsObject()` - 对象验证
|
110
|
+
|
111
|
+
### 字符串验证
|
112
|
+
|
113
|
+
- `@IsEmail()` - 邮箱格式验证
|
114
|
+
- `@IsUrl()` - URL 格式验证
|
115
|
+
- `@IsUuid()` - UUID 格式验证
|
116
|
+
- `@MinLength(min)` - 最小长度
|
117
|
+
- `@MaxLength(max)` - 最大长度
|
118
|
+
- `@Matches(pattern)` - 正则表达式匹配
|
119
|
+
|
120
|
+
### 数字验证
|
121
|
+
|
122
|
+
- `@Min(min)` - 最小值
|
123
|
+
- `@Max(max)` - 最大值
|
124
|
+
- `@IsPositive()` - 正数
|
125
|
+
- `@IsNegative()` - 负数
|
126
|
+
- `@IsInt()` - 整数
|
127
|
+
|
128
|
+
### 日期验证
|
129
|
+
|
130
|
+
- `@IsDate()` - 日期验证
|
131
|
+
- `@IsDateString()` - 日期字符串验证
|
132
|
+
|
133
|
+
### 其他
|
134
|
+
|
135
|
+
- `@IsOptional()` - 可选字段
|
136
|
+
- `@IsEnum(enumObject)` - 枚举验证
|
137
|
+
- `@IsCustom(validator, message)` - 自定义验证
|
138
|
+
|
139
|
+
## 高级用法
|
140
|
+
|
141
|
+
### 嵌套对象验证
|
142
|
+
|
143
|
+
```typescript
|
144
|
+
class AddressDto {
|
145
|
+
@IsString()
|
146
|
+
street: string;
|
147
|
+
|
148
|
+
@IsString()
|
149
|
+
city: string;
|
150
|
+
|
151
|
+
@IsString()
|
152
|
+
@Matches(/^\d{5}$/)
|
153
|
+
zipCode: string;
|
154
|
+
}
|
155
|
+
|
156
|
+
class UserDto {
|
157
|
+
@IsString()
|
158
|
+
name: string;
|
159
|
+
|
160
|
+
@IsEmail()
|
161
|
+
email: string;
|
162
|
+
|
163
|
+
@ValidateNested()
|
164
|
+
@Type(() => AddressDto)
|
165
|
+
address: AddressDto;
|
166
|
+
}
|
167
|
+
```
|
168
|
+
|
169
|
+
### 数组验证
|
170
|
+
|
171
|
+
```typescript
|
172
|
+
class CreateUsersDto {
|
173
|
+
@IsArray()
|
174
|
+
@ValidateNested({ each: true })
|
175
|
+
@Type(() => CreateUserDto)
|
176
|
+
users: CreateUserDto[];
|
177
|
+
}
|
178
|
+
```
|
179
|
+
|
180
|
+
### 条件验证
|
181
|
+
|
182
|
+
```typescript
|
183
|
+
class ConditionalDto {
|
184
|
+
@IsString()
|
185
|
+
type: 'email' | 'phone';
|
186
|
+
|
187
|
+
@IsOptional()
|
188
|
+
@IsEmail()
|
189
|
+
@ValidateIf(o => o.type === 'email')
|
190
|
+
email?: string;
|
191
|
+
|
192
|
+
@IsOptional()
|
193
|
+
@IsPhoneNumber()
|
194
|
+
@ValidateIf(o => o.type === 'phone')
|
195
|
+
phone?: string;
|
196
|
+
}
|
197
|
+
```
|
198
|
+
|
199
|
+
## 配置选项
|
200
|
+
|
201
|
+
### 全局配置
|
202
|
+
|
203
|
+
```typescript
|
204
|
+
import { ValidationModule } from '@hestjs/validation';
|
205
|
+
|
206
|
+
@Module({
|
207
|
+
imports: [
|
208
|
+
ValidationModule.forRoot({
|
209
|
+
whitelist: true, // 移除未装饰的属性
|
210
|
+
forbidNonWhitelisted: true, // 禁止非白名单属性
|
211
|
+
transform: true, // 自动类型转换
|
212
|
+
disableErrorMessages: false, // 禁用错误消息
|
213
|
+
dismissDefaultMessages: false, // 忽略默认消息
|
214
|
+
validationError: { target: false }, // 错误对象配置
|
215
|
+
}),
|
216
|
+
],
|
217
|
+
})
|
218
|
+
export class AppModule {}
|
219
|
+
```
|
220
|
+
|
221
|
+
### 管道配置
|
222
|
+
|
223
|
+
```typescript
|
224
|
+
import { ValidationPipe } from '@hestjs/validation';
|
225
|
+
|
226
|
+
// 在控制器方法中使用
|
227
|
+
@Post()
|
228
|
+
@UsePipes(new ValidationPipe({
|
229
|
+
transform: true,
|
230
|
+
whitelist: true,
|
231
|
+
}))
|
232
|
+
async createUser(@Body() createUserDto: CreateUserDto) {
|
233
|
+
return createUserDto;
|
234
|
+
}
|
235
|
+
```
|
236
|
+
|
237
|
+
## 错误处理
|
238
|
+
|
239
|
+
验证错误会抛出 `ValidationException`,包含详细的错误信息:
|
240
|
+
|
241
|
+
```typescript
|
242
|
+
try {
|
243
|
+
await ValidationUtils.validateObject(CreateUserDto, invalidData);
|
244
|
+
} catch (error) {
|
245
|
+
if (error instanceof ValidationException) {
|
246
|
+
console.log('验证错误:', error.getMessages());
|
247
|
+
console.log('错误详情:', error.getErrors());
|
248
|
+
}
|
249
|
+
}
|
250
|
+
```
|
251
|
+
|
252
|
+
## TypeScript 支持
|
253
|
+
|
254
|
+
完全支持 TypeScript,提供类型安全的验证:
|
255
|
+
|
256
|
+
```typescript
|
257
|
+
// 自动类型推断
|
258
|
+
const user: CreateUserDto = await ValidationUtils.validateObject(CreateUserDto, data);
|
259
|
+
|
260
|
+
// 生成 TypeBox Schema
|
261
|
+
const schema = ValidationUtils.generateSchema(CreateUserDto);
|
262
|
+
```
|
263
|
+
|
264
|
+
## 与 HestJS 集成
|
265
|
+
|
266
|
+
### 自动验证
|
267
|
+
|
268
|
+
```typescript
|
269
|
+
import { Body, Controller, Post } from '@hestjs/core';
|
270
|
+
import { UseValidation } from '@hestjs/validation';
|
271
|
+
|
272
|
+
@Controller('/api')
|
273
|
+
@UseValidation() // 启用自动验证
|
274
|
+
export class ApiController {
|
275
|
+
@Post('/users')
|
276
|
+
async createUser(@Body() userData: CreateUserDto) {
|
277
|
+
// userData 已自动验证
|
278
|
+
return userData;
|
279
|
+
}
|
280
|
+
}
|
281
|
+
```
|
282
|
+
|
283
|
+
### 自定义验证拦截器
|
284
|
+
|
285
|
+
```typescript
|
286
|
+
import { UseInterceptors } from '@hestjs/core';
|
287
|
+
import { ValidationInterceptor } from '@hestjs/validation';
|
288
|
+
|
289
|
+
@Controller('/api')
|
290
|
+
@UseInterceptors(ValidationInterceptor)
|
291
|
+
export class ApiController {
|
292
|
+
// ...
|
293
|
+
}
|
294
|
+
```
|
295
|
+
|
296
|
+
## 性能
|
297
|
+
|
298
|
+
- 基于 TypeBox 的高性能验证引擎
|
299
|
+
- 支持 JIT 编译的验证函数
|
300
|
+
- 最小化运行时开销
|
301
|
+
- 支持缓存验证结果
|
302
|
+
|
303
|
+
## 许可证
|
304
|
+
|
305
|
+
MIT
|
306
|
+
|
307
|
+
## 贡献
|
308
|
+
|
309
|
+
欢迎提交 Issue 和 Pull Request!
|
310
|
+
|
311
|
+
## 更新日志
|
312
|
+
|
313
|
+
### v0.1.2
|
314
|
+
- 新增 ValidationUtils 工具类
|
315
|
+
- 支持批量验证和部分验证
|
316
|
+
- 优化错误消息格式
|
317
|
+
- 提升验证性能
|
318
|
+
|
319
|
+
### v0.1.1
|
320
|
+
- 修复 TypeBox 兼容性问题
|
321
|
+
- 优化装饰器实现
|
322
|
+
|
323
|
+
### v0.1.0
|
324
|
+
- 初始版本发布
|
325
|
+
- 基础验证装饰器
|
326
|
+
- TypeBox 集成
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@hestjs/validation",
|
3
|
-
"version": "0.1.
|
3
|
+
"version": "0.1.4",
|
4
4
|
"description": "HestJS Validation Module with TypeBox",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"types": "dist/index.d.ts",
|
@@ -14,7 +14,7 @@
|
|
14
14
|
"check-types": "tsc --noEmit"
|
15
15
|
},
|
16
16
|
"dependencies": {
|
17
|
-
"@hestjs/core": "
|
17
|
+
"@hestjs/core": "^0.1.0",
|
18
18
|
"@sinclair/typebox": "^0.32.15",
|
19
19
|
"reflect-metadata": "^0.2.2"
|
20
20
|
},
|