quantique-field-validator 1.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/README.md +0 -0
- package/index.js +300 -0
- package/package.json +22 -0
package/README.md
ADDED
|
Binary file
|
package/index.js
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced dynamic validator with custom function support
|
|
3
|
+
* @param {string} value - The value to validate
|
|
4
|
+
* @param {string} type - Type of validation ('name', 'email', 'mobile', 'address', etc.)
|
|
5
|
+
* @param {object} rules - Custom rules for validation
|
|
6
|
+
* @param {function} [customValidator] - Optional custom validation function
|
|
7
|
+
* @returns {object} - Returns { isValid: boolean, error: string }
|
|
8
|
+
*/
|
|
9
|
+
const dynamicValidator = (value, type, rules = {}, customValidator = null) => {
|
|
10
|
+
// Default error messages
|
|
11
|
+
const defaultErrorMessages = {
|
|
12
|
+
required: "This field is required",
|
|
13
|
+
minLength: `Minimum length should be ${rules.minLength}`,
|
|
14
|
+
maxLength: `Maximum length should be ${rules.maxLength}`,
|
|
15
|
+
invalid: `Invalid ${type}`,
|
|
16
|
+
custom: "Validation failed",
|
|
17
|
+
customValidation:
|
|
18
|
+
rules.errorMessages?.customValidation || "Custom validation failed",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Trim the value if it's a string
|
|
22
|
+
const trimmedValue = typeof value === "string" ? value.trim() : value;
|
|
23
|
+
|
|
24
|
+
// Check if field is required and empty
|
|
25
|
+
if (rules.required && (!trimmedValue || trimmedValue === "")) {
|
|
26
|
+
return {
|
|
27
|
+
isValid: false,
|
|
28
|
+
error: rules.errorMessages?.required || defaultErrorMessages.required,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Skip further validation if the field is empty and not required
|
|
33
|
+
if (!rules.required && (!trimmedValue || trimmedValue === "")) {
|
|
34
|
+
return { isValid: true, error: "" };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// First run custom validator if provided (highest priority)
|
|
38
|
+
if (customValidator && typeof customValidator === "function") {
|
|
39
|
+
const customValidation = customValidator(trimmedValue);
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
typeof customValidation === "object" &&
|
|
43
|
+
customValidation.isValid === false
|
|
44
|
+
) {
|
|
45
|
+
return {
|
|
46
|
+
isValid: false,
|
|
47
|
+
error: customValidation.error || defaultErrorMessages.customValidation,
|
|
48
|
+
};
|
|
49
|
+
} else if (customValidation === false) {
|
|
50
|
+
return {
|
|
51
|
+
isValid: false,
|
|
52
|
+
error: defaultErrorMessages.customValidation,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// If custom validator returns true or { isValid: true }, continue with other validations
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Then run any custom validator in rules
|
|
59
|
+
if (rules.customValidator && typeof rules.customValidator === "function") {
|
|
60
|
+
const rulesCustomValidation = rules.customValidator(trimmedValue);
|
|
61
|
+
|
|
62
|
+
if (
|
|
63
|
+
typeof rulesCustomValidation === "object" &&
|
|
64
|
+
rulesCustomValidation.isValid === false
|
|
65
|
+
) {
|
|
66
|
+
return {
|
|
67
|
+
isValid: false,
|
|
68
|
+
error: rulesCustomValidation.error || defaultErrorMessages.custom,
|
|
69
|
+
};
|
|
70
|
+
} else if (rulesCustomValidation === false) {
|
|
71
|
+
return {
|
|
72
|
+
isValid: false,
|
|
73
|
+
error: defaultErrorMessages.custom,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Then validate based on type
|
|
79
|
+
switch (type) {
|
|
80
|
+
case "name":
|
|
81
|
+
return validateName(trimmedValue, rules, defaultErrorMessages);
|
|
82
|
+
case "email":
|
|
83
|
+
return validateEmail(trimmedValue, rules, defaultErrorMessages);
|
|
84
|
+
case "mobile":
|
|
85
|
+
return validateMobile(trimmedValue, rules, defaultErrorMessages);
|
|
86
|
+
case "address":
|
|
87
|
+
return validateAddress(trimmedValue, rules, defaultErrorMessages);
|
|
88
|
+
case "password":
|
|
89
|
+
return validatePassword(trimmedValue, rules, defaultErrorMessages);
|
|
90
|
+
default:
|
|
91
|
+
return validateCustom(trimmedValue, rules, defaultErrorMessages);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// ... (keep all the existing validateName, validateEmail, etc. functions from previous solution)
|
|
96
|
+
|
|
97
|
+
// Name validation
|
|
98
|
+
const validateName = (value, rules, defaultErrorMessages) => {
|
|
99
|
+
// Check length constraints
|
|
100
|
+
if (rules?.minLength && value?.length < rules?.minLength) {
|
|
101
|
+
return {
|
|
102
|
+
isValid: false,
|
|
103
|
+
error: rules?.errorMessages?.minLength || defaultErrorMessages.minLength,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (rules?.maxLength && value?.length > rules?.maxLength) {
|
|
108
|
+
return {
|
|
109
|
+
isValid: false,
|
|
110
|
+
error: rules?.errorMessages?.maxLength || defaultErrorMessages.maxLength,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Check against custom regex if provided
|
|
115
|
+
if (rules?.regex && !new RegExp(rules?.regex).test(value)) {
|
|
116
|
+
return {
|
|
117
|
+
isValid: false,
|
|
118
|
+
error: rules?.errorMessages?.invalid || defaultErrorMessages.invalid,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Default name validation (only letters, spaces, and basic punctuation)
|
|
123
|
+
const nameRegex = /^[a-zA-ZÀ-ÿ\s'-.]*$/;
|
|
124
|
+
if (!nameRegex.test(value)) {
|
|
125
|
+
return {
|
|
126
|
+
isValid: false,
|
|
127
|
+
error:
|
|
128
|
+
rules?.errorMessages?.invalid || "Name contains invalid characters",
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return { isValid: true, error: "" };
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Email validation
|
|
136
|
+
const validateEmail = (value, rules, defaultErrorMessages) => {
|
|
137
|
+
// Check length constraints
|
|
138
|
+
if (rules?.minLength && value.length < rules?.minLength) {
|
|
139
|
+
return {
|
|
140
|
+
isValid: false,
|
|
141
|
+
error: rules?.errorMessages?.minLength || defaultErrorMessages.minLength,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (rules?.maxLength && value.length > rules?.maxLength) {
|
|
146
|
+
return {
|
|
147
|
+
isValid: false,
|
|
148
|
+
error: rules?.errorMessages?.maxLength || defaultErrorMessages.maxLength,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Check against custom regex if provided
|
|
153
|
+
if (rules?.regex && !new RegExp(rules?.regex).test(value)) {
|
|
154
|
+
return {
|
|
155
|
+
isValid: false,
|
|
156
|
+
error: rules?.errorMessages?.invalid || defaultErrorMessages.invalid,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Default email regex
|
|
161
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
162
|
+
if (!emailRegex.test(value)) {
|
|
163
|
+
return {
|
|
164
|
+
isValid: false,
|
|
165
|
+
error:
|
|
166
|
+
rules?.errorMessages?.invalid || "Please enter a valid email address",
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return { isValid: true, error: "" };
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Mobile validation
|
|
174
|
+
const validateMobile = (value, rules, defaultErrorMessages) => {
|
|
175
|
+
// Check length constraints
|
|
176
|
+
if (rules?.minLength && value.length < rules?.minLength) {
|
|
177
|
+
return {
|
|
178
|
+
isValid: false,
|
|
179
|
+
error: rules?.errorMessages?.minLength || defaultErrorMessages.minLength,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (rules?.maxLength && value.length > rules?.maxLength) {
|
|
184
|
+
return {
|
|
185
|
+
isValid: false,
|
|
186
|
+
error: rules?.errorMessages?.maxLength || defaultErrorMessages.maxLength,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Check against custom regex if provided
|
|
191
|
+
if (rules?.regex && !new RegExp(rules?.regex).test(value)) {
|
|
192
|
+
return {
|
|
193
|
+
isValid: false,
|
|
194
|
+
error: rules?.errorMessages?.invalid || defaultErrorMessages.invalid,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Default mobile regex (accepts numbers, +, -, and spaces)
|
|
199
|
+
const mobileRegex = /^[\d\s+\-()]*$/;
|
|
200
|
+
if (!mobileRegex.test(value)) {
|
|
201
|
+
return {
|
|
202
|
+
isValid: false,
|
|
203
|
+
error:
|
|
204
|
+
rules?.errorMessages?.invalid || "Please enter a valid mobile number",
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return { isValid: true, error: "" };
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// Address validation
|
|
212
|
+
const validateAddress = (value, rules, defaultErrorMessages) => {
|
|
213
|
+
// Check length constraints
|
|
214
|
+
if (rules?.minLength && value.length < rules?.minLength) {
|
|
215
|
+
return {
|
|
216
|
+
isValid: false,
|
|
217
|
+
error: rules?.errorMessages?.minLength || defaultErrorMessages.minLength,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (rules?.maxLength && value.length > rules?.maxLength) {
|
|
222
|
+
return {
|
|
223
|
+
isValid: false,
|
|
224
|
+
error: rules?.errorMessages?.maxLength || defaultErrorMessages.maxLength,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Check against custom regex if provided
|
|
229
|
+
if (rules?.regex && !new RegExp(rules?.regex).test(value)) {
|
|
230
|
+
return {
|
|
231
|
+
isValid: false,
|
|
232
|
+
error: rules?.errorMessages?.invalid || defaultErrorMessages.invalid,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return { isValid: true, error: "" };
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Add password validation
|
|
240
|
+
const validatePassword = (value, rules, defaultErrorMessages) => {
|
|
241
|
+
// Check length constraints
|
|
242
|
+
if (rules?.minLength && value.length < rules?.minLength) {
|
|
243
|
+
return {
|
|
244
|
+
isValid: false,
|
|
245
|
+
error: rules?.errorMessages?.minLength || defaultErrorMessages.minLength,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (rules?.maxLength && value.length > rules?.maxLength) {
|
|
250
|
+
return {
|
|
251
|
+
isValid: false,
|
|
252
|
+
error: rules?.errorMessages?.maxLength || defaultErrorMessages.maxLength,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Check against custom regex if provided
|
|
257
|
+
if (rules?.regex && !new RegExp(rules?.regex).test(value)) {
|
|
258
|
+
return {
|
|
259
|
+
isValid: false,
|
|
260
|
+
error: rules?.errorMessages?.invalid || defaultErrorMessages.invalid,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Default password validation (at least one letter, one number)
|
|
265
|
+
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d).+$/;
|
|
266
|
+
if (!passwordRegex.test(value)) {
|
|
267
|
+
return {
|
|
268
|
+
isValid: false,
|
|
269
|
+
error:
|
|
270
|
+
rules?.errorMessages?.invalid ||
|
|
271
|
+
"Password must contain at least one letter and one number",
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return { isValid: true, error: "" };
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// Custom validation
|
|
279
|
+
const validateCustom = (value, rules, defaultErrorMessages) => {
|
|
280
|
+
// Check length constraints if value is a string
|
|
281
|
+
if (typeof value === "string") {
|
|
282
|
+
if (rules?.minLength && value.length < rules?.minLength) {
|
|
283
|
+
return {
|
|
284
|
+
isValid: false,
|
|
285
|
+
error:
|
|
286
|
+
rules?.errorMessages?.minLength || defaultErrorMessages.minLength,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (rules?.maxLength && value.length > rules?.maxLength) {
|
|
291
|
+
return {
|
|
292
|
+
isValid: false,
|
|
293
|
+
error:
|
|
294
|
+
rules?.errorMessages?.maxLength || defaultErrorMessages.maxLength,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
module.exports = dynamicValidator;
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "quantique-field-validator",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Validator to verify all form fields.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/saketsinhaquantique/quantique-field-validator.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"QFV"
|
|
15
|
+
],
|
|
16
|
+
"author": "Saket Brij Sinha <saket.sinha@quantique.ai>",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/saketsinhaquantique/quantique-field-validator/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/saketsinhaquantique/quantique-field-validator#readme"
|
|
22
|
+
}
|