Reputation: 1699
I have Joi schema and want to add a custom validator for validating data which isn't possible with default Joi validators.
Currently, I'm using the version 16.1.7 of Joi
const method = (value, helpers) => {
// for example if the username value is (something) then it will throw an
// error with the following message but it throws an error inside (value)
// object without error message. It should throw error inside the (error)
// object with a proper error message
if (value === "something") {
return new Error("something is not allowed as username");
}
return value; // Return the value unchanged
};
const createProfileSchema = Joi.object().keys({
username: Joi.string()
.required()
.trim()
.empty()
.min(5)
.max(20)
.lowercase()
.custom(method, "custom validation")
});
const { error, value } = createProfileSchema.validate({
username: "something"
});
console.log(value); // returns {username: Error}
console.log(error); // returns undefined
But I couldn't implement it the right way. I read Joi documents but it seems a little bit confusing to me. Can anyone help me to figure it out?
Upvotes: 33
Views: 59600
Reputation: 29
recently faced the same isuue, hope this helps.
//joi object schema
password: Joi.custom(validatePassword, "validate password").required(),
// custom validator with custom message
// custom.validation.ts
import { CustomHelpers } from "joi";
const validatePassword = (value: string, helpers: CustomHelpers) => {
if (value.length < 6) {
return helpers.message({
custom: "Password must have at least 6 characters.",
});
}
if (!value.match(/\d/) || !value.match(/[a-zA-Z]/)) {
return helpers.message({
custom: "Password must contain at least 1 letter and 1 number.",
});
}
return value;
};
export { validatePassword };
Upvotes: 1
Reputation: 1121
const Joi = require('@hapi/joi');
Joi.object({
password: Joi
.string()
.custom((value, helper) => {
if (value.length < 8) {
return helper.message("Password must be at least 8 characters long");
}
return true;
})
}).validate({
password: '1234'
});
Upvotes: 44
Reputation: 17858
Your custom method must be like this:
const method = (value, helpers) => {
// for example if the username value is (something) then it will throw an
// error with the following message but it throws an error inside (value)
// object without error message. It should throw error inside the (error)
// object with a proper error message
if (value === "something") {
return helpers.error("any.invalid");
}
return value; // Return the value unchanged
};
Docs:
https://github.com/hapijs/joi/blob/master/API.md#anycustommethod-description
Output for value :
{ username: 'something' }
Output for error:
[Error [ValidationError]: "username" contains an invalid value] {
_original: { username: 'something' },
details: [
{
message: '"username" contains an invalid value',
path: [Array],
type: 'any.invalid',
context: [Object]
}
]
}
Upvotes: 37
Reputation: 37
This is how I validated my code, have a look at it and try to format yours
const busInput = (req) => {
const schema = Joi.object().keys({
routId: Joi.number().integer().required().min(1)
.max(150),
bus_plate: Joi.string().required().min(5),
currentLocation: Joi.string().required().custom((value, helper) => {
const coordinates = req.body.currentLocation.split(',');
const lat = coordinates[0].trim();
const long = coordinates[1].trim();
const valRegex = /-?\d/;
if (!valRegex.test(lat)) {
return helper.message('Laltitude must be numbers');
}
if (!valRegex.test(long)) {
return helper.message('Longitude must be numbers');
}
}),
bus_status: Joi.string().required().valid('active', 'inactive'),
});
return schema.validate(req.body);
};
Upvotes: 2