@sebgroup/frontend-tools
Version:
A set of frontend tools
246 lines (243 loc) • 9.84 kB
JavaScript
import { isEmpty } from '../isEmpty/isEmpty.js';
import { isPhoneNumber } from '../isPhoneNumber/isPhoneNumber.js';
import { isEmail } from '../isEmail/isEmail.js';
import { deepCopy } from '../deepCopy/deepCopy.js';
import { isStrongPassword } from '../isStrongPassword/isStrongPassword.js';
import { isValidDate } from '../isValidDate/isValidDate.js';
import { isDateBefore } from '../isDateBefore/isDateBefore.js';
import { isDateAfter } from '../isDateAfter/isDateAfter.js';
class ValidatorModelItem {
constructor(name, value) {
this.value = null;
this.specs = {};
this.validations = [];
this.name = name;
this.value = value;
this.specs = {};
this.validations = [];
}
}
class FormValidator {
constructor(formObject) {
this.formObject = new Map();
this.formObjectErrors = {};
this.customValidators = [];
if (!isEmpty(formObject) && typeof formObject === "object") {
const clone = deepCopy(formObject);
this.originalFormObject = clone;
for (const field in clone) {
this.formObject.set(field, new ValidatorModelItem(field, clone[field]));
}
}
}
addValidation(fields, type, specs) {
if (fields &&
fields instanceof Array &&
type &&
typeof type === "string" &&
this.isValidType(type)) {
if (fields.length) {
fields.map((field) => {
if (this.formObject.has(field)) {
this.formObject.get(field).validations.push(type);
if (!isEmpty(specs)) {
this.formObject.get(field).specs = Object.assign(Object.assign({}, this.formObject.get(field).specs), specs);
}
}
});
}
else {
this.formObject.forEach((item) => {
item.validations.push(type);
if (!isEmpty(specs)) {
item.specs = Object.assign(Object.assign({}, item.specs), specs);
}
});
}
}
return this;
}
/**
* Add a custom validator that returns an error message if found
* @param {Array<string>} errorFields The fields where the error is reported to
* @param {function} validator The validator method
* @returns {FormValidator} The form validator object
* @example addValidator(["balance", "payment"], ["payment"], (balance: number, payment: number) => { return payment > balance ? "The payment exceeds your balance" : null; });
*/
addCustomValidation(errorFields, validator) {
if (errorFields &&
errorFields instanceof Array &&
errorFields.length &&
validator &&
validator instanceof Function) {
this.customValidators.push({ errorFields, validator });
}
return this;
}
/**
* Get the error found in the form object. Has to be called after `validate` method has been called.
* @returns {any} The form object object populated by validation errors, if found any. Otherwise, it's an empty object.
*/
getErrors() {
return this.formObjectErrors;
}
/**
* Get a specific error found during validation, if any. Has to be called after `validate` method has been called.
* @returns {any} The error of the specific item in the form, if any.
*/
getError(name) {
return this.formObjectErrors[name];
}
/**
* Validates the form object passed in the constructor
* @returns {FormValidator} The form validator object
*/
validate() {
this.formObject.forEach((item) => {
if (item.validations.length) {
let fieldError;
let i = 0;
do {
fieldError = this.validateField(item.value, item.validations[i], item.specs);
if (!isEmpty(fieldError)) {
this.formObjectErrors[item.name] = fieldError;
}
i++;
} while (i < item.validations.length && !fieldError);
}
});
if (this.customValidators.length) {
this.customValidators.map((customValidator) => {
const customValidatorError = customValidator.validator(this.originalFormObject);
customValidator.errorFields.map((field) => {
if (this.formObject.has(field) &&
!this.getError(field) &&
customValidatorError) {
this.formObjectErrors[field] = customValidatorError;
}
});
});
}
return this;
}
/**
* Validate a parameter in the form formObject based on predefined set of criteria
* @param {ValidatorModelItem} fieldObject The field object stored in the local formObject
* @returns {string} The error found in the parameter
*/
validateField(value, type, specs) {
let fieldError = null;
// Don't validate an empty field if it's not required
const date = new Date(value);
const empty = isEmpty(value);
if (empty && type !== "required") {
return null;
}
const valid = isValidDate(date);
switch (type) {
case "required":
return empty ? { errorCode: "empty" } : null;
case "isDate":
return valid ? null : { errorCode: "invalidDate" };
case "dateRange":
if (valid) {
if (specs.minDate) {
fieldError = isDateBefore(date, specs.minDate)
? {
errorCode: "beforeMinDate",
specs: { minDate: specs.minDate },
}
: null;
}
if (!fieldError && specs.maxDate) {
fieldError = isDateAfter(date, specs.maxDate)
? {
errorCode: "afterMaxDate",
specs: { maxDate: specs.maxDate },
}
: null;
}
return fieldError;
}
else {
return null;
}
case "textLength":
if (typeof value === "string") {
if (specs.minLength) {
fieldError =
value.length < specs.minLength
? {
errorCode: "lessThanMinLength",
specs: { minLength: specs.minLength },
}
: null;
}
if (!fieldError && specs.maxLength) {
fieldError =
value.length > specs.maxLength
? {
errorCode: "moreThanMaxLength",
specs: { maxLength: specs.maxLength },
}
: null;
}
return fieldError;
}
else {
return null;
}
case "valueRange":
if (typeof value === "number") {
if (specs.minValue) {
fieldError =
value < specs.minValue
? {
errorCode: "lessThanMinValue",
specs: { minValue: specs.minValue },
}
: null;
}
if (!fieldError && specs.maxValue) {
fieldError =
value > specs.maxValue
? {
errorCode: "moreThanMaxValue",
specs: { maxValue: specs.maxValue },
}
: null;
}
return fieldError;
}
else {
return null;
}
case "validEmail":
return isEmail(value) ? null : { errorCode: "invalidEmail" };
case "strongPassword":
return isStrongPassword(value)
? null
: { errorCode: "weakPassword" };
case "isPhoneNumber":
return isPhoneNumber(value)
? null
: { errorCode: "invalidPhoneNumber" };
}
}
// Helpers
isValidType(type) {
const availableValidationTypes = {
required: true,
isDate: true,
dateRange: true,
textLength: true,
valueRange: true,
validEmail: true,
strongPassword: true,
isPhoneNumber: true,
};
return availableValidationTypes.hasOwnProperty(type);
}
}
export { FormValidator };
//# sourceMappingURL=FormValidator.js.map