rxtutils 1.1.2-beta.3 → 1.1.2-beta.5
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 +144 -1
- package/dist/cjs/request/index.cjs +91 -70
- package/dist/cjs/validator/decorators.cjs +143 -1
- package/dist/cjs/validator/validator.cjs +55 -0
- package/dist/es/request/index.mjs +92 -71
- package/dist/es/validator/decorators.mjs +143 -1
- package/dist/es/validator/validator.mjs +55 -0
- package/dist/types/request/index.d.ts +7 -20
- package/dist/types/validator/decorators.d.ts +144 -0
- package/dist/types/validator/validator.d.ts +65 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ pnpm add rxtutils
|
|
|
17
17
|
- **缓存管理** - 支持内存、localStorage、sessionStorage 和 IndexedDB 多种存储方式
|
|
18
18
|
- **HTTP 请求** - 基于 axios 的请求封装,支持错误处理和缓存
|
|
19
19
|
- **状态管理** - 轻量级的状态管理解决方案,支持 React Hook
|
|
20
|
+
- **数据验证** - 基于装饰器的数据验证系统,支持多种验证规则
|
|
20
21
|
- **TypeScript** - 完整的 TypeScript 类型支持
|
|
21
22
|
|
|
22
23
|
## 📚 模块介绍
|
|
@@ -198,7 +199,149 @@ const currentUser = userStore.get();
|
|
|
198
199
|
userStore.set({ name: 'Jane Doe', email: 'jane@example.com', isLoggedIn: true });
|
|
199
200
|
```
|
|
200
201
|
|
|
201
|
-
### 4.
|
|
202
|
+
### 4. 数据验证 (Validator)
|
|
203
|
+
|
|
204
|
+
基于装饰器的数据验证系统,提供多种验证规则和自定义验证能力。
|
|
205
|
+
|
|
206
|
+
#### 基本用法
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { BaseValidator, VString, VNumber, VRequired, VEmail, VMinLength } from 'rxtutils';
|
|
210
|
+
|
|
211
|
+
// 创建验证模型
|
|
212
|
+
class User extends BaseValidator {
|
|
213
|
+
@VString('用户名必须为字符串')
|
|
214
|
+
@(VRequired()('用户名不能为空'))
|
|
215
|
+
name?: string;
|
|
216
|
+
|
|
217
|
+
@VNumber('年龄必须为数字')
|
|
218
|
+
@(VRequired()('年龄不能为空'))
|
|
219
|
+
age?: number;
|
|
220
|
+
|
|
221
|
+
@VEmail('邮箱格式不正确')
|
|
222
|
+
@(VRequired()('邮箱不能为空'))
|
|
223
|
+
email?: string;
|
|
224
|
+
|
|
225
|
+
@(VMinLength(6)('密码长度不能少于6位'))
|
|
226
|
+
@(VRequired()('密码不能为空'))
|
|
227
|
+
password?: string;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// 使用验证
|
|
231
|
+
const user = new User();
|
|
232
|
+
user.name = '张三';
|
|
233
|
+
user.age = 25;
|
|
234
|
+
user.email = 'invalid-email'; // 无效的邮箱格式
|
|
235
|
+
user.password = '123'; // 密码长度不足
|
|
236
|
+
|
|
237
|
+
// 验证单个字段
|
|
238
|
+
const emailErrors = user.validate('email');
|
|
239
|
+
console.log(emailErrors); // [{ status: false, message: '邮箱格式不正确' }]
|
|
240
|
+
|
|
241
|
+
// 验证所有字段
|
|
242
|
+
const allErrors = user.validateAll();
|
|
243
|
+
console.log(allErrors); // 返回所有验证错误
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
#### 内置验证装饰器
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
// 基本类型验证
|
|
250
|
+
@VString('必须为字符串')
|
|
251
|
+
@VNumber('必须为数字')
|
|
252
|
+
@VBoolean('必须为布尔值')
|
|
253
|
+
@VArray('必须为数组')
|
|
254
|
+
|
|
255
|
+
// 必填验证
|
|
256
|
+
@(VRequired()('不能为空'))
|
|
257
|
+
|
|
258
|
+
// 范围验证
|
|
259
|
+
@(VMin(18)('必须大于等于18'))
|
|
260
|
+
@(VMax(100)('必须小于等于100'))
|
|
261
|
+
|
|
262
|
+
// 长度验证
|
|
263
|
+
@(VMinLength(6)('长度不能少于6位'))
|
|
264
|
+
@(VMaxLength(20)('长度不能超过20位'))
|
|
265
|
+
|
|
266
|
+
// 格式验证
|
|
267
|
+
@VEmail('邮箱格式不正确')
|
|
268
|
+
@(VPattern(/^1[3-9]\d{9}$/)('手机号格式不正确'))
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### 自定义验证装饰器
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
import { BaseValidator } from 'rxtutils';
|
|
275
|
+
|
|
276
|
+
// 创建自定义验证装饰器
|
|
277
|
+
const VCustom = BaseValidator.decoratorCreator(
|
|
278
|
+
(val) => {
|
|
279
|
+
// 自定义验证逻辑
|
|
280
|
+
return typeof val === 'string' && val.startsWith('custom-');
|
|
281
|
+
}
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
// 使用自定义验证装饰器
|
|
285
|
+
class Product extends BaseValidator {
|
|
286
|
+
@VCustom('产品编码必须以 custom- 开头')
|
|
287
|
+
code?: string;
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
#### 验证方法
|
|
292
|
+
|
|
293
|
+
BaseValidator 类提供了两个主要的验证方法:
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
// 验证单个字段
|
|
297
|
+
validate(itemKey: string, itemAll: boolean = false): { status: boolean; message?: string }[] | null;
|
|
298
|
+
|
|
299
|
+
// 验证多个或所有字段
|
|
300
|
+
validateAll(itemAll: boolean = false, everyItem: boolean = false, order?: string[]): { status: boolean; message?: string }[] | null;
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
参数说明:
|
|
304
|
+
|
|
305
|
+
- `itemKey`: 要验证的字段名
|
|
306
|
+
- `itemAll`: 是否验证该字段的所有规则,为 true 时会验证所有规则,为 false 时遇到第一个失败的规则就停止
|
|
307
|
+
- `everyItem`: 是否验证所有字段,为 true 时会验证所有字段,为 false 时遇到第一个失败的字段就停止
|
|
308
|
+
- `order`: 验证字段的顺序,可以指定验证的字段名数组及其顺序
|
|
309
|
+
|
|
310
|
+
使用示例:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
// 创建验证模型
|
|
314
|
+
class LoginForm extends BaseValidator {
|
|
315
|
+
@VString('用户名必须为字符串')
|
|
316
|
+
@(VRequired()('用户名不能为空'))
|
|
317
|
+
@(VMinLength(3)('用户名长度不能少于3位'))
|
|
318
|
+
@(VMaxLength(20)('用户名长度不能超过20位'))
|
|
319
|
+
username?: string;
|
|
320
|
+
|
|
321
|
+
@(VRequired()('密码不能为空'))
|
|
322
|
+
@(VMinLength(6)('密码长度不能少于6位'))
|
|
323
|
+
password?: string;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const form = new LoginForm();
|
|
327
|
+
form.username = 'ab'; // 长度不足
|
|
328
|
+
form.password = '123456';
|
|
329
|
+
|
|
330
|
+
// 验证单个字段的所有规则
|
|
331
|
+
const usernameErrors = form.validate('username', true);
|
|
332
|
+
console.log(usernameErrors);
|
|
333
|
+
// [{ status: false, message: '用户名长度不能少于3位' }]
|
|
334
|
+
|
|
335
|
+
// 验证所有字段,每个字段遇到第一个错误就停止
|
|
336
|
+
const allErrors = form.validateAll(false, true);
|
|
337
|
+
console.log(allErrors);
|
|
338
|
+
|
|
339
|
+
// 按指定顺序验证字段,并验证每个字段的所有规则
|
|
340
|
+
const orderedErrors = form.validateAll(true, true, ['password', 'username']);
|
|
341
|
+
console.log(orderedErrors);
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### 5. 状态计算器 (createStoreGetter)
|
|
202
345
|
|
|
203
346
|
为状态存储提供计算属性和派生状态。
|
|
204
347
|
|
|
@@ -30,16 +30,17 @@ function createBaseRequest(baseOptions) {
|
|
|
30
30
|
*/
|
|
31
31
|
return function createRequest(requestOptions, createOptions) {
|
|
32
32
|
var _a = tslib.__assign({}, requestOptions), method = _a.method, url = _a.url;
|
|
33
|
-
var _b = tslib.__assign(tslib.__assign({}, baseOptions), createOptions), baseURL = _b.baseURL, _c = _b.cacheDataKey, cacheDataKey = _c === void 0 ? "".concat(method, ":").concat(baseURL).concat(url) : _c, cacheDataInStorage = _b.cacheDataInStorage, _d = _b.cacheKeyEquals, cacheKeyEquals = _d === void 0 ? defaultEquals : _d, cacheTime = _b.cacheTime, _e = _b.indexDBName, indexDBName = _e === void 0 ?
|
|
33
|
+
var _b = tslib.__assign(tslib.__assign({}, baseOptions), createOptions), baseURL = _b.baseURL, _c = _b.cacheDataKey, cacheDataKey = _c === void 0 ? "".concat(method, ":").concat(baseURL).concat(url) : _c, cacheDataInStorage = _b.cacheDataInStorage, _d = _b.cacheKeyEquals, cacheKeyEquals = _d === void 0 ? defaultEquals : _d, cacheTime = _b.cacheTime, _e = _b.indexDBName, indexDBName = _e === void 0 ? "__apiCacheDatabase__" : _e;
|
|
34
34
|
var cache = new index.default(cacheDataInStorage, cacheDataKey, cacheTime, indexDBName, cacheKeyEquals);
|
|
35
35
|
function request(requestParam, options) {
|
|
36
|
+
var _this = this;
|
|
36
37
|
var _a = tslib.__assign(tslib.__assign({}, requestOptions), requestParam), method = _a.method, url = _a.url, _b = _a.data, data = _b === void 0 ? {} : _b, _c = _a.params, params = _c === void 0 ? {} : _c;
|
|
37
38
|
var requestDataOrParams = params;
|
|
38
|
-
if (method.toLowerCase() ===
|
|
39
|
+
if (method.toLowerCase() === "post") {
|
|
39
40
|
requestDataOrParams = data;
|
|
40
41
|
}
|
|
41
42
|
var _d = tslib.__assign(tslib.__assign(tslib.__assign({}, baseOptions), createOptions), options).defaultMessageShower, defaultMessageShower = _d === void 0 ? console.error : _d;
|
|
42
|
-
var _e = tslib.__assign(tslib.__assign(tslib.__assign({}, baseOptions), createOptions), options), _f = _e.enableCache, enableCache = _f === void 0 ? false : _f, _g = _e.cacheData, cacheData = _g === void 0 ? false : _g, _h = _e.defaultErrorCodeHandler, defaultErrorCodeHandler = _h === void 0 ? defaultHandlers._defaultErrorCodeHandler.bind(null, defaultMessageShower) : _h, _j = _e.defaultHttpErrorCodeHandler, defaultHttpErrorCodeHandler = _j === void 0 ? defaultHandlers._defaultHttpErrorCodeHandler.bind(null, defaultMessageShower) : _j, _k = _e.otherErrorHandler, otherErrorHandler = _k === void 0 ? defaultHandlers._defaultOtherErrorCodeHandler.bind(null, defaultMessageShower) : _k, _l = _e.errorCodePath, errorCodePath = _l === void 0 ?
|
|
43
|
+
var _e = tslib.__assign(tslib.__assign(tslib.__assign({}, baseOptions), createOptions), options), _f = _e.enableCache, enableCache = _f === void 0 ? false : _f, _g = _e.cacheData, cacheData = _g === void 0 ? false : _g, _h = _e.defaultErrorCodeHandler, defaultErrorCodeHandler = _h === void 0 ? defaultHandlers._defaultErrorCodeHandler.bind(null, defaultMessageShower) : _h, _j = _e.defaultHttpErrorCodeHandler, defaultHttpErrorCodeHandler = _j === void 0 ? defaultHandlers._defaultHttpErrorCodeHandler.bind(null, defaultMessageShower) : _j, _k = _e.otherErrorHandler, otherErrorHandler = _k === void 0 ? defaultHandlers._defaultOtherErrorCodeHandler.bind(null, defaultMessageShower) : _k, _l = _e.errorCodePath, errorCodePath = _l === void 0 ? "code" : _l, _m = _e.cacheTime, cacheTime = _m === void 0 ? 60 : _m, _o = _e.errorCodeMap, errorCodeMap = _o === void 0 ? {} : _o, _p = _e.successCodes, successCodes = _p === void 0 ? ["0", "200"] : _p, _q = _e.httpErrorCodeMap, httpErrorCodeMap = _q === void 0 ? {} : _q, _r = _e.axiosOptions, axiosOptions = _r === void 0 ? {} : _r, _s = _e.throwError, throwError = _s === void 0 ? true : _s;
|
|
43
44
|
if (enableCache) {
|
|
44
45
|
var cacheItem = cache.getCache(requestDataOrParams);
|
|
45
46
|
if (cacheItem) {
|
|
@@ -48,76 +49,96 @@ function createBaseRequest(baseOptions) {
|
|
|
48
49
|
}
|
|
49
50
|
return instance
|
|
50
51
|
.request(tslib.__assign({ method: method, url: url, data: data, params: params }, axiosOptions))
|
|
51
|
-
.then(function (res) {
|
|
52
|
-
var errorCode
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
case
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
var err = new error('服务端错误', 'http', error$1);
|
|
84
|
-
if (typeof customHandler === 'string') {
|
|
85
|
-
defaultMessageShower(customHandler);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
var _d = (Object(customHandler(error$1.response.status, error$1, tslib.__assign(tslib.__assign({}, requestOptions), requestParam)))), _e = _d.replaceResData, replaceResData = _e === void 0 ? error$1 : _e, _f = _d.throwError, handlerThrowError = _f === void 0 ? 'default' : _f;
|
|
89
|
-
resData = replaceResData;
|
|
90
|
-
switch (handlerThrowError) {
|
|
91
|
-
case true:
|
|
52
|
+
.then(function (res) { return tslib.__awaiter(_this, void 0, void 0, function () {
|
|
53
|
+
var errorCode, _a, _b, _c, customHandler, err, _d, _e, replaceResData, _f, handlerThrowError, _g;
|
|
54
|
+
return tslib.__generator(this, function (_h) {
|
|
55
|
+
switch (_h.label) {
|
|
56
|
+
case 0:
|
|
57
|
+
errorCode = String(lodash.at(res.data, errorCodePath));
|
|
58
|
+
if (successCodes.includes(errorCode)) {
|
|
59
|
+
if (cacheData) {
|
|
60
|
+
cache.setCache(requestDataOrParams, res.data, { cacheTime: cacheTime });
|
|
61
|
+
}
|
|
62
|
+
return [2 /*return*/, res.data];
|
|
63
|
+
}
|
|
64
|
+
_a = errorCodeMap, _b = errorCode, _c = _a[_b], customHandler = _c === void 0 ? defaultErrorCodeHandler : _c;
|
|
65
|
+
err = new error("服务端错误", "server", res);
|
|
66
|
+
if (!(typeof customHandler === "string")) return [3 /*break*/, 1];
|
|
67
|
+
defaultMessageShower(customHandler);
|
|
68
|
+
return [3 /*break*/, 3];
|
|
69
|
+
case 1:
|
|
70
|
+
_g = Object;
|
|
71
|
+
return [4 /*yield*/, customHandler(errorCode, res.data, res, tslib.__assign(tslib.__assign({}, requestOptions), requestParam))];
|
|
72
|
+
case 2:
|
|
73
|
+
_d = (_g.apply(void 0, [(_h.sent())])), _e = _d.replaceResData, replaceResData = _e === void 0 ? res.data : _e, _f = _d.throwError, handlerThrowError = _f === void 0 ? "default" : _f;
|
|
74
|
+
res.data = replaceResData;
|
|
75
|
+
switch (handlerThrowError) {
|
|
76
|
+
case true:
|
|
77
|
+
throw err;
|
|
78
|
+
case false:
|
|
79
|
+
return [2 /*return*/, res.data];
|
|
80
|
+
}
|
|
81
|
+
_h.label = 3;
|
|
82
|
+
case 3:
|
|
83
|
+
if (throwError) {
|
|
92
84
|
throw err;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
85
|
+
}
|
|
86
|
+
return [2 /*return*/, res.data];
|
|
96
87
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
case
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
88
|
+
});
|
|
89
|
+
}); }, function (error$1) { return tslib.__awaiter(_this, void 0, void 0, function () {
|
|
90
|
+
var resData, _a, _b, _c, customHandler, err, _d, _e, replaceResData, _f, handlerThrowError, _g, resData, err, _h, _j, replaceResData, _k, handlerThrowError, _l;
|
|
91
|
+
return tslib.__generator(this, function (_m) {
|
|
92
|
+
switch (_m.label) {
|
|
93
|
+
case 0:
|
|
94
|
+
if (!error$1.response) return [3 /*break*/, 4];
|
|
95
|
+
resData = error$1;
|
|
96
|
+
_a = httpErrorCodeMap, _b = error$1.response.status, _c = _a[_b], customHandler = _c === void 0 ? defaultHttpErrorCodeHandler : _c;
|
|
97
|
+
err = new error("服务端错误", "http", error$1);
|
|
98
|
+
if (!(typeof customHandler === "string")) return [3 /*break*/, 1];
|
|
99
|
+
defaultMessageShower(customHandler);
|
|
100
|
+
return [3 /*break*/, 3];
|
|
101
|
+
case 1:
|
|
102
|
+
_g = Object;
|
|
103
|
+
return [4 /*yield*/, customHandler(error$1.response.status, error$1, tslib.__assign(tslib.__assign({}, requestOptions), requestParam))];
|
|
104
|
+
case 2:
|
|
105
|
+
_d = (_g.apply(void 0, [(_m.sent())])), _e = _d.replaceResData, replaceResData = _e === void 0 ? error$1 : _e, _f = _d.throwError, handlerThrowError = _f === void 0 ? "default" : _f;
|
|
106
|
+
resData = replaceResData;
|
|
107
|
+
switch (handlerThrowError) {
|
|
108
|
+
case true:
|
|
109
|
+
throw err;
|
|
110
|
+
case false:
|
|
111
|
+
return [2 /*return*/, resData];
|
|
112
|
+
}
|
|
113
|
+
_m.label = 3;
|
|
114
|
+
case 3:
|
|
115
|
+
if (throwError) {
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
return [2 /*return*/, resData];
|
|
119
|
+
case 4:
|
|
120
|
+
resData = error$1;
|
|
121
|
+
err = new error("服务端错误", "http", error$1);
|
|
122
|
+
err.type = "http";
|
|
123
|
+
err.data = error$1;
|
|
124
|
+
_l = Object;
|
|
125
|
+
return [4 /*yield*/, otherErrorHandler(error$1)];
|
|
126
|
+
case 5:
|
|
127
|
+
_h = (_l.apply(void 0, [(_m.sent())])), _j = _h.replaceResData, replaceResData = _j === void 0 ? error$1 : _j, _k = _h.throwError, handlerThrowError = _k === void 0 ? "default" : _k;
|
|
128
|
+
resData = replaceResData;
|
|
129
|
+
switch (handlerThrowError) {
|
|
130
|
+
case true:
|
|
131
|
+
throw err;
|
|
132
|
+
case false:
|
|
133
|
+
return [2 /*return*/, resData];
|
|
134
|
+
}
|
|
135
|
+
if (throwError) {
|
|
136
|
+
throw err;
|
|
137
|
+
}
|
|
138
|
+
return [2 /*return*/, resData];
|
|
117
139
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
});
|
|
140
|
+
});
|
|
141
|
+
}); });
|
|
121
142
|
}
|
|
122
143
|
request.clearCache = function () {
|
|
123
144
|
cache.clear();
|
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
var validator = require('./validator.cjs');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* 验证器装饰器模块
|
|
7
|
+
* 提供一系列用于数据验证的装饰器,可用于类属性的验证规则定义
|
|
8
|
+
* 这些装饰器基于 BaseValidator 的 decoratorCreator 方法创建
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* 必填项验证装饰器
|
|
12
|
+
* 验证值是否存在且不在指定的无效值列表中
|
|
13
|
+
*
|
|
14
|
+
* @param noneVals 被视为无效的值数组,默认为 [undefined]
|
|
15
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* class User extends BaseValidator {
|
|
19
|
+
* @(VRequired()('用户名不能为空'))
|
|
20
|
+
* username?: string;
|
|
21
|
+
* }
|
|
22
|
+
*/
|
|
5
23
|
function VRequired(noneVals) {
|
|
6
24
|
if (noneVals === void 0) { noneVals = [undefined]; }
|
|
7
25
|
return validator.BaseValidator.decoratorCreator(function (val) {
|
|
@@ -11,31 +29,91 @@ function VRequired(noneVals) {
|
|
|
11
29
|
return true;
|
|
12
30
|
});
|
|
13
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* 字符串类型验证装饰器
|
|
34
|
+
* 验证值是否为字符串类型
|
|
35
|
+
*
|
|
36
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* class User extends BaseValidator {
|
|
40
|
+
* @VString('用户名必须为字符串')
|
|
41
|
+
* username?: string;
|
|
42
|
+
* }
|
|
43
|
+
*/
|
|
14
44
|
var VString = validator.BaseValidator.decoratorCreator(function (val) {
|
|
15
45
|
if (typeof val !== 'string') {
|
|
16
46
|
return false;
|
|
17
47
|
}
|
|
18
48
|
return true;
|
|
19
49
|
});
|
|
50
|
+
/**
|
|
51
|
+
* 数字类型验证装饰器
|
|
52
|
+
* 验证值是否为数字类型
|
|
53
|
+
*
|
|
54
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* class User extends BaseValidator {
|
|
58
|
+
* @VNumber('年龄必须为数字')
|
|
59
|
+
* age?: number;
|
|
60
|
+
* }
|
|
61
|
+
*/
|
|
20
62
|
var VNumber = validator.BaseValidator.decoratorCreator(function (val) {
|
|
21
63
|
if (typeof val !== 'number') {
|
|
22
64
|
return false;
|
|
23
65
|
}
|
|
24
66
|
return true;
|
|
25
67
|
});
|
|
68
|
+
/**
|
|
69
|
+
* 数组类型验证装饰器
|
|
70
|
+
* 验证值是否为数组类型
|
|
71
|
+
*
|
|
72
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* class User extends BaseValidator {
|
|
76
|
+
* @VArray('标签必须为数组')
|
|
77
|
+
* tags?: string[];
|
|
78
|
+
* }
|
|
79
|
+
*/
|
|
26
80
|
var VArray = validator.BaseValidator.decoratorCreator(function (val) {
|
|
27
81
|
if (!Array.isArray(val)) {
|
|
28
82
|
return false;
|
|
29
83
|
}
|
|
30
84
|
return true;
|
|
31
85
|
});
|
|
32
|
-
|
|
86
|
+
/**
|
|
87
|
+
* 布尔类型验证装饰器
|
|
88
|
+
* 验证值是否为布尔类型
|
|
89
|
+
*
|
|
90
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* class User extends BaseValidator {
|
|
94
|
+
* @VBoolean('状态必须为布尔值')
|
|
95
|
+
* active?: boolean;
|
|
96
|
+
* }
|
|
97
|
+
*/
|
|
33
98
|
var VBoolean = validator.BaseValidator.decoratorCreator(function (val) {
|
|
34
99
|
if (typeof val !== 'boolean') {
|
|
35
100
|
return false;
|
|
36
101
|
}
|
|
37
102
|
return true;
|
|
38
103
|
});
|
|
104
|
+
/**
|
|
105
|
+
* 最小值验证装饰器
|
|
106
|
+
* 验证数字是否大于或等于指定的最小值
|
|
107
|
+
*
|
|
108
|
+
* @param min 最小值
|
|
109
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* class User extends BaseValidator {
|
|
113
|
+
* @(VMin(18)('年龄必须大于或等于18岁'))
|
|
114
|
+
* age?: number;
|
|
115
|
+
* }
|
|
116
|
+
*/
|
|
39
117
|
var VMin = function (min) {
|
|
40
118
|
return validator.BaseValidator.decoratorCreator(function (val) {
|
|
41
119
|
if (typeof val !== 'number' || val < min) {
|
|
@@ -44,6 +122,19 @@ var VMin = function (min) {
|
|
|
44
122
|
return true;
|
|
45
123
|
});
|
|
46
124
|
};
|
|
125
|
+
/**
|
|
126
|
+
* 最大值验证装饰器
|
|
127
|
+
* 验证数字是否小于或等于指定的最大值
|
|
128
|
+
*
|
|
129
|
+
* @param max 最大值
|
|
130
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* class User extends BaseValidator {
|
|
134
|
+
* @(VMax(120)('年龄必须小于或等于120岁'))
|
|
135
|
+
* age?: number;
|
|
136
|
+
* }
|
|
137
|
+
*/
|
|
47
138
|
var VMax = function (max) {
|
|
48
139
|
return validator.BaseValidator.decoratorCreator(function (val) {
|
|
49
140
|
if (typeof val !== 'number' || val > max) {
|
|
@@ -52,6 +143,19 @@ var VMax = function (max) {
|
|
|
52
143
|
return true;
|
|
53
144
|
});
|
|
54
145
|
};
|
|
146
|
+
/**
|
|
147
|
+
* 最小长度验证装饰器
|
|
148
|
+
* 验证字符串或数组的长度是否大于或等于指定的最小长度
|
|
149
|
+
*
|
|
150
|
+
* @param minLen 最小长度
|
|
151
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* class User extends BaseValidator {
|
|
155
|
+
* @(VMinLength(6)('密码长度不能少于6位'))
|
|
156
|
+
* password?: string;
|
|
157
|
+
* }
|
|
158
|
+
*/
|
|
55
159
|
var VMinLength = function (minLen) {
|
|
56
160
|
return validator.BaseValidator.decoratorCreator(function (val) {
|
|
57
161
|
if (typeof val !== 'string' && !Array.isArray(val)) {
|
|
@@ -63,6 +167,19 @@ var VMinLength = function (minLen) {
|
|
|
63
167
|
return true;
|
|
64
168
|
});
|
|
65
169
|
};
|
|
170
|
+
/**
|
|
171
|
+
* 最大长度验证装饰器
|
|
172
|
+
* 验证字符串或数组的长度是否小于或等于指定的最大长度
|
|
173
|
+
*
|
|
174
|
+
* @param maxLen 最大长度
|
|
175
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* class User extends BaseValidator {
|
|
179
|
+
* @(VMaxLength(20)('用户名长度不能超过20位'))
|
|
180
|
+
* username?: string;
|
|
181
|
+
* }
|
|
182
|
+
*/
|
|
66
183
|
var VMaxLength = function (maxLen) {
|
|
67
184
|
return validator.BaseValidator.decoratorCreator(function (val) {
|
|
68
185
|
if (typeof val !== 'string' && !Array.isArray(val)) {
|
|
@@ -74,6 +191,18 @@ var VMaxLength = function (maxLen) {
|
|
|
74
191
|
return true;
|
|
75
192
|
});
|
|
76
193
|
};
|
|
194
|
+
/**
|
|
195
|
+
* 邮箱格式验证装饰器
|
|
196
|
+
* 验证字符串是否符合邮箱格式
|
|
197
|
+
*
|
|
198
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* class User extends BaseValidator {
|
|
202
|
+
* @VEmail('邮箱格式不正确')
|
|
203
|
+
* email?: string;
|
|
204
|
+
* }
|
|
205
|
+
*/
|
|
77
206
|
var VEmail = validator.BaseValidator.decoratorCreator(function (val) {
|
|
78
207
|
if (typeof val !== 'string') {
|
|
79
208
|
return false;
|
|
@@ -82,6 +211,19 @@ var VEmail = validator.BaseValidator.decoratorCreator(function (val) {
|
|
|
82
211
|
var emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
83
212
|
return emailReg.test(val);
|
|
84
213
|
});
|
|
214
|
+
/**
|
|
215
|
+
* 正则表达式验证装饰器
|
|
216
|
+
* 验证字符串是否匹配指定的正则表达式模式
|
|
217
|
+
*
|
|
218
|
+
* @param pattern 正则表达式
|
|
219
|
+
* @returns 装饰器工厂函数,可接收自定义错误消息
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* class User extends BaseValidator {
|
|
223
|
+
* @(VPattern(/^1[3-9]\d{9}$/)('手机号格式不正确'))
|
|
224
|
+
* phone?: string;
|
|
225
|
+
* }
|
|
226
|
+
*/
|
|
85
227
|
var VPattern = function (pattern) {
|
|
86
228
|
return validator.BaseValidator.decoratorCreator(function (val) {
|
|
87
229
|
if (typeof val !== 'string') {
|
|
@@ -2,12 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
var tslib = require('tslib');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* 基础验证器类
|
|
7
|
+
* 提供字段验证功能,可通过装饰器为类属性添加验证规则
|
|
8
|
+
*/
|
|
5
9
|
var BaseValidator = /** @class */ (function () {
|
|
10
|
+
/**
|
|
11
|
+
* 构造函数
|
|
12
|
+
* 初始化验证器映射存储
|
|
13
|
+
*/
|
|
6
14
|
function BaseValidator() {
|
|
15
|
+
/** 用于存储验证器映射的私有符号 */
|
|
7
16
|
this.__keySymbol = Symbol('key-description');
|
|
8
17
|
this.__keySymbol = Symbol('key-description');
|
|
9
18
|
this[this.__keySymbol] = {};
|
|
10
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* 验证单个字段
|
|
22
|
+
* @param itemKey 要验证的字段名
|
|
23
|
+
* @param itemAll 是否验证所有规则,为true时会验证该字段的所有规则,为false时遇到第一个失败的规则就停止
|
|
24
|
+
* @returns 验证错误数组,如果没有错误则返回null
|
|
25
|
+
*/
|
|
11
26
|
BaseValidator.prototype.validate = function (itemKey, itemAll) {
|
|
12
27
|
if (itemAll === void 0) { itemAll = false; }
|
|
13
28
|
var validatorMap = this[this.__keySymbol];
|
|
@@ -31,6 +46,13 @@ var BaseValidator = /** @class */ (function () {
|
|
|
31
46
|
}
|
|
32
47
|
return null;
|
|
33
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* 验证多个或所有字段
|
|
51
|
+
* @param itemAll 是否验证每个字段的所有规则,为true时会验证字段的所有规则,为false时遇到第一个失败的规则就停止
|
|
52
|
+
* @param everyItem 是否验证所有字段,为true时会验证所有字段,为false时遇到第一个失败的字段就停止
|
|
53
|
+
* @param order 验证字段的顺序,可以指定验证的字段名数组及其顺序
|
|
54
|
+
* @returns 验证错误数组,如果没有错误则返回null
|
|
55
|
+
*/
|
|
34
56
|
BaseValidator.prototype.validateAll = function (itemAll, everyItem, order) {
|
|
35
57
|
if (itemAll === void 0) { itemAll = false; }
|
|
36
58
|
if (everyItem === void 0) { everyItem = false; }
|
|
@@ -61,6 +83,39 @@ var BaseValidator = /** @class */ (function () {
|
|
|
61
83
|
}
|
|
62
84
|
return null;
|
|
63
85
|
};
|
|
86
|
+
/**
|
|
87
|
+
* 装饰器创建器
|
|
88
|
+
* 用于创建属性验证装饰器的工厂函数
|
|
89
|
+
*
|
|
90
|
+
* @param func 验证函数,接收属性值并返回布尔值表示验证结果
|
|
91
|
+
* @returns 返回一个接收错误消息的函数,该函数再返回实际的装饰器
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* // 创建一个验证字符串的装饰器
|
|
95
|
+
* const VString = BaseValidator.decoratorCreator(
|
|
96
|
+
* (val) => typeof val === 'string' || val === undefined
|
|
97
|
+
* );
|
|
98
|
+
*
|
|
99
|
+
* // 创建一个验证必填项的装饰器
|
|
100
|
+
* const VRequired = BaseValidator.decoratorCreator(
|
|
101
|
+
* (val) => val !== undefined && val !== null && val !== ''
|
|
102
|
+
* );
|
|
103
|
+
*
|
|
104
|
+
* // 在类中使用这些装饰器
|
|
105
|
+
* class User extends BaseValidator {
|
|
106
|
+
* @VString('名称必须为字符串')
|
|
107
|
+
* @(VRequired()('名称必须填写'))
|
|
108
|
+
* name?: string;
|
|
109
|
+
*
|
|
110
|
+
* // 验证使用
|
|
111
|
+
* validateName() {
|
|
112
|
+
* return this.validate('name');
|
|
113
|
+
* }
|
|
114
|
+
* }
|
|
115
|
+
*
|
|
116
|
+
* const user = new User();
|
|
117
|
+
* console.log(user.validateName()); // 显示错误信息:名称必须填写
|
|
118
|
+
*/
|
|
64
119
|
BaseValidator.decoratorCreator = function (func) {
|
|
65
120
|
return function (message) {
|
|
66
121
|
if (message === void 0) { message = function (val, value, context) { return "".concat(String(context.name), "\u683C\u5F0F\u9519\u8BEF"); }; }
|