Миграция между версиями Joi обычно связана с изменениями в API, поведении валидаторов и структурировании схем. Библиотека эволюционирует в сторону большей строгости, модульности и предсказуемости результатов валидации, поэтому обновления часто сопровождаются необходимостью адаптации существующего кода.
Одним из ключевых аспектов миграции является изменение дефолтного поведения валидации.
В старых версиях часто использовалась логика раннего завершения проверки:
В более новых версиях поведение становится более гибким, но при миграции важно явно фиксировать нужный режим:
Joi.object({
email: Joi.string().email(),
password: Joi.string().min(8)
}).validate(data, { abortEarly: false });
Изменение значения по умолчанию приводит к необходимости пересмотра обработки ошибок на уровне приложения.
Ранее многие схемы допускали неявное прохождение лишних полей. В новых версиях усиливается контроль за структурой данных.
Ключевые изменения:
allowUnknown становится более явно управляемым;stripUnknown используется чаще как безопасная
практика.Пример обновлённого поведения:
Joi.object({
username: Joi.string().required()
}).validate(data, {
allowUnknown: false,
stripUnknown: true
});
В процессе миграции важно учитывать, что ранее «лишние» поля могли проходить незаметно.
Старые версии активно использовали callback-подход:
schema.validate(data, (err, value) => {
// обработка
});
В более новых версиях предпочтение отдаётся Promise-ориентированному API:
await schema.validateAsync(data);
При миграции требуется:
В старых версиях структура ошибок была менее стандартизированной. Новые версии усиливают консистентность:
details становится основным источником информации;Пример обработки:
try {
await schema.validateAsync(data);
} catch (err) {
err.details.forEach(d => {
console.log(d.message);
});
}
Ранее часто использовались простые строки. В новых версиях
расширяется система messages:
Joi.string().min(8).messages({
'string.min': 'Строка слишком короткая'
});
При миграции важно заменить устаревшие методы кастомизации на новую систему ключей сообщений.
В процессе эволюции Joi ряд методов был изменён или признан устаревшим.
Ранее часто использовались неявные комбинации:
Joi.string().required()
Хотя базовая логика сохраняется, в новых версиях усиливается явность схем:
Методы вроде allow() в старых версиях использовались
более свободно, включая неожиданные типы значений. В новых версиях:
Условная логика валидации претерпела изменения.
Старые конструкции:
Joi.string().when('role', {
is: 'admin',
then: Joi.required()
});
В новых версиях усиливается читаемость и строгая типизация условий.
Особенности миграции:
alternatives()) используются чаще.Ранее вложенные объекты могли частично игнорировать строгие правила. Новые версии усиливают:
Поведение default() и cast становится более
детерминированным.
Joi.object({
createdAt: Joi.date().default(Date.now)
});
При миграции важно учитывать:
Механизм альтернативных схем становится более строгим:
Пример:
Joi.alternatives().try(
Joi.string(),
Joi.number()
);
В процессе миграции важно пересмотреть все места, где типы ранее определялись неявно.
В новых версиях усиливается контроль над преобразованием типов:
Пример изменения поведения:
Joi.number().strict()
Использование strict() становится важным инструментом
при миграции для выявления скрытых преобразований.
В старых версиях расширение схем было менее структурированным. В новых версиях:
При миграции кастомных валидаторов необходимо:
При переходе между версиями Joi основная сложность заключается не в синтаксисе, а в изменении семантики.
Рекомендуемая стратегия:
strict,
abortEarly, stripUnknown).Особое внимание требуется уделять:
Из-за изменения структуры details могут измениться
форматы логирования.
Код, зависящий от слабой типизации, начинает падать.
Значения по умолчанию могут применяться в другом порядке.
Ранее допустимые данные начинают отклоняться или удаляться.
В крупных кодовых базах миграция обычно включает:
Такая стратегия снижает риск регрессий при переходе между версиями.