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/package.json CHANGED
@@ -1,94 +1,91 @@
1
- {
2
- "name": "koatty_validation",
3
- "version": "1.3.6",
4
- "description": "Validation Util for Koatty and ThinkORM.",
5
- "scripts": {
6
- "build": "npm run build:js && npm run build:dts && npm run build:doc && npm run build:cp",
7
- "build:cp": "node scripts/postBuild && npx copyfiles package.json LICENSE README.md dist/",
8
- "build:js": "npx rollup --bundleConfigAsCjs -c .rollup.config.js",
9
- "build:doc": "npx api-documenter markdown --input temp --output docs/api",
10
- "build:dts": "npx tsc && npx api-extractor run --local --verbose",
11
- "eslint": "eslint --ext .ts,.js ./",
12
- "lock": "npx del-cli --force node_modules && npm i --package-lock-only && npx pnpm i",
13
- "prepublishOnly": "npm test && npm run build && git push --follow-tags origin",
14
- "prerelease": "npm run lock && npm test && npm run build",
15
- "release": "standard-version",
16
- "release:pre": "npm run release -- --prerelease",
17
- "release:major": "npm run release -- --release-as major",
18
- "release:minor": "npm run release -- --release-as minor",
19
- "test": "npm run eslint && jest --passWithNoTests",
20
- "test:cov": "jest --collectCoverage --detectOpenHandles",
21
- "version": "conventional-changelog -p angular -i CHANGELOG.md -s"
22
- },
23
- "main": "./dist/index.js",
24
- "exports": {
25
- "require": "./dist/index.js",
26
- "import": "./dist/index.mjs",
27
- "types": "./dist/index.d.ts"
28
- },
29
- "repository": {
30
- "type": "git",
31
- "url": "git+https://github.com/koatty/koatty_validation.git"
32
- },
33
- "engines": {
34
- "node": ">10.0.0"
35
- },
36
- "author": {
37
- "name": "richenlin",
38
- "email": "richenlin@gmail.com"
39
- },
40
- "license": "BSD-3-Clause",
41
- "bugs": {
42
- "url": "https://github.com/koatty/koatty_validation/issues"
43
- },
44
- "homepage": "https://github.com/koatty/koatty_validation",
45
- "maintainers": [
46
- {
47
- "name": "richenlin",
48
- "email": "richenlin@gmail.com"
49
- }
50
- ],
51
- "devDependencies": {
52
- "@commitlint/cli": "^19.x.x",
53
- "@commitlint/config-conventional": "^19.x.x",
54
- "@microsoft/api-documenter": "^7.x.x",
55
- "@microsoft/api-extractor": "^7.x.x",
56
- "@rollup/plugin-commonjs": "^28.x.x",
57
- "@rollup/plugin-json": "^6.x.x",
58
- "@rollup/plugin-node-resolve": "^15.x.x",
59
- "@types/jest": "^29.x.x",
60
- "@types/koa": "^2.x.x",
61
- "@types/lodash": "^4.x.x",
62
- "@types/node": "^22.x.x",
63
- "@types/validator": "^13.x.x",
64
- "@typescript-eslint/eslint-plugin": "^8.x.x",
65
- "@typescript-eslint/parser": "^8.x.x",
66
- "conventional-changelog-cli": "^5.x.x",
67
- "eslint": "^8.x.x",
68
- "eslint-plugin-jest": "^28.x.x",
69
- "husky": "^4.x.x",
70
- "jest": "^29.x.x",
71
- "jest-html-reporters": "^3.x.x",
72
- "libphonenumber-js": "^1.x.x",
73
- "reflect-metadata": "^0.x.x",
74
- "rollup": "^4.x.x",
75
- "rollup-plugin-delete": "^2.1.0",
76
- "rollup-plugin-typescript2": "^0.x.x",
77
- "standard-version": "^9.x.x",
78
- "ts-jest": "^29.x.x",
79
- "ts-node": "^10.x.x",
80
- "tslib": "^2.x.x",
81
- "typescript": "^5.x.x"
82
- },
83
- "dependencies": {
84
- "class-validator": "^0.14.1",
85
- "koatty_container": "^1.x.x",
86
- "koatty_lib": "^1.x.x",
87
- "koatty_logger": "^2.x.x"
88
- },
89
- "peerDependencies": {
90
- "koatty_container": "^1.x.x",
91
- "koatty_lib": "^1.x.x",
92
- "koatty_logger": "^2.x.x"
93
- }
94
- }
1
+ {
2
+ "name": "koatty_validation",
3
+ "version": "1.6.0",
4
+ "description": "Validation Util for Koatty and ThinkORM.",
5
+ "scripts": {
6
+ "build": "npm run build:js && npm run build:dts && npm run build:doc && npm run build:cp",
7
+ "build:cp": "node scripts/postBuild && copyfiles package.json LICENSE README.md dist/",
8
+ "build:js": "del-cli --force dist && npx rollup --bundleConfigAsCjs -c .rollup.config.js",
9
+ "build:doc": "del-cli --force docs/api && npx api-documenter markdown --input temp --output docs/api",
10
+ "build:dts": "del-cli --force temp && npx tsc && npx api-extractor run --local --verbose",
11
+ "eslint": "eslint --ext .ts,.js ./",
12
+ "lock": "npm i --package-lock-only",
13
+ "prepublishOnly": "npm test && npm run build && git push --follow-tags origin",
14
+ "prerelease": "npm test && npm run build",
15
+ "release": "standard-version",
16
+ "release:pre": "npm run release -- --prerelease",
17
+ "release:major": "npm run release -- --release-as major",
18
+ "release:minor": "npm run release -- --release-as minor",
19
+ "test": "npm run eslint && jest --passWithNoTests"
20
+ },
21
+ "main": "./dist/index.js",
22
+ "exports": {
23
+ "require": "./dist/index.js",
24
+ "import": "./dist/index.mjs"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/koatty/koatty_validation.git"
29
+ },
30
+ "engines": {
31
+ "node": ">10.0.0"
32
+ },
33
+ "author": {
34
+ "name": "richenlin",
35
+ "email": "richenlin@gmail.com"
36
+ },
37
+ "license": "BSD-3-Clause",
38
+ "bugs": {
39
+ "url": "https://github.com/koatty/koatty_validation/issues"
40
+ },
41
+ "homepage": "https://github.com/koatty/koatty_validation",
42
+ "maintainers": [
43
+ {
44
+ "name": "richenlin",
45
+ "email": "richenlin@gmail.com"
46
+ }
47
+ ],
48
+ "devDependencies": {
49
+ "@commitlint/cli": "^19.x.x",
50
+ "@commitlint/config-conventional": "^19.x.x",
51
+ "@microsoft/api-documenter": "^7.x.x",
52
+ "@microsoft/api-extractor": "^7.x.x",
53
+ "@rollup/plugin-json": "^6.x.x",
54
+ "@types/jest": "^29.x.x",
55
+ "@types/koa": "^2.x.x",
56
+ "@types/lodash": "^4.17.17",
57
+ "@types/node": "^24.x.x",
58
+ "@types/validator": "^13.x.x",
59
+ "@typescript-eslint/eslint-plugin": "^8.x.x",
60
+ "@typescript-eslint/parser": "^8.x.x",
61
+ "conventional-changelog-cli": "^5.x.x",
62
+ "copyfiles": "^2.x.x",
63
+ "del-cli": "^6.x.x",
64
+ "eslint": "^8.x.x",
65
+ "eslint-plugin-jest": "^28.x.x",
66
+ "husky": "^4.x.x",
67
+ "jest": "^29.x.x",
68
+ "jest-html-reporters": "^3.x.x",
69
+ "libphonenumber-js": "^1.x.x",
70
+ "reflect-metadata": "^0.x.x",
71
+ "rollup": "^4.x.x",
72
+ "rollup-plugin-typescript2": "^0.x.x",
73
+ "standard-version": "^9.x.x",
74
+ "ts-jest": "^29.x.x",
75
+ "ts-node": "^10.x.x",
76
+ "tslib": "^2.x.x",
77
+ "typescript": "^5.x.x"
78
+ },
79
+ "dependencies": {
80
+ "class-validator": "^0.14.2",
81
+ "koatty_container": "^1.x.x",
82
+ "koatty_lib": "^1.x.x",
83
+ "koatty_logger": "^2.x.x",
84
+ "lru-cache": "^11.2.2"
85
+ },
86
+ "peerDependencies": {
87
+ "koatty_container": "^1.x.x",
88
+ "koatty_lib": "^1.x.x",
89
+ "koatty_logger": "^2.x.x"
90
+ }
91
+ }
@@ -0,0 +1,90 @@
1
+ # koatty_validation 使用示例
2
+
3
+ 本目录包含了 koatty_validation 的各种使用示例,帮助您快速上手。
4
+
5
+ ## 📁 文件结构
6
+
7
+ - `basic-usage.ts` - 基础使用示例
8
+ - `custom-decorators.ts` - 自定义装饰器使用示例
9
+ - `advanced-validation.ts` - 高级验证场景示例
10
+ - `error-handling.ts` - 错误处理示例
11
+
12
+ ## 🚀 快速开始
13
+
14
+ ### 1. 基础验证
15
+
16
+ ```typescript
17
+ import { IsNotEmpty, IsEmail, IsInt } from 'koatty_validation';
18
+
19
+ class UserDto {
20
+ @IsNotEmpty()
21
+ name: string;
22
+
23
+ @IsEmail()
24
+ email: string;
25
+
26
+ @IsInt({ min: 18, max: 100 })
27
+ age: number;
28
+ }
29
+ ```
30
+
31
+ ### 2. 自定义装饰器
32
+
33
+ ```typescript
34
+ import { createSimpleDecorator } from 'koatty_validation';
35
+
36
+ const IsStrongPassword = createSimpleDecorator(
37
+ 'IsStrongPassword',
38
+ (value: string) => {
39
+ return /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/.test(value);
40
+ },
41
+ 'Password must be at least 8 characters with uppercase, lowercase, number and special character'
42
+ );
43
+
44
+ class RegisterDto {
45
+ @IsStrongPassword()
46
+ password: string;
47
+ }
48
+ ```
49
+
50
+ ### 3. 中文本土化验证
51
+
52
+ ```typescript
53
+ import { IsCnName, IsIdNumber, IsMobile } from 'koatty_validation';
54
+
55
+ class ChineseUserDto {
56
+ @IsCnName()
57
+ name: string;
58
+
59
+ @IsIdNumber()
60
+ idCard: string;
61
+
62
+ @IsMobile()
63
+ phone: string;
64
+ }
65
+ ```
66
+
67
+ ## 📖 详细示例
68
+
69
+ 查看各个示例文件了解更多用法:
70
+
71
+ - **基础使用**: 查看 `basic-usage.ts`
72
+ - **自定义装饰器**: 查看 `custom-decorators.ts`
73
+ - **高级验证**: 查看 `advanced-validation.ts`
74
+ - **错误处理**: 查看 `error-handling.ts`
75
+
76
+ ## 🔧 运行示例
77
+
78
+ ```bash
79
+ # 编译TypeScript
80
+ npm run build
81
+
82
+ # 运行示例
83
+ node dist/examples/basic-usage.js
84
+ ```
85
+
86
+ ## 📚 更多文档
87
+
88
+ - [自定义装饰器指南](../CUSTOM_DECORATORS_GUIDE.md)
89
+ - [API文档](../README.md)
90
+ - [测试用例](../test/)
@@ -0,0 +1,239 @@
1
+ /**
2
+ * koatty_validation 基础使用示例
3
+ * @author richen
4
+ */
5
+
6
+ import { validate } from 'class-validator';
7
+ import {
8
+ IsNotEmpty,
9
+ IsEmail,
10
+ IsCnName,
11
+ IsIdNumber,
12
+ IsMobile,
13
+ Expose
14
+ } from '../src/index';
15
+ import {
16
+ IsStrongPassword,
17
+ IsHexColor,
18
+ IsPositiveInteger,
19
+ IsFileExtension,
20
+ MatchesPattern,
21
+ ArrayLength,
22
+ InRange
23
+ } from '../examples/custom-decorators-example';
24
+
25
+ // =============== 用户注册示例 ===============
26
+
27
+ class UserRegistrationDto {
28
+ @IsNotEmpty()
29
+ @IsCnName()
30
+ name: string;
31
+
32
+ @IsEmail()
33
+ email: string;
34
+
35
+ @IsStrongPassword()
36
+ password: string;
37
+
38
+ @IsPositiveInteger()
39
+ age: number;
40
+
41
+ @IsIdNumber()
42
+ idCard: string;
43
+
44
+ @IsMobile()
45
+ phone: string;
46
+
47
+ @IsHexColor()
48
+ favoriteColor: string;
49
+
50
+ @IsFileExtension(['jpg', 'png', 'gif'])
51
+ avatar: string;
52
+
53
+ @MatchesPattern(/^[A-Z]{2,3}$/)
54
+ countryCode: string;
55
+
56
+ @ArrayLength(1, 5)
57
+ hobbies: string[];
58
+
59
+ @InRange(0, 100)
60
+ completionRate: number;
61
+
62
+ @Expose()
63
+ createdAt: Date = new Date();
64
+ }
65
+
66
+ // =============== 产品信息示例 ===============
67
+
68
+ class ProductDto {
69
+ @IsNotEmpty()
70
+ @MatchesPattern(/^[A-Z0-9-]+$/)
71
+ sku: string;
72
+
73
+ @IsNotEmpty()
74
+ title: string;
75
+
76
+ @InRange(0.01, 9999999.99)
77
+ price: number;
78
+
79
+ @InRange(0, 10000)
80
+ stock: number;
81
+
82
+ @ArrayLength(1, 10)
83
+ tags: string[];
84
+
85
+ @IsHexColor()
86
+ primaryColor: string;
87
+
88
+ @IsFileExtension(['jpg', 'png', 'webp'])
89
+ mainImage: string;
90
+
91
+ @Expose()
92
+ isActive: boolean = true;
93
+ }
94
+
95
+ // =============== 验证演示函数 ===============
96
+
97
+ async function demonstrateValidation() {
98
+ console.log('🚀 koatty_validation 基础使用示例\n');
99
+
100
+ // ========== 成功验证示例 ==========
101
+ console.log('✅ 成功验证示例:');
102
+
103
+ const validUser = new UserRegistrationDto();
104
+ validUser.name = '张三';
105
+ validUser.email = 'zhangsan@example.com';
106
+ validUser.password = 'MySecure123!';
107
+ validUser.age = 25;
108
+ validUser.idCard = '110101199001011234';
109
+ validUser.phone = '13812345678';
110
+ validUser.favoriteColor = '#FF5733';
111
+ validUser.avatar = 'profile.jpg';
112
+ validUser.countryCode = 'CN';
113
+ validUser.hobbies = ['reading', 'coding'];
114
+ validUser.completionRate = 85;
115
+
116
+ const validErrors = await validate(validUser);
117
+ if (validErrors.length === 0) {
118
+ console.log('用户注册数据验证通过 ✓');
119
+ } else {
120
+ console.log('用户注册数据验证失败:', validErrors.map(e => e.constraints));
121
+ }
122
+
123
+ // ========== 失败验证示例 ==========
124
+ console.log('\n❌ 失败验证示例:');
125
+
126
+ const invalidUser = new UserRegistrationDto();
127
+ invalidUser.name = 'John123'; // 不是中文名
128
+ invalidUser.email = 'invalid-email'; // 无效邮箱
129
+ invalidUser.password = 'weak'; // 弱密码
130
+ invalidUser.age = -5; // 负数年龄
131
+ invalidUser.idCard = '123'; // 无效身份证
132
+ invalidUser.phone = '123'; // 无效手机号
133
+ invalidUser.favoriteColor = 'red'; // 不是十六进制颜色
134
+ invalidUser.avatar = 'profile.pdf'; // 不允许的文件类型
135
+ invalidUser.countryCode = 'china'; // 不符合模式
136
+ invalidUser.hobbies = []; // 数组为空
137
+ invalidUser.completionRate = 150; // 超出范围
138
+
139
+ const invalidErrors = await validate(invalidUser);
140
+ console.log(`发现 ${invalidErrors.length} 个验证错误:`);
141
+
142
+ invalidErrors.forEach((error, index) => {
143
+ console.log(`${index + 1}. ${error.property}:`);
144
+ Object.values(error.constraints || {}).forEach(message => {
145
+ console.log(` - ${message}`);
146
+ });
147
+ });
148
+
149
+ // ========== 产品验证示例 ==========
150
+ console.log('\n📦 产品信息验证示例:');
151
+
152
+ const product = new ProductDto();
153
+ product.sku = 'PROD-2024-001';
154
+ product.title = 'Gaming Laptop';
155
+ product.price = 1299.99;
156
+ product.stock = 50;
157
+ product.tags = ['gaming', 'laptop', 'electronics'];
158
+ product.primaryColor = '#1E1E1E';
159
+ product.mainImage = 'laptop.jpg';
160
+
161
+ const productErrors = await validate(product);
162
+ if (productErrors.length === 0) {
163
+ console.log('产品信息验证通过 ✓');
164
+ console.log('产品详情:', {
165
+ sku: product.sku,
166
+ title: product.title,
167
+ price: `$${product.price}`,
168
+ stock: product.stock,
169
+ tags: product.tags.join(', '),
170
+ primaryColor: product.primaryColor,
171
+ isActive: product.isActive
172
+ });
173
+ } else {
174
+ console.log('产品信息验证失败:', productErrors.map(e => e.constraints));
175
+ }
176
+ }
177
+
178
+ // =============== 性能测试示例 ===============
179
+
180
+ async function performanceDemo() {
181
+ console.log('\n⚡ 性能测试示例:');
182
+
183
+ const testCount = 1000;
184
+ const startTime = Date.now();
185
+
186
+ for (let i = 0; i < testCount; i++) {
187
+ const user = new UserRegistrationDto();
188
+ user.name = '测试用户';
189
+ user.email = `user${i}@example.com`;
190
+ user.password = 'Test123!';
191
+ user.age = 25;
192
+ user.idCard = '110101199001011234';
193
+ user.phone = '13812345678';
194
+ user.favoriteColor = '#FF5733';
195
+ user.avatar = 'avatar.jpg';
196
+ user.countryCode = 'CN';
197
+ user.hobbies = ['test'];
198
+ user.completionRate = 50;
199
+
200
+ await validate(user);
201
+ }
202
+
203
+ const endTime = Date.now();
204
+ const duration = endTime - startTime;
205
+
206
+ console.log(`验证 ${testCount} 个对象耗时: ${duration}ms`);
207
+ console.log(`平均每个对象: ${(duration / testCount).toFixed(2)}ms`);
208
+ }
209
+
210
+ // =============== 主函数 ===============
211
+
212
+ async function main() {
213
+ try {
214
+ await demonstrateValidation();
215
+ await performanceDemo();
216
+
217
+ console.log('\n🎉 所有示例运行完成!');
218
+ console.log('\n📚 更多示例请查看:');
219
+ console.log(' - custom-decorators.ts - 自定义装饰器示例');
220
+ console.log(' - advanced-validation.ts - 高级验证示例');
221
+ console.log(' - error-handling.ts - 错误处理示例');
222
+
223
+ } catch (error) {
224
+ console.error('示例运行失败:', error);
225
+ process.exit(1);
226
+ }
227
+ }
228
+
229
+ // 如果直接运行此文件
230
+ if (require.main === module) {
231
+ main();
232
+ }
233
+
234
+ export {
235
+ UserRegistrationDto,
236
+ ProductDto,
237
+ demonstrateValidation,
238
+ performanceDemo
239
+ };