@lytjs/common-validate 6.0.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/index.cjs +157 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +88 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.mjs +142 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +36 -0
- package/src/index.ts +224 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
function validate(value, rules) {
|
|
5
|
+
const errors = [];
|
|
6
|
+
for (const rule of rules) {
|
|
7
|
+
const result = rule.validate(value);
|
|
8
|
+
if (result === false) {
|
|
9
|
+
errors.push(rule.message || `Validation failed: ${rule.name}`);
|
|
10
|
+
} else if (typeof result === "string") {
|
|
11
|
+
errors.push(result);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
valid: errors.length === 0,
|
|
16
|
+
errors
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function createValidator(rules) {
|
|
20
|
+
return (value) => validate(value, rules);
|
|
21
|
+
}
|
|
22
|
+
var required = {
|
|
23
|
+
name: "required",
|
|
24
|
+
validate: (value) => {
|
|
25
|
+
if (value === null || value === void 0) return false;
|
|
26
|
+
if (typeof value === "string" && value.trim() === "") return false;
|
|
27
|
+
return true;
|
|
28
|
+
},
|
|
29
|
+
message: "This field is required"
|
|
30
|
+
};
|
|
31
|
+
function minLength(n) {
|
|
32
|
+
return {
|
|
33
|
+
name: "minLength",
|
|
34
|
+
validate: (value) => {
|
|
35
|
+
if (typeof value !== "string") return true;
|
|
36
|
+
return value.length >= n;
|
|
37
|
+
},
|
|
38
|
+
message: `Must be at least ${n} characters`
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function maxLength(n) {
|
|
42
|
+
return {
|
|
43
|
+
name: "maxLength",
|
|
44
|
+
validate: (value) => {
|
|
45
|
+
if (typeof value !== "string") return true;
|
|
46
|
+
return value.length <= n;
|
|
47
|
+
},
|
|
48
|
+
message: `Must be at most ${n} characters`
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function pattern(regex, message) {
|
|
52
|
+
return {
|
|
53
|
+
name: "pattern",
|
|
54
|
+
validate: (value) => {
|
|
55
|
+
if (typeof value !== "string") return true;
|
|
56
|
+
return regex.test(value);
|
|
57
|
+
},
|
|
58
|
+
message: message || "Value does not match the required pattern"
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
var email = {
|
|
62
|
+
name: "email",
|
|
63
|
+
validate: (value) => {
|
|
64
|
+
if (typeof value !== "string") return true;
|
|
65
|
+
if (value === "") return true;
|
|
66
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
67
|
+
},
|
|
68
|
+
message: "Must be a valid email address"
|
|
69
|
+
};
|
|
70
|
+
var url = {
|
|
71
|
+
name: "url",
|
|
72
|
+
validate: (value) => {
|
|
73
|
+
if (typeof value !== "string") return true;
|
|
74
|
+
if (value === "") return true;
|
|
75
|
+
try {
|
|
76
|
+
new URL(value);
|
|
77
|
+
return true;
|
|
78
|
+
} catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
message: "Must be a valid URL"
|
|
83
|
+
};
|
|
84
|
+
var number = {
|
|
85
|
+
name: "number",
|
|
86
|
+
validate: (value) => {
|
|
87
|
+
if (value === null || value === void 0 || value === "") return true;
|
|
88
|
+
return typeof value === "number" || !isNaN(Number(value));
|
|
89
|
+
},
|
|
90
|
+
message: "Must be a number"
|
|
91
|
+
};
|
|
92
|
+
function min(n) {
|
|
93
|
+
return {
|
|
94
|
+
name: "min",
|
|
95
|
+
validate: (value) => {
|
|
96
|
+
if (typeof value !== "number") return true;
|
|
97
|
+
return value >= n;
|
|
98
|
+
},
|
|
99
|
+
message: `Must be at least ${n}`
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function max(n) {
|
|
103
|
+
return {
|
|
104
|
+
name: "max",
|
|
105
|
+
validate: (value) => {
|
|
106
|
+
if (typeof value !== "number") return true;
|
|
107
|
+
return value <= n;
|
|
108
|
+
},
|
|
109
|
+
message: `Must be at most ${n}`
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function oneOf(values) {
|
|
113
|
+
return {
|
|
114
|
+
name: "oneOf",
|
|
115
|
+
validate: (value) => {
|
|
116
|
+
return values.includes(value);
|
|
117
|
+
},
|
|
118
|
+
message: `Must be one of: ${values.join(", ")}`
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function custom(fn, message) {
|
|
122
|
+
return {
|
|
123
|
+
name: "custom",
|
|
124
|
+
validate: fn,
|
|
125
|
+
message
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
var builtInRules = {
|
|
129
|
+
required,
|
|
130
|
+
minLength,
|
|
131
|
+
maxLength,
|
|
132
|
+
pattern,
|
|
133
|
+
email,
|
|
134
|
+
url,
|
|
135
|
+
number,
|
|
136
|
+
min,
|
|
137
|
+
max,
|
|
138
|
+
oneOf,
|
|
139
|
+
custom
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
exports.builtInRules = builtInRules;
|
|
143
|
+
exports.createValidator = createValidator;
|
|
144
|
+
exports.custom = custom;
|
|
145
|
+
exports.email = email;
|
|
146
|
+
exports.max = max;
|
|
147
|
+
exports.maxLength = maxLength;
|
|
148
|
+
exports.min = min;
|
|
149
|
+
exports.minLength = minLength;
|
|
150
|
+
exports.number = number;
|
|
151
|
+
exports.oneOf = oneOf;
|
|
152
|
+
exports.pattern = pattern;
|
|
153
|
+
exports.required = required;
|
|
154
|
+
exports.url = url;
|
|
155
|
+
exports.validate = validate;
|
|
156
|
+
//# sourceMappingURL=index.cjs.map
|
|
157
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * @lytjs/common-validate\r\n * 轻量级验证工具\r\n */\r\n\r\ndeclare const __DEV__: boolean;\r\n\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: string[];\r\n}\r\n\r\nexport type ValidationRule = {\r\n name: string;\r\n validate: (value: unknown) => boolean | string;\r\n message?: string;\r\n};\r\n\r\n/**\r\n * 验证值是否符合所有规则\r\n *\r\n * @param value - 待验证的值\r\n * @param rules - 验证规则列表\r\n * @returns 验证结果\r\n */\r\nexport function validate(value: unknown, rules: ValidationRule[]): ValidationResult {\r\n const errors: string[] = [];\r\n\r\n for (const rule of rules) {\r\n const result = rule.validate(value);\r\n if (result === false) {\r\n errors.push(rule.message || `Validation failed: ${rule.name}`);\r\n } else if (typeof result === 'string') {\r\n errors.push(result);\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n };\r\n}\r\n\r\n/**\r\n * 创建一个可复用的验证器函数\r\n *\r\n * @param rules - 验证规则列表\r\n * @returns 验证函数\r\n */\r\nexport function createValidator(\r\n rules: ValidationRule[],\r\n): (value: unknown) => ValidationResult {\r\n return (value: unknown) => validate(value, rules);\r\n}\r\n\r\n// --- 内置规则 ---\r\n\r\n/**\r\n * 必填规则\r\n */\r\nexport const required: ValidationRule = {\r\n name: 'required',\r\n validate: (value: unknown) => {\r\n if (value === null || value === undefined) return false;\r\n if (typeof value === 'string' && value.trim() === '') return false;\r\n return true;\r\n },\r\n message: 'This field is required',\r\n};\r\n\r\n/**\r\n * 最小长度规则\r\n */\r\nexport function minLength(n: number): ValidationRule {\r\n return {\r\n name: 'minLength',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true; // Skip non-strings\r\n return value.length >= n;\r\n },\r\n message: `Must be at least ${n} characters`,\r\n };\r\n}\r\n\r\n/**\r\n * 最大长度规则\r\n */\r\nexport function maxLength(n: number): ValidationRule {\r\n return {\r\n name: 'maxLength',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true;\r\n return value.length <= n;\r\n },\r\n message: `Must be at most ${n} characters`,\r\n };\r\n}\r\n\r\n/**\r\n * 正则匹配规则\r\n */\r\nexport function pattern(regex: RegExp, message?: string): ValidationRule {\r\n return {\r\n name: 'pattern',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true;\r\n return regex.test(value);\r\n },\r\n message: message || 'Value does not match the required pattern',\r\n };\r\n}\r\n\r\n/**\r\n * 邮箱格式规则\r\n */\r\nexport const email: ValidationRule = {\r\n name: 'email',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true;\r\n if (value === '') return true; // Empty strings are handled by required\r\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\r\n },\r\n message: 'Must be a valid email address',\r\n};\r\n\r\n/**\r\n * URL 格式规则\r\n */\r\nexport const url: ValidationRule = {\r\n name: 'url',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true;\r\n if (value === '') return true;\r\n try {\r\n new URL(value);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n message: 'Must be a valid URL',\r\n};\r\n\r\n/**\r\n * 数字规则\r\n */\r\nexport const number: ValidationRule = {\r\n name: 'number',\r\n validate: (value: unknown) => {\r\n if (value === null || value === undefined || value === '') return true;\r\n return typeof value === 'number' || !isNaN(Number(value));\r\n },\r\n message: 'Must be a number',\r\n};\r\n\r\n/**\r\n * 最小值规则\r\n */\r\nexport function min(n: number): ValidationRule {\r\n return {\r\n name: 'min',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'number') return true;\r\n return value >= n;\r\n },\r\n message: `Must be at least ${n}`,\r\n };\r\n}\r\n\r\n/**\r\n * 最大值规则\r\n */\r\nexport function max(n: number): ValidationRule {\r\n return {\r\n name: 'max',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'number') return true;\r\n return value <= n;\r\n },\r\n message: `Must be at most ${n}`,\r\n };\r\n}\r\n\r\n/**\r\n * 枚举值规则\r\n */\r\nexport function oneOf(values: unknown[]): ValidationRule {\r\n return {\r\n name: 'oneOf',\r\n validate: (value: unknown) => {\r\n return values.includes(value);\r\n },\r\n message: `Must be one of: ${values.join(', ')}`,\r\n };\r\n}\r\n\r\n/**\r\n * 自定义验证规则\r\n */\r\nexport function custom(\r\n fn: (value: unknown) => boolean,\r\n message: string,\r\n): ValidationRule {\r\n return {\r\n name: 'custom',\r\n validate: fn,\r\n message,\r\n };\r\n}\r\n\r\n/** 所有内置规则的集合 */\r\nexport const builtInRules = {\r\n required,\r\n minLength,\r\n maxLength,\r\n pattern,\r\n email,\r\n url,\r\n number,\r\n min,\r\n max,\r\n oneOf,\r\n custom,\r\n};\r\n"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lytjs/common-validate
|
|
3
|
+
* 轻量级验证工具
|
|
4
|
+
*/
|
|
5
|
+
interface ValidationResult {
|
|
6
|
+
valid: boolean;
|
|
7
|
+
errors: string[];
|
|
8
|
+
}
|
|
9
|
+
type ValidationRule = {
|
|
10
|
+
name: string;
|
|
11
|
+
validate: (value: unknown) => boolean | string;
|
|
12
|
+
message?: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* 验证值是否符合所有规则
|
|
16
|
+
*
|
|
17
|
+
* @param value - 待验证的值
|
|
18
|
+
* @param rules - 验证规则列表
|
|
19
|
+
* @returns 验证结果
|
|
20
|
+
*/
|
|
21
|
+
declare function validate(value: unknown, rules: ValidationRule[]): ValidationResult;
|
|
22
|
+
/**
|
|
23
|
+
* 创建一个可复用的验证器函数
|
|
24
|
+
*
|
|
25
|
+
* @param rules - 验证规则列表
|
|
26
|
+
* @returns 验证函数
|
|
27
|
+
*/
|
|
28
|
+
declare function createValidator(rules: ValidationRule[]): (value: unknown) => ValidationResult;
|
|
29
|
+
/**
|
|
30
|
+
* 必填规则
|
|
31
|
+
*/
|
|
32
|
+
declare const required: ValidationRule;
|
|
33
|
+
/**
|
|
34
|
+
* 最小长度规则
|
|
35
|
+
*/
|
|
36
|
+
declare function minLength(n: number): ValidationRule;
|
|
37
|
+
/**
|
|
38
|
+
* 最大长度规则
|
|
39
|
+
*/
|
|
40
|
+
declare function maxLength(n: number): ValidationRule;
|
|
41
|
+
/**
|
|
42
|
+
* 正则匹配规则
|
|
43
|
+
*/
|
|
44
|
+
declare function pattern(regex: RegExp, message?: string): ValidationRule;
|
|
45
|
+
/**
|
|
46
|
+
* 邮箱格式规则
|
|
47
|
+
*/
|
|
48
|
+
declare const email: ValidationRule;
|
|
49
|
+
/**
|
|
50
|
+
* URL 格式规则
|
|
51
|
+
*/
|
|
52
|
+
declare const url: ValidationRule;
|
|
53
|
+
/**
|
|
54
|
+
* 数字规则
|
|
55
|
+
*/
|
|
56
|
+
declare const number: ValidationRule;
|
|
57
|
+
/**
|
|
58
|
+
* 最小值规则
|
|
59
|
+
*/
|
|
60
|
+
declare function min(n: number): ValidationRule;
|
|
61
|
+
/**
|
|
62
|
+
* 最大值规则
|
|
63
|
+
*/
|
|
64
|
+
declare function max(n: number): ValidationRule;
|
|
65
|
+
/**
|
|
66
|
+
* 枚举值规则
|
|
67
|
+
*/
|
|
68
|
+
declare function oneOf(values: unknown[]): ValidationRule;
|
|
69
|
+
/**
|
|
70
|
+
* 自定义验证规则
|
|
71
|
+
*/
|
|
72
|
+
declare function custom(fn: (value: unknown) => boolean, message: string): ValidationRule;
|
|
73
|
+
/** 所有内置规则的集合 */
|
|
74
|
+
declare const builtInRules: {
|
|
75
|
+
required: ValidationRule;
|
|
76
|
+
minLength: typeof minLength;
|
|
77
|
+
maxLength: typeof maxLength;
|
|
78
|
+
pattern: typeof pattern;
|
|
79
|
+
email: ValidationRule;
|
|
80
|
+
url: ValidationRule;
|
|
81
|
+
number: ValidationRule;
|
|
82
|
+
min: typeof min;
|
|
83
|
+
max: typeof max;
|
|
84
|
+
oneOf: typeof oneOf;
|
|
85
|
+
custom: typeof custom;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export { type ValidationResult, type ValidationRule, builtInRules, createValidator, custom, email, max, maxLength, min, minLength, number, oneOf, pattern, required, url, validate };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lytjs/common-validate
|
|
3
|
+
* 轻量级验证工具
|
|
4
|
+
*/
|
|
5
|
+
interface ValidationResult {
|
|
6
|
+
valid: boolean;
|
|
7
|
+
errors: string[];
|
|
8
|
+
}
|
|
9
|
+
type ValidationRule = {
|
|
10
|
+
name: string;
|
|
11
|
+
validate: (value: unknown) => boolean | string;
|
|
12
|
+
message?: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* 验证值是否符合所有规则
|
|
16
|
+
*
|
|
17
|
+
* @param value - 待验证的值
|
|
18
|
+
* @param rules - 验证规则列表
|
|
19
|
+
* @returns 验证结果
|
|
20
|
+
*/
|
|
21
|
+
declare function validate(value: unknown, rules: ValidationRule[]): ValidationResult;
|
|
22
|
+
/**
|
|
23
|
+
* 创建一个可复用的验证器函数
|
|
24
|
+
*
|
|
25
|
+
* @param rules - 验证规则列表
|
|
26
|
+
* @returns 验证函数
|
|
27
|
+
*/
|
|
28
|
+
declare function createValidator(rules: ValidationRule[]): (value: unknown) => ValidationResult;
|
|
29
|
+
/**
|
|
30
|
+
* 必填规则
|
|
31
|
+
*/
|
|
32
|
+
declare const required: ValidationRule;
|
|
33
|
+
/**
|
|
34
|
+
* 最小长度规则
|
|
35
|
+
*/
|
|
36
|
+
declare function minLength(n: number): ValidationRule;
|
|
37
|
+
/**
|
|
38
|
+
* 最大长度规则
|
|
39
|
+
*/
|
|
40
|
+
declare function maxLength(n: number): ValidationRule;
|
|
41
|
+
/**
|
|
42
|
+
* 正则匹配规则
|
|
43
|
+
*/
|
|
44
|
+
declare function pattern(regex: RegExp, message?: string): ValidationRule;
|
|
45
|
+
/**
|
|
46
|
+
* 邮箱格式规则
|
|
47
|
+
*/
|
|
48
|
+
declare const email: ValidationRule;
|
|
49
|
+
/**
|
|
50
|
+
* URL 格式规则
|
|
51
|
+
*/
|
|
52
|
+
declare const url: ValidationRule;
|
|
53
|
+
/**
|
|
54
|
+
* 数字规则
|
|
55
|
+
*/
|
|
56
|
+
declare const number: ValidationRule;
|
|
57
|
+
/**
|
|
58
|
+
* 最小值规则
|
|
59
|
+
*/
|
|
60
|
+
declare function min(n: number): ValidationRule;
|
|
61
|
+
/**
|
|
62
|
+
* 最大值规则
|
|
63
|
+
*/
|
|
64
|
+
declare function max(n: number): ValidationRule;
|
|
65
|
+
/**
|
|
66
|
+
* 枚举值规则
|
|
67
|
+
*/
|
|
68
|
+
declare function oneOf(values: unknown[]): ValidationRule;
|
|
69
|
+
/**
|
|
70
|
+
* 自定义验证规则
|
|
71
|
+
*/
|
|
72
|
+
declare function custom(fn: (value: unknown) => boolean, message: string): ValidationRule;
|
|
73
|
+
/** 所有内置规则的集合 */
|
|
74
|
+
declare const builtInRules: {
|
|
75
|
+
required: ValidationRule;
|
|
76
|
+
minLength: typeof minLength;
|
|
77
|
+
maxLength: typeof maxLength;
|
|
78
|
+
pattern: typeof pattern;
|
|
79
|
+
email: ValidationRule;
|
|
80
|
+
url: ValidationRule;
|
|
81
|
+
number: ValidationRule;
|
|
82
|
+
min: typeof min;
|
|
83
|
+
max: typeof max;
|
|
84
|
+
oneOf: typeof oneOf;
|
|
85
|
+
custom: typeof custom;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export { type ValidationResult, type ValidationRule, builtInRules, createValidator, custom, email, max, maxLength, min, minLength, number, oneOf, pattern, required, url, validate };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
function validate(value, rules) {
|
|
3
|
+
const errors = [];
|
|
4
|
+
for (const rule of rules) {
|
|
5
|
+
const result = rule.validate(value);
|
|
6
|
+
if (result === false) {
|
|
7
|
+
errors.push(rule.message || `Validation failed: ${rule.name}`);
|
|
8
|
+
} else if (typeof result === "string") {
|
|
9
|
+
errors.push(result);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
valid: errors.length === 0,
|
|
14
|
+
errors
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function createValidator(rules) {
|
|
18
|
+
return (value) => validate(value, rules);
|
|
19
|
+
}
|
|
20
|
+
var required = {
|
|
21
|
+
name: "required",
|
|
22
|
+
validate: (value) => {
|
|
23
|
+
if (value === null || value === void 0) return false;
|
|
24
|
+
if (typeof value === "string" && value.trim() === "") return false;
|
|
25
|
+
return true;
|
|
26
|
+
},
|
|
27
|
+
message: "This field is required"
|
|
28
|
+
};
|
|
29
|
+
function minLength(n) {
|
|
30
|
+
return {
|
|
31
|
+
name: "minLength",
|
|
32
|
+
validate: (value) => {
|
|
33
|
+
if (typeof value !== "string") return true;
|
|
34
|
+
return value.length >= n;
|
|
35
|
+
},
|
|
36
|
+
message: `Must be at least ${n} characters`
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function maxLength(n) {
|
|
40
|
+
return {
|
|
41
|
+
name: "maxLength",
|
|
42
|
+
validate: (value) => {
|
|
43
|
+
if (typeof value !== "string") return true;
|
|
44
|
+
return value.length <= n;
|
|
45
|
+
},
|
|
46
|
+
message: `Must be at most ${n} characters`
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function pattern(regex, message) {
|
|
50
|
+
return {
|
|
51
|
+
name: "pattern",
|
|
52
|
+
validate: (value) => {
|
|
53
|
+
if (typeof value !== "string") return true;
|
|
54
|
+
return regex.test(value);
|
|
55
|
+
},
|
|
56
|
+
message: message || "Value does not match the required pattern"
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
var email = {
|
|
60
|
+
name: "email",
|
|
61
|
+
validate: (value) => {
|
|
62
|
+
if (typeof value !== "string") return true;
|
|
63
|
+
if (value === "") return true;
|
|
64
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
65
|
+
},
|
|
66
|
+
message: "Must be a valid email address"
|
|
67
|
+
};
|
|
68
|
+
var url = {
|
|
69
|
+
name: "url",
|
|
70
|
+
validate: (value) => {
|
|
71
|
+
if (typeof value !== "string") return true;
|
|
72
|
+
if (value === "") return true;
|
|
73
|
+
try {
|
|
74
|
+
new URL(value);
|
|
75
|
+
return true;
|
|
76
|
+
} catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
message: "Must be a valid URL"
|
|
81
|
+
};
|
|
82
|
+
var number = {
|
|
83
|
+
name: "number",
|
|
84
|
+
validate: (value) => {
|
|
85
|
+
if (value === null || value === void 0 || value === "") return true;
|
|
86
|
+
return typeof value === "number" || !isNaN(Number(value));
|
|
87
|
+
},
|
|
88
|
+
message: "Must be a number"
|
|
89
|
+
};
|
|
90
|
+
function min(n) {
|
|
91
|
+
return {
|
|
92
|
+
name: "min",
|
|
93
|
+
validate: (value) => {
|
|
94
|
+
if (typeof value !== "number") return true;
|
|
95
|
+
return value >= n;
|
|
96
|
+
},
|
|
97
|
+
message: `Must be at least ${n}`
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function max(n) {
|
|
101
|
+
return {
|
|
102
|
+
name: "max",
|
|
103
|
+
validate: (value) => {
|
|
104
|
+
if (typeof value !== "number") return true;
|
|
105
|
+
return value <= n;
|
|
106
|
+
},
|
|
107
|
+
message: `Must be at most ${n}`
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function oneOf(values) {
|
|
111
|
+
return {
|
|
112
|
+
name: "oneOf",
|
|
113
|
+
validate: (value) => {
|
|
114
|
+
return values.includes(value);
|
|
115
|
+
},
|
|
116
|
+
message: `Must be one of: ${values.join(", ")}`
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function custom(fn, message) {
|
|
120
|
+
return {
|
|
121
|
+
name: "custom",
|
|
122
|
+
validate: fn,
|
|
123
|
+
message
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
var builtInRules = {
|
|
127
|
+
required,
|
|
128
|
+
minLength,
|
|
129
|
+
maxLength,
|
|
130
|
+
pattern,
|
|
131
|
+
email,
|
|
132
|
+
url,
|
|
133
|
+
number,
|
|
134
|
+
min,
|
|
135
|
+
max,
|
|
136
|
+
oneOf,
|
|
137
|
+
custom
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export { builtInRules, createValidator, custom, email, max, maxLength, min, minLength, number, oneOf, pattern, required, url, validate };
|
|
141
|
+
//# sourceMappingURL=index.mjs.map
|
|
142
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * @lytjs/common-validate\r\n * 轻量级验证工具\r\n */\r\n\r\ndeclare const __DEV__: boolean;\r\n\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: string[];\r\n}\r\n\r\nexport type ValidationRule = {\r\n name: string;\r\n validate: (value: unknown) => boolean | string;\r\n message?: string;\r\n};\r\n\r\n/**\r\n * 验证值是否符合所有规则\r\n *\r\n * @param value - 待验证的值\r\n * @param rules - 验证规则列表\r\n * @returns 验证结果\r\n */\r\nexport function validate(value: unknown, rules: ValidationRule[]): ValidationResult {\r\n const errors: string[] = [];\r\n\r\n for (const rule of rules) {\r\n const result = rule.validate(value);\r\n if (result === false) {\r\n errors.push(rule.message || `Validation failed: ${rule.name}`);\r\n } else if (typeof result === 'string') {\r\n errors.push(result);\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n };\r\n}\r\n\r\n/**\r\n * 创建一个可复用的验证器函数\r\n *\r\n * @param rules - 验证规则列表\r\n * @returns 验证函数\r\n */\r\nexport function createValidator(\r\n rules: ValidationRule[],\r\n): (value: unknown) => ValidationResult {\r\n return (value: unknown) => validate(value, rules);\r\n}\r\n\r\n// --- 内置规则 ---\r\n\r\n/**\r\n * 必填规则\r\n */\r\nexport const required: ValidationRule = {\r\n name: 'required',\r\n validate: (value: unknown) => {\r\n if (value === null || value === undefined) return false;\r\n if (typeof value === 'string' && value.trim() === '') return false;\r\n return true;\r\n },\r\n message: 'This field is required',\r\n};\r\n\r\n/**\r\n * 最小长度规则\r\n */\r\nexport function minLength(n: number): ValidationRule {\r\n return {\r\n name: 'minLength',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true; // Skip non-strings\r\n return value.length >= n;\r\n },\r\n message: `Must be at least ${n} characters`,\r\n };\r\n}\r\n\r\n/**\r\n * 最大长度规则\r\n */\r\nexport function maxLength(n: number): ValidationRule {\r\n return {\r\n name: 'maxLength',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true;\r\n return value.length <= n;\r\n },\r\n message: `Must be at most ${n} characters`,\r\n };\r\n}\r\n\r\n/**\r\n * 正则匹配规则\r\n */\r\nexport function pattern(regex: RegExp, message?: string): ValidationRule {\r\n return {\r\n name: 'pattern',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true;\r\n return regex.test(value);\r\n },\r\n message: message || 'Value does not match the required pattern',\r\n };\r\n}\r\n\r\n/**\r\n * 邮箱格式规则\r\n */\r\nexport const email: ValidationRule = {\r\n name: 'email',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true;\r\n if (value === '') return true; // Empty strings are handled by required\r\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\r\n },\r\n message: 'Must be a valid email address',\r\n};\r\n\r\n/**\r\n * URL 格式规则\r\n */\r\nexport const url: ValidationRule = {\r\n name: 'url',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'string') return true;\r\n if (value === '') return true;\r\n try {\r\n new URL(value);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n message: 'Must be a valid URL',\r\n};\r\n\r\n/**\r\n * 数字规则\r\n */\r\nexport const number: ValidationRule = {\r\n name: 'number',\r\n validate: (value: unknown) => {\r\n if (value === null || value === undefined || value === '') return true;\r\n return typeof value === 'number' || !isNaN(Number(value));\r\n },\r\n message: 'Must be a number',\r\n};\r\n\r\n/**\r\n * 最小值规则\r\n */\r\nexport function min(n: number): ValidationRule {\r\n return {\r\n name: 'min',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'number') return true;\r\n return value >= n;\r\n },\r\n message: `Must be at least ${n}`,\r\n };\r\n}\r\n\r\n/**\r\n * 最大值规则\r\n */\r\nexport function max(n: number): ValidationRule {\r\n return {\r\n name: 'max',\r\n validate: (value: unknown) => {\r\n if (typeof value !== 'number') return true;\r\n return value <= n;\r\n },\r\n message: `Must be at most ${n}`,\r\n };\r\n}\r\n\r\n/**\r\n * 枚举值规则\r\n */\r\nexport function oneOf(values: unknown[]): ValidationRule {\r\n return {\r\n name: 'oneOf',\r\n validate: (value: unknown) => {\r\n return values.includes(value);\r\n },\r\n message: `Must be one of: ${values.join(', ')}`,\r\n };\r\n}\r\n\r\n/**\r\n * 自定义验证规则\r\n */\r\nexport function custom(\r\n fn: (value: unknown) => boolean,\r\n message: string,\r\n): ValidationRule {\r\n return {\r\n name: 'custom',\r\n validate: fn,\r\n message,\r\n };\r\n}\r\n\r\n/** 所有内置规则的集合 */\r\nexport const builtInRules = {\r\n required,\r\n minLength,\r\n maxLength,\r\n pattern,\r\n email,\r\n url,\r\n number,\r\n min,\r\n max,\r\n oneOf,\r\n custom,\r\n};\r\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lytjs/common-validate",
|
|
3
|
+
"version": "6.0.0",
|
|
4
|
+
"description": "Lightweight validation utilities for LytJS",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"test:coverage": "vitest run --coverage",
|
|
23
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"type-check": "tsc --noEmit",
|
|
26
|
+
"clean": "rm -rf dist"
|
|
27
|
+
},
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"jsdom": "^26.0.0",
|
|
32
|
+
"tsup": "^8.4.0",
|
|
33
|
+
"typescript": "^5.8.2",
|
|
34
|
+
"vitest": "^3.0.7"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lytjs/common-validate
|
|
3
|
+
* 轻量级验证工具
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
declare const __DEV__: boolean;
|
|
7
|
+
|
|
8
|
+
export interface ValidationResult {
|
|
9
|
+
valid: boolean;
|
|
10
|
+
errors: string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type ValidationRule = {
|
|
14
|
+
name: string;
|
|
15
|
+
validate: (value: unknown) => boolean | string;
|
|
16
|
+
message?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 验证值是否符合所有规则
|
|
21
|
+
*
|
|
22
|
+
* @param value - 待验证的值
|
|
23
|
+
* @param rules - 验证规则列表
|
|
24
|
+
* @returns 验证结果
|
|
25
|
+
*/
|
|
26
|
+
export function validate(value: unknown, rules: ValidationRule[]): ValidationResult {
|
|
27
|
+
const errors: string[] = [];
|
|
28
|
+
|
|
29
|
+
for (const rule of rules) {
|
|
30
|
+
const result = rule.validate(value);
|
|
31
|
+
if (result === false) {
|
|
32
|
+
errors.push(rule.message || `Validation failed: ${rule.name}`);
|
|
33
|
+
} else if (typeof result === 'string') {
|
|
34
|
+
errors.push(result);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
valid: errors.length === 0,
|
|
40
|
+
errors,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 创建一个可复用的验证器函数
|
|
46
|
+
*
|
|
47
|
+
* @param rules - 验证规则列表
|
|
48
|
+
* @returns 验证函数
|
|
49
|
+
*/
|
|
50
|
+
export function createValidator(
|
|
51
|
+
rules: ValidationRule[],
|
|
52
|
+
): (value: unknown) => ValidationResult {
|
|
53
|
+
return (value: unknown) => validate(value, rules);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// --- 内置规则 ---
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 必填规则
|
|
60
|
+
*/
|
|
61
|
+
export const required: ValidationRule = {
|
|
62
|
+
name: 'required',
|
|
63
|
+
validate: (value: unknown) => {
|
|
64
|
+
if (value === null || value === undefined) return false;
|
|
65
|
+
if (typeof value === 'string' && value.trim() === '') return false;
|
|
66
|
+
return true;
|
|
67
|
+
},
|
|
68
|
+
message: 'This field is required',
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 最小长度规则
|
|
73
|
+
*/
|
|
74
|
+
export function minLength(n: number): ValidationRule {
|
|
75
|
+
return {
|
|
76
|
+
name: 'minLength',
|
|
77
|
+
validate: (value: unknown) => {
|
|
78
|
+
if (typeof value !== 'string') return true; // Skip non-strings
|
|
79
|
+
return value.length >= n;
|
|
80
|
+
},
|
|
81
|
+
message: `Must be at least ${n} characters`,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 最大长度规则
|
|
87
|
+
*/
|
|
88
|
+
export function maxLength(n: number): ValidationRule {
|
|
89
|
+
return {
|
|
90
|
+
name: 'maxLength',
|
|
91
|
+
validate: (value: unknown) => {
|
|
92
|
+
if (typeof value !== 'string') return true;
|
|
93
|
+
return value.length <= n;
|
|
94
|
+
},
|
|
95
|
+
message: `Must be at most ${n} characters`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 正则匹配规则
|
|
101
|
+
*/
|
|
102
|
+
export function pattern(regex: RegExp, message?: string): ValidationRule {
|
|
103
|
+
return {
|
|
104
|
+
name: 'pattern',
|
|
105
|
+
validate: (value: unknown) => {
|
|
106
|
+
if (typeof value !== 'string') return true;
|
|
107
|
+
return regex.test(value);
|
|
108
|
+
},
|
|
109
|
+
message: message || 'Value does not match the required pattern',
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 邮箱格式规则
|
|
115
|
+
*/
|
|
116
|
+
export const email: ValidationRule = {
|
|
117
|
+
name: 'email',
|
|
118
|
+
validate: (value: unknown) => {
|
|
119
|
+
if (typeof value !== 'string') return true;
|
|
120
|
+
if (value === '') return true; // Empty strings are handled by required
|
|
121
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
122
|
+
},
|
|
123
|
+
message: 'Must be a valid email address',
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* URL 格式规则
|
|
128
|
+
*/
|
|
129
|
+
export const url: ValidationRule = {
|
|
130
|
+
name: 'url',
|
|
131
|
+
validate: (value: unknown) => {
|
|
132
|
+
if (typeof value !== 'string') return true;
|
|
133
|
+
if (value === '') return true;
|
|
134
|
+
try {
|
|
135
|
+
new URL(value);
|
|
136
|
+
return true;
|
|
137
|
+
} catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
message: 'Must be a valid URL',
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* 数字规则
|
|
146
|
+
*/
|
|
147
|
+
export const number: ValidationRule = {
|
|
148
|
+
name: 'number',
|
|
149
|
+
validate: (value: unknown) => {
|
|
150
|
+
if (value === null || value === undefined || value === '') return true;
|
|
151
|
+
return typeof value === 'number' || !isNaN(Number(value));
|
|
152
|
+
},
|
|
153
|
+
message: 'Must be a number',
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* 最小值规则
|
|
158
|
+
*/
|
|
159
|
+
export function min(n: number): ValidationRule {
|
|
160
|
+
return {
|
|
161
|
+
name: 'min',
|
|
162
|
+
validate: (value: unknown) => {
|
|
163
|
+
if (typeof value !== 'number') return true;
|
|
164
|
+
return value >= n;
|
|
165
|
+
},
|
|
166
|
+
message: `Must be at least ${n}`,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 最大值规则
|
|
172
|
+
*/
|
|
173
|
+
export function max(n: number): ValidationRule {
|
|
174
|
+
return {
|
|
175
|
+
name: 'max',
|
|
176
|
+
validate: (value: unknown) => {
|
|
177
|
+
if (typeof value !== 'number') return true;
|
|
178
|
+
return value <= n;
|
|
179
|
+
},
|
|
180
|
+
message: `Must be at most ${n}`,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 枚举值规则
|
|
186
|
+
*/
|
|
187
|
+
export function oneOf(values: unknown[]): ValidationRule {
|
|
188
|
+
return {
|
|
189
|
+
name: 'oneOf',
|
|
190
|
+
validate: (value: unknown) => {
|
|
191
|
+
return values.includes(value);
|
|
192
|
+
},
|
|
193
|
+
message: `Must be one of: ${values.join(', ')}`,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* 自定义验证规则
|
|
199
|
+
*/
|
|
200
|
+
export function custom(
|
|
201
|
+
fn: (value: unknown) => boolean,
|
|
202
|
+
message: string,
|
|
203
|
+
): ValidationRule {
|
|
204
|
+
return {
|
|
205
|
+
name: 'custom',
|
|
206
|
+
validate: fn,
|
|
207
|
+
message,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** 所有内置规则的集合 */
|
|
212
|
+
export const builtInRules = {
|
|
213
|
+
required,
|
|
214
|
+
minLength,
|
|
215
|
+
maxLength,
|
|
216
|
+
pattern,
|
|
217
|
+
email,
|
|
218
|
+
url,
|
|
219
|
+
number,
|
|
220
|
+
min,
|
|
221
|
+
max,
|
|
222
|
+
oneOf,
|
|
223
|
+
custom,
|
|
224
|
+
};
|