@mub22/validity
Version:
Lightweight JavaScript validation library inspired by Laravel's rule syntax. Validate fields and forms easily with built-in rules and error messages.
165 lines (148 loc) • 4.43 kB
JavaScript
;
function required(value) {
return value !== undefined && value !== null && value !== "";
}
const min = (value, arg) => {
return typeof value === "string" && value.length >= parseInt(arg || "0");
};
const max = (value, arg) => {
return typeof value === "string" && value.length <= parseInt(arg || "0");
};
function email(value) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return typeof value === "string" && regex.test(value);
}
function numeric(value) {
const regex = /^-?\d+(\.\d+)?$/;
return typeof value === "string" && regex.test(value);
}
function alpha(value) {
const regex = /^[a-zA-Z]+$/;
return typeof value === "string" && regex.test(value);
}
const rules = {
required,
min,
max,
email,
numeric,
alpha,
};
function capitalize(str) {
if (!str)
return "";
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
}
const confirm = (value, arg, data) => {
let isValidFnWithData = false;
let args = {};
if (data) {
const { __field__ } = data;
const confirmField = `confirm${capitalize(__field__)}`;
if (data[__field__] === data[confirmField]) {
isValidFnWithData = true;
}
else {
args = { arg1: __field__, arg2: `confirm ${__field__}` };
}
}
return { isValidFnWithData, args };
};
const rulesWithData = {
confirm
};
const messages$1 = {
required: "El campo es obligatorio",
min: "Debe tener al menos :arg caracteres",
max: "Debe tener como máximo :arg caracteres",
email: "El campo debe ser un correo válido",
numeric: "El valor debe ser numérico",
alpha: "Solo se permiten letras",
};
const messages = {
/* Rules */
required: "This field is required",
min: "Must be at least :arg characters long",
max: "Must be at most :arg characters long",
email: "This field must be a valid email address",
numeric: "The value must be numeric",
alpha: "Only letters are allowed",
/* rules with data */
confirm: "The :arg1 field must match the :arg2 field",
};
const locales = {
es: messages$1,
en: messages,
};
const defaultLocale = locales.en;
function validate(value, ruleString, data) {
const ruleList = ruleString.split("|");
const errors = [];
for (const rule of ruleList) {
/* Rules */
const [ruleName, arg] = rule.split(":");
const fn = rules[ruleName];
const fnWithData = rulesWithData[ruleName];
/* Validations */
if (!fn && !fnWithData)
continue;
/* Response */
if (fn) {
let isValidFn = fn(value, arg);
if (!isValidFn) {
const template = defaultLocale[ruleName] || "Validation failed";
const message = template.replace(":arg", arg || "");
errors.push(message);
}
}
else if (fnWithData) {
const { isValidFnWithData, args } = fnWithData(value, arg, data);
if (!isValidFnWithData) {
const template = defaultLocale[ruleName] || "Validation failed";
let message = template;
for (const [key, value] of Object.entries(args || {})) {
message = message.replace(`:${key}`, value);
}
errors.push(message);
}
}
}
return {
valid: errors.length === 0,
errors,
};
}
function validateForm(data, rules) {
let isFormValid = true;
const errors = {};
for (const field in rules) {
const value = data[field];
/* Validations */
/* Skip internal fields */
if (/^__/.test(field))
continue;
const ruleList = rules[field].split("|");
if (!ruleList.length)
continue;
let result;
if (ruleList.some(rule => rule in rulesWithData)) {
data.__field__ = field;
result = validate(value, rules[field], data);
}
else {
result = validate(value, rules[field]);
}
if (!result.valid) {
errors[field] = result.errors;
isFormValid = false;
}
}
return {
valid: isFormValid,
errors
};
}
exports.locales = locales;
exports.rules = rules;
exports.validate = validate;
exports.validateForm = validateForm;