koatty_validation 1.3.6 → 1.6.0

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/dist/LICENSE CHANGED
@@ -1,29 +1,29 @@
1
- BSD 3-Clause License
2
-
3
- Copyright (c) 2020, Koatty
4
- All rights reserved.
5
-
6
- Redistribution and use in source and binary forms, with or without
7
- modification, are permitted provided that the following conditions are met:
8
-
9
- 1. Redistributions of source code must retain the above copyright notice, this
10
- list of conditions and the following disclaimer.
11
-
12
- 2. Redistributions in binary form must reproduce the above copyright notice,
13
- this list of conditions and the following disclaimer in the documentation
14
- and/or other materials provided with the distribution.
15
-
16
- 3. Neither the name of the copyright holder nor the names of its
17
- contributors may be used to endorse or promote products derived from
18
- this software without specific prior written permission.
19
-
20
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2020, Koatty
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/dist/README.md CHANGED
@@ -1,116 +1,363 @@
1
- # koatty_validation
2
- Validation Util for Koatty. Based on class-validator, extended parameter type checking and restricted attribute functions.
3
-
4
-
5
- # User Decorators
6
-
7
- * @IsDefined
8
- * @IsCnName
9
- * @IsIdNumber
10
- * @IsZipCode
11
- * @IsMobile
12
- * @IsPlateNumber
13
- * @IsEmail
14
- * @IsIP
15
- * @IsPhoneNumber
16
- * @IsUrl
17
- * @IsHash
18
- * @IsNotEmpty
19
- * @Equals
20
- * @NotEquals
21
- * @Contains
22
- * @IsIn
23
- * @IsNotIn
24
- * @IsDate
25
- * @Gt
26
- * @Gte
27
- * @Lt
28
- * @Lte
29
-
30
- * @Valid
31
- * @Validated
32
-
33
-
34
-
35
- ```js
36
-
37
- export class Controller {
38
-
39
- Test(@Valid("IsNotEmpty", "can not be empty!!") id: number){
40
- //todo
41
- }
42
-
43
- @Validated() // use dto validation
44
- TestDto(user: UserDTO) {
45
-
46
- }
47
- }
48
-
49
- export class UserDTO {
50
- @IsNotEmpty({ message: "can not be empty!!" })
51
- phoneNum: string;
52
-
53
- @IsCnName({ message: "must be cn name"})
54
- userName: string;
55
- }
56
-
57
- ```
58
-
59
- # Validator for manual
60
-
61
- ## FunctionValidator
62
-
63
- * IsCnName
64
- * IsIdNumber
65
- * IsZipCode
66
- * IsMobile
67
- * IsPlateNumber
68
- * IsEmail
69
- * IsIP
70
- * IsPhoneNumber
71
- * IsUrl
72
- * IsHash
73
- * IsNotEmpty
74
- * Equals
75
- * NotEquals
76
- * Contains
77
- * IsIn
78
- * IsNotIn
79
- * IsDate
80
- * Gt
81
- * Gte
82
- * Lt
83
- * Lte
84
-
85
- exp:
86
-
87
- ```js
88
- const str = "";
89
- // throw Error
90
- FunctionValidator.IsNotEmpty(str, "cannot be empty");
91
- FunctionValidator.Contains(str, {message: "must contain s", value: "s"});
92
- //
93
- if (!ValidFuncs.IsNotEmpty(str)) {
94
- console.log("empty");
95
- }
96
- ```
97
-
98
- ## ClassValidator
99
-
100
- exp:
101
-
102
- ```js
103
- class SchemaClass {
104
- @IsDefined
105
- id: number;
106
-
107
- @IsNotEmpty
108
- name: string;
109
- }
110
-
111
-
112
- ClassValidator.valid(SchemaClass, {name: ''}).catch(err => {
113
- console.log(err);
114
- })
115
- ```
116
-
1
+ # koatty_validation
2
+
3
+ 基于 class-validator 扩展的 Koatty 验证工具库,支持中文本地化验证规则、自定义装饰器、性能缓存和错误处理。
4
+
5
+ [![npm version](https://badge.fury.io/js/koatty_validation.svg)](https://badge.fury.io/js/koatty_validation)
6
+ [![Node.js CI](https://github.com/koatty/koatty_validation/workflows/Node.js%20CI/badge.svg)](https://github.com/koatty/koatty_validation/actions)
7
+
8
+ ## ✨ 特性
9
+
10
+ - 🚀 **高性能**: 内置缓存机制,提升验证性能
11
+ - 🌏 **中文支持**: 内置中文验证规则(姓名、身份证、手机号等)
12
+ - 🔧 **自定义装饰器**: 支持装饰器工厂模式,轻松创建自定义验证器
13
+ - 📊 **性能监控**: 内置性能监控和缓存统计
14
+ - 🎯 **错误处理**: 多语言错误信息支持
15
+ - 📦 **TypeScript**: 完整的 TypeScript 支持
16
+
17
+ ## 📦 安装
18
+
19
+ ```bash
20
+ npm install koatty_validation
21
+ #
22
+ yarn add koatty_validation
23
+ ```
24
+
25
+ ## 🎯 快速开始
26
+
27
+ ### 基础用法
28
+
29
+ ```typescript
30
+ import { IsNotEmpty, IsCnName, IsMobile, Valid, Validated } from 'koatty_validation';
31
+
32
+ // 在控制器中使用参数验证
33
+ export class Controller {
34
+ // 参数验证
35
+ Test(@Valid("IsNotEmpty", "不能为空") id: number) {
36
+ // 业务逻辑
37
+ }
38
+
39
+ // DTO 验证
40
+ @Validated()
41
+ TestDto(user: UserDTO) {
42
+ // 自动验证 UserDTO
43
+ }
44
+ }
45
+
46
+ // 定义 DTO 类
47
+ export class UserDTO {
48
+ @IsNotEmpty({ message: "手机号不能为空" })
49
+ @IsMobile({ message: "手机号格式不正确" })
50
+ phoneNum: string;
51
+
52
+ @IsCnName({ message: "姓名必须是有效的中文姓名" })
53
+ userName: string;
54
+ }
55
+ ```
56
+
57
+ ## 📋 可用装饰器
58
+
59
+ ### 🇨🇳 中文验证装饰器
60
+
61
+ ```typescript
62
+ @IsCnName() // 中文姓名
63
+ @IsIdNumber() // 身份证号
64
+ @IsMobile() // 手机号
65
+ @IsZipCode() // 邮政编码
66
+ @IsPlateNumber() // 车牌号
67
+ ```
68
+
69
+ ### 🌐 通用验证装饰器
70
+
71
+ ```typescript
72
+ @IsNotEmpty() // 非空
73
+ @IsEmail() // 邮箱
74
+ @IsIP() // IP地址
75
+ @IsPhoneNumber() // 国际电话号码
76
+ @IsUrl() // URL
77
+ @IsHash() // 哈希值
78
+ @IsDate() // 日期
79
+ ```
80
+
81
+ ### 🔢 数值比较装饰器
82
+
83
+ ```typescript
84
+ @Gt(10) // 大于
85
+ @Gte(10) // 大于等于
86
+ @Lt(100) // 小于
87
+ @Lte(100) // 小于等于
88
+ @Equals('value') // 等于
89
+ @NotEquals('x') // 不等于
90
+ ```
91
+
92
+ ### 📝 字符串验证装饰器
93
+
94
+ ```typescript
95
+ @Contains('test') // 包含字符串
96
+ @IsIn(['a', 'b', 'c']) // 在数组中
97
+ @IsNotIn(['x', 'y', 'z']) // 不在数组中
98
+ ```
99
+
100
+ ### 🛠️ 控制装饰器
101
+
102
+ ```typescript
103
+ @Valid(rule, options) // 参数验证
104
+ @Validated() // DTO验证
105
+ @Expose() // 暴露属性
106
+ @IsDefined() // 已定义(Expose别名)
107
+ ```
108
+
109
+ ## 🔧 自定义装饰器
110
+
111
+ ### 使用装饰器工厂创建自定义验证器
112
+
113
+ ```typescript
114
+ import { createSimpleDecorator, createParameterizedDecorator } from 'koatty_validation';
115
+
116
+ // 简单装饰器
117
+ export const IsPositiveInteger = createSimpleDecorator(
118
+ 'IsPositiveInteger',
119
+ (value: any) => {
120
+ const num = Number(value);
121
+ return Number.isInteger(num) && num > 0;
122
+ },
123
+ 'must be a positive integer'
124
+ );
125
+
126
+ // 带参数的装饰器
127
+ export const InRange = createParameterizedDecorator(
128
+ 'InRange',
129
+ (value: any, min: number, max: number) => {
130
+ const num = Number(value);
131
+ return num >= min && num <= max;
132
+ },
133
+ 'must be between $constraint1 and $constraint2'
134
+ );
135
+
136
+ // 使用自定义装饰器
137
+ class ProductDto {
138
+ @IsPositiveInteger()
139
+ quantity: number;
140
+
141
+ @InRange(0, 100)
142
+ discountPercent: number;
143
+ }
144
+ ```
145
+
146
+ ### 高级自定义装饰器
147
+
148
+ ```typescript
149
+ import { createValidationDecorator } from 'koatty_validation';
150
+
151
+ // 复杂验证逻辑
152
+ export function IsStrongPassword(validationOptions?: ValidationOptions) {
153
+ return createValidationDecorator({
154
+ name: 'IsStrongPassword',
155
+ validator: (value: string) => {
156
+ const hasLowercase = /[a-z]/.test(value);
157
+ const hasUppercase = /[A-Z]/.test(value);
158
+ const hasNumbers = /\d/.test(value);
159
+ const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value);
160
+ return value.length >= 8 && hasLowercase && hasUppercase && hasNumbers && hasSpecialChar;
161
+ },
162
+ defaultMessage: 'password must be at least 8 characters with uppercase, lowercase, number and special character',
163
+ requiresValue: false
164
+ })(validationOptions);
165
+ }
166
+ ```
167
+
168
+ ## 🚀 性能优化
169
+
170
+ ### 缓存预热
171
+
172
+ ```typescript
173
+ import { warmupCaches, performanceMonitor } from 'koatty_validation';
174
+
175
+ // 应用启动时预热缓存
176
+ await warmupCaches();
177
+
178
+ // 性能监控
179
+ const timer = performanceMonitor.startTimer('validation');
180
+ // ... 执行验证
181
+ timer(); // 结束计时
182
+
183
+ // 获取性能报告
184
+ const report = performanceMonitor.getReport();
185
+ console.log(report);
186
+ ```
187
+
188
+ ### 缓存统计
189
+
190
+ ```typescript
191
+ import { getAllCacheStats, clearAllCaches } from 'koatty_validation';
192
+
193
+ // 获取缓存统计
194
+ const stats = getAllCacheStats();
195
+ console.log(stats);
196
+
197
+ // 清理缓存(用于测试或内存管理)
198
+ clearAllCaches();
199
+ ```
200
+
201
+ ## 🌐 错误处理
202
+
203
+ ### 多语言支持
204
+
205
+ ```typescript
206
+ import { setValidationLanguage, KoattyValidationError } from 'koatty_validation';
207
+
208
+ // 设置中文错误信息
209
+ setValidationLanguage('zh');
210
+
211
+ // 自定义错误处理
212
+ try {
213
+ await validate(userDto);
214
+ } catch (error) {
215
+ if (error instanceof KoattyValidationError) {
216
+ console.log('验证错误:', error.message);
217
+ console.log('错误详情:', error.errors);
218
+ }
219
+ }
220
+ ```
221
+
222
+ ### 错误格式化
223
+
224
+ ```typescript
225
+ import { errorFormatter } from 'koatty_validation';
226
+
227
+ const errors = await validate(dto);
228
+ if (errors.length > 0) {
229
+ const formatted = errorFormatter(errors, 'zh');
230
+ console.log(formatted);
231
+ }
232
+ ```
233
+
234
+ ## 📖 手动验证
235
+
236
+ ### FunctionValidator
237
+
238
+ ```typescript
239
+ import { FunctionValidator } from 'koatty_validation';
240
+
241
+ // 手动验证并抛出错误
242
+ try {
243
+ FunctionValidator.IsNotEmpty("", "不能为空");
244
+ FunctionValidator.IsMobile("123", "手机号格式不正确");
245
+ } catch (error) {
246
+ console.log(error.message);
247
+ }
248
+
249
+ // 带选项的验证
250
+ FunctionValidator.Contains(str, {
251
+ message: "必须包含字母s",
252
+ value: "s"
253
+ });
254
+ ```
255
+
256
+ ### ValidFuncs (纯函数)
257
+
258
+ ```typescript
259
+ import { ValidFuncs } from 'koatty_validation';
260
+
261
+ // 返回布尔值的验证函数
262
+ if (!ValidFuncs.IsNotEmpty(str)) {
263
+ console.log("字符串为空");
264
+ }
265
+
266
+ if (!ValidFuncs.IsCnName("张三")) {
267
+ console.log("不是有效的中文姓名");
268
+ }
269
+
270
+ if (!ValidFuncs.IsMobile("13812345678")) {
271
+ console.log("不是有效的手机号");
272
+ }
273
+ ```
274
+
275
+ ### ClassValidator
276
+
277
+ ```typescript
278
+ import { ClassValidator } from 'koatty_validation';
279
+
280
+ class UserSchema {
281
+ @IsDefined()
282
+ id: number;
283
+
284
+ @IsNotEmpty()
285
+ name: string;
286
+
287
+ @IsMobile()
288
+ phone: string;
289
+ }
290
+
291
+ // 验证对象
292
+ try {
293
+ const result = await ClassValidator.valid(UserSchema, {
294
+ id: 1,
295
+ name: '',
296
+ phone: '123'
297
+ });
298
+ } catch (error) {
299
+ console.log('验证失败:', error.message);
300
+ }
301
+
302
+ // 转换并验证
303
+ const validatedData = await ClassValidator.valid(UserSchema, rawData, true);
304
+ ```
305
+
306
+ ## 📚 更多示例
307
+
308
+ 查看 [examples](./examples/) 目录获取更多使用示例:
309
+
310
+ - [基础用法示例](./examples/basic-usage.ts)
311
+ - [自定义装饰器示例](./examples/custom-decorators-example.ts)
312
+ - [完整使用示例](./examples/usage-example.ts)
313
+
314
+ ## 🔍 可用验证函数
315
+
316
+ 所有验证函数都同时提供装饰器和函数两种形式:
317
+
318
+ | 函数名 | 描述 | 示例 |
319
+ |--------|------|------|
320
+ | IsCnName | 中文姓名 | `ValidFuncs.IsCnName("张三")` |
321
+ | IsIdNumber | 身份证号 | `ValidFuncs.IsIdNumber("110101199001011234")` |
322
+ | IsMobile | 手机号 | `ValidFuncs.IsMobile("13812345678")` |
323
+ | IsZipCode | 邮政编码 | `ValidFuncs.IsZipCode("100000")` |
324
+ | IsPlateNumber | 车牌号 | `ValidFuncs.IsPlateNumber("京A12345")` |
325
+ | IsEmail | 邮箱 | `ValidFuncs.IsEmail("test@example.com")` |
326
+ | IsIP | IP地址 | `ValidFuncs.IsIP("192.168.1.1")` |
327
+ | IsPhoneNumber | 国际电话 | `ValidFuncs.IsPhoneNumber("+86-138-1234-5678")` |
328
+ | IsUrl | URL | `ValidFuncs.IsUrl("https://example.com")` |
329
+ | IsHash | 哈希值 | `ValidFuncs.IsHash("abc123", "md5")` |
330
+ | IsNotEmpty | 非空 | `ValidFuncs.IsNotEmpty("test")` |
331
+ | Equals | 相等 | `ValidFuncs.Equals("a", "a")` |
332
+ | NotEquals | 不相等 | `ValidFuncs.NotEquals("a", "b")` |
333
+ | Contains | 包含 | `ValidFuncs.Contains("hello", "ell")` |
334
+ | IsIn | 在数组中 | `ValidFuncs.IsIn("a", ["a", "b"])` |
335
+ | IsNotIn | 不在数组中 | `ValidFuncs.IsNotIn("c", ["a", "b"])` |
336
+ | IsDate | 日期 | `ValidFuncs.IsDate(new Date())` |
337
+ | Gt | 大于 | `ValidFuncs.Gt(10, 5)` |
338
+ | Gte | 大于等于 | `ValidFuncs.Gte(10, 10)` |
339
+ | Lt | 小于 | `ValidFuncs.Lt(5, 10)` |
340
+ | Lte | 小于等于 | `ValidFuncs.Lte(10, 10)` |
341
+
342
+ ## 📊 测试覆盖率
343
+
344
+ 当前测试覆盖率:**76%+**
345
+
346
+ - 语句覆盖率: 76.23%
347
+ - 分支覆盖率: 77.92%
348
+ - 函数覆盖率: 69.62%
349
+ - 行覆盖率: 76.14%
350
+
351
+ ## 🤝 贡献
352
+
353
+ 欢迎提交 Issue 和 Pull Request!
354
+
355
+ ## 📄 许可证
356
+
357
+ [BSD-3-Clause License](LICENSE)
358
+
359
+ ## 🔗 相关项目
360
+
361
+ - [koatty](https://github.com/koatty/koatty) - 基于 Koa2 的 Node.js 框架
362
+ - [class-validator](https://github.com/typestack/class-validator) - 基础验证库
363
+