Контекст валидации в Joi представляет собой набор данных и
параметров, которые сопровождают процесс проверки значений и влияют на
поведение схем, правил, сообщений об ошибках и динамических условий. Он
формируется в момент вызова validate и распространяется на
все уровни схемы, включая вложенные структуры, кастомные валидаторы и
вычисляемые правила.
При выполнении валидации Joi оперирует не только проверяемым значением и схемой, но и дополнительными данными, которые можно рассматривать как «окружение» проверки. Это окружение включает:
Контекст формируется на уровне вызова:
schema.validate(value, options)
или
Joi.validate(value, schema, options)
Именно объект options становится основным источником
управляющего контекста.
Наиболее важные элементы контекста задаются через параметры:
Последний параметр имеет особое значение, так как именно он расширяет контекст произвольными данными.
Пользовательский контекст позволяет передавать внешние данные в процесс валидации. Эти данные не участвуют напрямую в проверке значения, но могут использоваться:
.when();.custom();Пример передачи контекста:
schema.validate(data, {
context: {
role: 'admin',
minAge: 18
}
})
.when()Одним из ключевых механизмов, использующих контекст, являются условные правила.
const schema = Joi.object({
age: Joi.number().when(Joi.ref('$minAge'), {
is: Joi.number().min(18),
then: Joi.required(),
otherwise: Joi.optional()
})
});
Здесь $minAge — это ссылка на значение из контекста. Joi
подставляет его из options.context.
Контекстные переменные обозначаются через $, что делает
их доступными в любом месте схемы.
Система ссылок Joi (Joi.ref) тесно связана с контекстом.
Ссылка может указывать:
Пример использования:
const schema = Joi.object({
password: Joi.string(),
confirm: Joi.any().valid(Joi.ref('password'))
});
Здесь контекстом выступает сам объект валидации, внутри которого происходит разрешение ссылок.
Если используется $-синтаксис:
Joi.ref('$role')
значение берётся уже из внешнего контекста, а не из проверяемого объекта.
При создании собственных валидаторов через .custom()
контекст доступен через параметры функции.
Joi.string().custom((value, helpers) => {
const role = helpers.prefs.context.role;
if (role === 'admin') {
return value;
}
if (value === 'restricted') {
return helpers.error('string.invalid');
}
return value;
});
Здесь helpers.prefs.context предоставляет доступ к
внешнему контексту, переданному при валидации.
Контекст активно используется при формировании сообщений об ошибках. Joi поддерживает шаблонные выражения, в которых можно подставлять значения из контекста.
Пример:
const schema = Joi.number().messages({
'number.min': 'Минимальное значение: {#limit}, роль: {#role}'
});
При расширенной настройке можно передавать дополнительные данные в ошибку через контекст:
schema.validate(value, {
context: {
role: 'guest'
}
});
Эти данные становятся доступны в шаблонах сообщений.
Во время рекурсивной валидации объектов Joi формирует внутренний контекст обхода структуры. Он включает:
path);Этот контекст используется системой для:
Метаданные схемы также являются частью контекстного слоя. Метка
(label) используется для:
Joi.string().label('Имя пользователя')
При ошибке эта информация попадает в контекст сообщения и может быть
использована в формате {#label}.
Контекст в Joi наследуется сверху вниз:
validate;При этом внутренние уровни могут расширять или уточнять контекст, но не всегда способны его переопределить полностью.
Особенно это важно для $-переменных, которые вычисляются
на этапе разрешения ссылок и могут зависеть от уровня вложенности.
При использовании Joi.extend() можно добавлять новые
типы, которые получают доступ к контексту в своих внутренних методах
валидации.
Joi.extend((joi) => ({
type: 'positive',
base: joi.number(),
validate(value, helpers) {
const mode = helpers.prefs.context.mode;
if (mode === 'strict' && value <= 0) {
return { value, errors: helpers.error('number.positive') };
}
return { value };
}
}));
Контекст здесь становится частью механизма определения поведения нового типа.
Контекст Joi имеет несколько характерных свойств:
Эти свойства делают его ключевым механизмом для построения адаптивных схем валидации, зависящих от внешних факторов и бизнес-логики.