basic-data-validator v1.0.5
Basic-Data-Validator
Basic-Data-Validator is a JavaScript library for data validation. At first it was built to be used in React-Final-Form, but it is not limited to React and you can use it in every javascript project.
Basic-Data-Validator contains some general Api to create your own validation schema.
If you want more, you can easily define your custom rule.
For Persian users it fully supports Shamsi (Jalaali) date.
Also you can customize all messages or overwrite your message in every rule.
CONTENT
INSTALL
Install via npm:
npm install basic-data-validatorBasic-Data-Validator supports Jalaali date validation that uses Basic-Shamsi package.
npm install basic-shamsiUSAGE
Import BasicValidator class from the Basic-Data-Validator package.
BasicValidator accepts an schema (or schema generator) as input argument and validate values.
Define schema
Lets start with an example:
import BasicValidator from "basic-data-validator";
const myValidator = BasicValidator((builder) =>
builder.object({
userName: builder.label("First Name").string().required().userName(),
password: builder.string().required().password(),
confirmPassword: builder
.string()
.required()
.equals((data) => data.password, "must be equal to password"),
address: builder
.object({
city: builder.label("CITY").string().required(),
postalCode: builder
.label("POSTAL CODE")
.string()
.required()
.digits(),
})
.required(),
})
);The above schema defines the following constraints:
userName- a required string
- a valid username: may contains any symboles of _ – . \ / @ or digits or letters, having a length of 3 to 20 characters
password- a required string
- requires a password rule: must not contains space and ' symbol, having a length of 3 to 20 characters
confirmPassword- a required string
- must be equal to value of password field
address- a required object
city- a required string
postalCode- a required string
- just contains digits
Use in Fnal Form
You can easily use myValidator.validate in React-Final-Form .
<Form
onSubmit={onSubmit}
validate={myValidator.validate}
...
/>Using validateAll method enforces all rules to be validated, so you can show all input errors.
<Form
onSubmit={onSubmit}
validate={myValidator.validateAll}
...
/>Use in code
Also you can use myValidator in your code:
const data = { userName: "Mahdi", password: null, confirmPassword: "*" };
const is_valid = myValidator.isValid(data); // false
const errors = myValidator.validate(data);
/*
output:
{
userName: null,
password: 'password is a required field',
confirmPassword: 'must be equal to password',
address: {
city: 'CITY is a required field',
postalCode: 'POSTAL CODE is a required field'
}
}
*/Next section will explains more about BasicValidator
BasicValidator
BasicValidator generates a schema using schema builder.
const myValidator = BasicValidator(SCHEMA, CUSTOM_MESSAGES);
myValidator.isValid(DATA); // returns boolean (true | false)
myValidator.vaidate(DATA); // returns first error for each schema class
myValidator.vaidateAll(DATA); // returns all errorsDefine schema
You can define your own schema using schema builder:
const mySchema = builder => builder.object({
userName: builder.string().required().notContains([" ","'"]),
password: builder.string().required().notContains([" ","'"])
})
const myValidator = BasicValidator( mySchema );
...Validate values
BasicValidator returns a validator object with folowing methods:
isValid(value): Returnstrueif the value matches the schema.validate(value)This method match the value and schema. For each schema class it will stop at first error.validateAll(value)This method match the value and schema. It checks all validation rules and extract all errors in each validation schema.
Schema Builder
Helps you to define validation schema. It contains folowing methods:
label( text )Labels the name of property. Use this method when you are using validator level messages.
(builder) => builder.label("User Name");string( message )Generates an instance of
StringSchemaand also adds a rule that will be matched when value is undefined, null or string.(builder) => builder.stirng("JUST STRING VALUE ALLOWED");inSensitive()All string rules are case sensitive. Using this method right before string() method, makes them case in-sensitive.
(builder) => builder.inSensitive().stirng();number( message )Generates an instance of
NumberSchemaand also adds a rule that will be matched when value is undefined, null or number.(builder) => builder.number();bool( message )Generates an instance of
BooleanSchemaand also adds a rule that will be matched when value is undefined, null or boolean.(builder) => builder.bool();shamsi( message )Generates an instance of
ShamsiSchemaand also adds a rule that will be matched when value is undefined, null or valid Shamsi (Jalaali) date.(builder) => builder.shamsi();object( DEFINED-SCHEMA-OBJECT)Generates an instance of
ObjectSchemaand also adds a rule that will be matched when value is undefined, null or object.(builder) => builder.object({});
API
There are 5 classes of schema StringSchema, NumberSchema, BooleanSchema, ShamsiSchema and ObjectSchema
StringSchema
This schema class contains folowing methods:
custom(fn, message)Allows you to write your custom match function to validate a string. This function takes 2 argument: the value (current evaluation value) and the data (current evaluation object)
var schema = builder => builder.string() .custom((value, data) => value > data.startDate, "CUSTOM ERROR MESSAGE"));Default vaildation error: DefaultMessages.Invalidrequired(message)Will not allow undefined or null as value.
var schema = (builder) => builder.string().required();Default vaildation error: DefaultMessages.Requiredequals(value, message)Just the specified value is allwed.
var schema = (builder) => builder.string().equals("Mahdi");Late binding: The
valueargument can be a function, so it will be calculated each time it is accessed.var schema = builder => builder.object({ ... confirmPassword: builder.string() .equals(data => data.password) ... });Default validation error: DefaultMessages.EqualsnotEquals(value, message)The specified value is not allwed.
var schema = (builder) => builder.string().notEquals("Mahdi");Late binding: The
valueargument can be a function, so it will be calculated each time it is accessed.var schema = builder => builder.object({ ... lastName: builder.string() .notEquals(data => data.firstName) ... });Default validation error: DefaultMessages.NotEqualsemail(message)Requires the string value to be a valid email address.
var schema = (builder) => builder.string().email();Default validation error: DefaultMessages.Emailurl(message)Requires the string value to be a valid url address.
var schema = (builder) => builder.string().url();Default validation error: DefaultMessages.Urlmatch(regex, message)Requires the
regexpattern to match the string value.var schema = (builder) => builder.string().match(/^[0-9]+$/);Late binding: The
regexargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.string() .equals((data) => (data.typeId == 1 ? /^[0-9]+$/ : /^[a-zA-Z]+$/));Default validation error: DefaultMessages.MatchesuserName(message)Requires the string value to be a valid user name (Contains any symboles of _ – . \ / @ or digits or letters, having a length of 3 to 20 characters)
var schema = (builder) => builder.string().userName();Default validation error: DefaultMessages.UserNamestrongPassword(message)Requires the string value to be a strong password that has at least one lowercase letter, one uppercase letter, one digit, one special character, and is at least 8 characters long.
var schema = (builder) => builder.string().strongPassword();Default validation error: DefaultMessages.StrongPasswordmediumPassword(message)Requires the string value to be a medium password that has at least one lowercase letter, one uppercase letter, one digit, one special character, and is at least 6 characters long.
var schema = (builder) => builder.string().mediumPassword();Default validation error: DefaultMessages.MediumPasswordpassword(message)Requires the string value to be a valid password that has at 3 and characters and not contains space and ' (single quotation)
var schema = (builder) => builder.string().password();This is a shortcut for
.notContains([" ", "'"]).min(3).max(20).digits(message)Requires the string value to only contain 0-9.
var schema = (builder) => builder.string().digits();Default validation error: DefaultMessages.Digitsletters(message)Requires the string value to only contain a-z or A-Z.
var schema = (builder) => builder.string().letters();Default validation error: DefaultMessages.Lettersalphanum(message)Requires the string value to only contain a-z, A-Z or 0-9.
var schema = (builder) => builder.string().alphanum();Default validation error: DefaultMessages.AlphaNummin(min, message)Specifies the minimum length limit for the string value.
var schema = (builder) => builder.string().min(3);Late binding: The
minargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.string().min((data) => (data.typeId == 1 ? 3 : 10));Default validation error: DefaultMessages.MinLenmax(max, message)Specifies the maximum length limit for the string value.
var schema = (builder) => builder.string().max(3);Late binding: The
maxargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.string().max((data) => (data.typeId == 1 ? 3 : 10));Default validation error: DefaultMessages.MaxLenlength(length, message)Specifies the length limit for the string value.
var schema = (builder) => builder.string().length(3);Late binding: The
lengthargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.string().length((data) => (data.typeId == 1 ? 3 : 10));Default validation error: DefaultMessages.Lengthtrim(message)Requires the string value to be trimmed.
var schema = (builder) => builder.string().trim();Default validation error: DefaultMessages.TrimlowerCase(lowerCase, message)Requires the string value to be lowercase.
var schema = (builder) => builder.string().lowerCase();Default validation error: DefaultMessages.LowerCaseupperCase(upperCase, message)Requires the string value to be uppercase.
var schema = (builder) => builder.string().upperCase();Default validation error: DefaultMessages.UpperCasecontains(values, message)Requires the string value at least contains one of
values.var schema = (builder) => builder.string().contains(["US", "UK"]);Late binding: The
valuesargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.string() .contains((data) => data.typeId == 1 ? ["US", "UK"] : ["RUSSIA", "CHINA"]);Also the items of
valuescan be a function.var schema = builder => builder.string() .contains(['US', 'UK', data => data.typeId == 1? 'RUSSIA', 'CHINA']);Default validation error: DefaultMessages.ContainsnotContains(values, message)Requires the string value does not contain any of
values.var schema = (builder) => builder.string().notContains(["RUSSIA", "CHINA"]);Late binding: The
valuesargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.string() .notContains((data) => data.typeId == 1 ? ["US", "UK"] : ["RUSSIA", "CHINA"]);Also the items of
valuescan be a function.var schema = builder => builder.string() .notContains(['US', 'UK', data => data.typeId == 1? 'RUSSIA', 'CHINA']);Default validation error: DefaultMessages.NotContainsoneOf(values, message)Requires the string value to be one of
values.var schema = (builder) => builder.string().oneOf(["RUSSIA", "CHINA"]);Late binding: The
valuesargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.string() .oneOf((data) => data.typeId == 1 ? ["US", "UK"] : ["RUSSIA", "CHINA"]);Also the items of
valuescan be a function.var schema = builder => builder.string() .oneOf(['US', 'UK', data => data.typeId == 1? 'RUSSIA', 'CHINA']);Default validation error: DefaultMessages.OneOf
notOneOf(values, message)Requires the string value not to be one of
values.var schema = (builder) => builder.string().notOneOf(["RUSSIA", "CHINA"]);Late binding: The
valuesargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.string() .notOneOf((data) => data.typeId == 1 ? ["US", "UK"] : ["RUSSIA", "CHINA"]);Also the items of
valuescan be a function.var schema = builder => builder.string() .notOneOf(['US', 'UK', data => data.typeId == 1? 'RUSSIA', 'CHINA']);Default validation error: DefaultMessages.NotOneOf
NumberSchema
This class contains folowing methods:
custom(fn, message)Refer to
string.custom()required(message)Refer to
string.required()equals(value, message)Refer to
string.equals()notEquals(value, message)Refer to
string.notEquals()integer(message)Requires the value to be an integer or null or undefined
var schema = (builder) => builder.number().integer();Default validation error: DefaultMessages.Integermin(min, message)Set the minimum value allowed.
var schema = (builder) => builder.number().min(5);Late binding: The
minargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.number().min((data) => (data.typeId == 1 ? 5 : 10));Default validation error: DefaultMessages.Minmax(max, message)Set the maximum value allowed.
var schema = (builder) => builder.number().max(15);Late binding: The
maxargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.number().max((data) => (data.typeId == 1 ? 15 : 10));Default validation error: DefaultMessages.MaxlessThan(max, message)Value must be less than
max.var schema = (builder) => builder.number().lessThan(15);Late binding: The
maxargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.number().lessThan((data) => (data.typeId == 1 ? 15 : 10));Default validation error: DefaultMessages.LessThanmoreThan(min, message)Value must be more than
min.var schema = (builder) => builder.number().moreThan(5);Late binding: The
minargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.number().moreThan((data) => (data.typeId == 1 ? 5 : 10));Default validation error: DefaultMessages.MoreThanpositive(message)Value must be positive number.
var schema = (builder) => builder.number().positive();Default validation error: DefaultMessages.Positivenegative(message)Value must be negative number.
var schema = (builder) => builder.number().negative();Default validation error: DefaultMessages.NegativeoneOf(values, message)Refer to
string.oneOf()notOneOf(values, message)Refer to
string.notOneOf()
BooleanSchema
This class contains folowing methods:
custom(fn, message)Refer to
string.custom()required(message)Refer to
string.required()equals(value, message)Refer to
string.equals()notEquals(value, message)Refer to
string.notEquals()
ShamsiSchema
This class contains folowing methods:
custom(fn, message)Refer to
string.custom()required(message)Refer to
string.required()equals(value, message)Refer to
string.equals()notEquals(value, message)Refer to
string.notEquals()min(min, message)Set the minimum Shamsi date allowed.
var schema = (builder) => builder.number().min("1400/01/01");Late binding: The
minargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder.string() .min((data) => (data.typeId == 1 ? "1400/01/01" : "1400/07/01"));Default validation error: DefaultMessages.MinShamsimax(max, message)Set the maximum Shamsi date allowed.
var schema = (builder) => builder.number().max("1400/01/01");Late binding: The
maxargument can be a function, so it will be calculated each time it is accessed.var schema = (builder) => builder .string() .max((data) => (data.typeId == 1 ? "1400/01/01" : "1400/07/01"));Default validation error: DefaultMessages.MaxShamsi
ObjectSchema
This class contains folowing methods:
Refer torequired(message)string.required()
Custom Messages
In BasicValidator you can custimize error messages in 2 ways.
Rule Level
In each rule you can optinally define your error message.
var schema = (builder) =>
builder
.number("VALUE MUST BE A NUMBER")
.required("CAN NOT BE EMPTY")
.max(10, "VALUE <= 10");Validator Level
Also you can customize all or some of messages in each validator.
You can find list of all messages in the file basic-data-validator/lib/messages.js. like this:
export const DefaultMessages = {
Invalid: "{path} is invalid",
Required: "{path} is a required field",
Equals: "{path} field must be equal to {value}",
NotEquals: "{path} field must be not equal to {value}",
String: "{path} must be a string",
Email: "{path} must be a valid email",
Url: "{path} must be a valid URL",
Matches: '{path} must match the following: "{regex}"',
UserName: "{path} is not a valid user name",
StrongPassword: "{path} is not a strong password",
MediumPassword: "{path} is not a medium password",
Digits: '{path} must contains only numbers"',
Letters: '{path} must contains only letters"',
AlphaNum: '{path} must contains letters or numbers"',
MinLen: "{path} must be at least {min} characters",
MaxLen: "{path} must be at most {max} characters",
Length: "{path} must be exactly {length} characters",
Trim: "{path} must be a trimmed string",
LowerCase: "{path} must be a lowercase string",
UpperCase: "{path} must be a upper case string",
Contains: "{path} must contains one of the following values: {values}",
NotContains:
"{path} must not contains one of the following values: {values}",
OneOf: "{path} must be one of the following values: {values}",
NotOneOf: "{path} must not be one of the following values: {values}",
Number: "{path} must be a number",
Integer: "{path} must be an integer",
Min: "{path} must be greater than or equal to {min}",
Max: "{path} must be less than or equal to {max}",
LessThan: "{path} must be less than {less}",
MoreThan: "{path} must be greater than {more}",
Positive: "{path} must be a positive number",
Negative: "{path} must be a negative number",
Boolean: "{path} field must be boolean",
Shamsi: "{path} field must be Shamsi date",
MinShamsi: "{path} field must be later than {min}",
MaxShamsi: "{path} field must be at earlier than {max}",
};Define your new messages and pass it as second argument in basic-data-validator
const MyValidatorMessages = {
Required: "CAN NOT BE EMPTY",
Number: "VALUE MUST BE A NUMBER",
Max: "VALUE <= {max}",
};
var mySchemaBuilder = (builder) => builder.number().required().max(10, "10");
const myValidator = BasicValidator(mySchemaBuilder, MyValidatorMessages);Basic-Data-Validator will use default message if you miss to overwrite it.
EXAMPLES
Example 1: validate simple value
const validator = BasicValidator((b) => b.string().strongPassword());
validator.isValid("do,p!#32Z?"); // true
validator.validate("do,p!#32Z?"); // null
validator.isValid("123"); // false
validator.validate("123"); // ? is not a strong passwordExample 2: password must not contains user name
const validator = BasicValidator(b => b.object({
...
userName: b.string().required(),
password: b.inSensitive().string().required(),
.notContains(d => d.userName, 'password must not contains user name'),
...
}));Example 3: confirm password must be equal to password
const validator = BasicValidator(b => b.object({
...
password: b.string().required(),
confirmPassword: b.string().required()
.equals(d => d.password, 'must be equal to password'),
...
}));Example 4: End date must be earlier than start date
const validator = BasicValidator(b => b.object({
...
startDate: b.shamsi().required(),
endDate: b.shamsi().required()
.moreThan(d => d.startDate, 'End date must be earlier than start date'),
...
}));