Joi - A Powerful Data Validator for JavaScript

Joi is the most powerful schema description language and data validator for JavaScript. Joi helps to describe the schema and checks whether given input data is valid or not. In any user interactive applications, user will input the data and it has to be validated according to the schema before it gets inserted in to the database.
Joi makes life easier, It helps to define the schema in readable language In this article, we will explore how to validate Strings, Password, Date, Email.
Dependency
npm install joi
OR
Add below dependency to package.json
"dependencies": {
"joi" : "^17.13.1"
}
Input validation
If we want to accept username with below rules.
Username should be
- Alpha numeric string
- Minimum of 3 characters
- Maximum of 30 characters
- Mandatory field
Below is the schema definition from Joi. The statement is self explanatory.
Joi.string()
.alphanum()
.min(3)
.max(30)
.required()
.error(new Error('username is required'))
Test the statement with different input.
function test_username() {
const schema = Joi.object({
username: Joi.string()
.alphanum()
.min(3)
.max(30)
.required()
.error(new Error('username is required'))
});
let input = { username: 'ab'}
let result = schema.validate(input);
console.log('input-1');
console.log(result);
input = { username: 'abcd34'}
result = schema.validate(input);
console.log('input-2');
console.log(result);
}
The result of validate
function will be value
and error
. value
will be the input object and error
is an err object.
input-1
{
value: { username: 'ab' },
error: Error: username is required
at test_username (file:///blackslate-samples/nodejs/joi/index.js:62:20)
at file:///blackslate-samples/nodejs/joi/index.js:128:1
at ModuleJob.run (node:internal/modules/esm/module_job:222:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:123:5)
}
input-2
{ value: { username: 'abcd34' } }
Password Validation
This is the most important and much needed in all front end applications.
Passwords has to be strong and it should contain
- Atleast one capital letter
- Atleast one small letter
- Atleast one digit
- Atleast one special character
- Minimum of 8 characters
function test_password() {
const schema = Joi.object({
password: Joi.string()
.min(8)
.regex(/[A-Z]/, 'upper-case')
.regex(/[a-z]/, 'lower-case')
.regex(/[^\w]/, 'special character')
.regex(/[0-9]/, "number")
});
let input = { password: 'test'}
let result = schema.validate(input);
console.log(result);
input = { password: 'Test124#'}
result = schema.validate(input);
console.log(result);
}
Email Validation
Validate email whether it is in correct format or not.
function test_email() {
const schema = Joi.object({
email: Joi.string().email()
});
let input = { email: 'test'}
let result = schema.validate(input);
console.log(result);
input = { email: 'test@example.com'}
result = schema.validate(input);
console.log(result);
}
Date Validation
We want to validate date, whether the input date is valid and end date is greater than the start date.
function test_date() {
const schema = Joi.object({
startDate: Joi.date().required(),
endDate: Joi.date().greater(Joi.ref('startDate')).required()
});
let input = { startDate: '2024-01-01', endDate: '2024-02-01'}
let result = schema.validate(input);
console.log(result);
}
Joi.date()
represents date object
Joi.ref()
refers to the input value available in the schema.
Putting it all together
Let's define a schema which has username, email, date, password, repeatPassword and access token.
- username should be minimum of 3 and maximum of 30 characters
- password should contain atleast one uppercase, one lowercase, one digit and one special character
- access token should contain only strings and digits
- password and repeatPassword should be same
- password or access token, either or is mandatory.
- start date should be greater than end date.
async function test() {
const schema = Joi.object({
username: Joi.string()
.alphanum()
.min(3)
.max(30)
.required(),
password: Joi.string()
.min(8)
.regex(/[A-Z]/, 'upper-case')
.regex(/[a-z]/, 'lower-case')
.regex(/[^\w]/, 'special character')
.regex(/[0-9]/, "number"),
repeatPassword: Joi.ref('password'),
accessToken: [
Joi.string(),
Joi.number()
],
email: Joi.string().email(),
startDate: Joi.date().required(),
endDate: Joi.date().greater(Joi.ref('startDate')).required()
})
.xor('password', 'accessToken');
let result = schema.validate({ username: 'abc', password: 1994 });
console.log(result); //error
let input = {
username: 'Kishore',
email: 'raj@gmail.com',
startDate: '2024-01-01',
endDate: '2024-02-01',
password: 'Test124#$',
repeatPassword: 'Test124#$'
}
result = schema.validate(input);
console.log(result); //success
input = {
username: 'Kishore',
email: 'raj@gmail.com',
startDate: '2024-01-01',
endDate: '2024-02-01',
accessToken: '1AS4486B2459F06401R8420A470B5FAD38F'
}
result = schema.validate(input);
console.log(result);
//const result = await schema.validateAsync()
}
Joi.xor()
is used to consider either of the input is mandatory.
schema.validate()
is a synchronous function and schema.validateAsync()
is used for asynchronous function.
Conclusion
Joi is a powerful, schema definition language to validate input in JavaScript.