validateпакет
Валидация объектов на основе правил-аннотаций
Пакет лежит в основном пуле хаба: короткой формы достаточно, если хаб прописан сервером пакетов в opm.cfg.
opm install validateУстановка на opm младше 1.7.0
Легаси-флоу. Клиент младше 1.7.0 адрес пула в аргументе не разбирает: пул сначала прописывают сервером пакетов, и только потом ставят через него. На 1.7.0 и новее этот раздел не нужен — хватает команды из шапки страницы.
Добавьте пул сервером пакетов в opm.cfg. Порт продублирован в «Сервер»: у opm push поле «Порт» не читается.
{
"СервераПакетов": [
{
"Имя": "default",
"Сервер": "https://hub.1cdevelopers.ru",
"Порт": 443,
"ПутьНаСервере": "/api/v1/pools/default/download/",
"РесурсПубликацииПакетов": "/api/v1/pools/default/push",
"Приоритет": 1
}
]
}И ставьте пакет, указывая сервер:
opm install -m default validateОписание
validate
Валидация объектов на основе правил-аннотаций для OneScript.
Библиотека позволяет описывать ограничения прямо на свойствах объектов через аннотации и выполнять проверку одним вызовом валидатора. Поддерживается проверка вложенных объектов, настраиваемые сообщения и простое расширение набора правил.
Для навигации по коллекциям используйте переключающую аннотацию &ДляКаждого:
&ДляКаждого("Значение")— переключает контекст на элементы коллекции (значение режима можно опустить)&ДляКаждого("Ключ")— переключает контекст на ключи коллекции (только для коллекций, итерируемых как КлючИЗначение)
Требования
- OneScript 1.9.2 или выше
Установка
- Через OPM (OneScript Package Manager):
opm install validate
- Локально в проект: добавьте зависимость в ваш packagedef:
.ЗависитОт("validate", "0.1.0")
Быстрый старт
Опишите ограничения аннотациями на полях вашего объекта:
&Заполнено(Сообщение = "Произвольное сообщение")
Перем Поле1 Экспорт;
&Заполнено
Перем Поле2 Экспорт;
&Минимум(-10)
&Максимум(10)
Перем Поле3 Экспорт;
&Валидно
Перем ВложенныйОбъект Экспорт;
&Тип("Число")
Перем Поле4 Экспорт;
// Элементы массива — строки
&Тип("Массив")
&ДляКаждого
&Тип("Строка")
Перем КоллекцияСтрок Экспорт;
// Значения структуры — числа
&Тип("Структура")
&ДляКаждого
&Тип("Число")
Перем СтруктураЧисел Экспорт;
// Ключи соответствия — числа
&Тип("Соответствие")
&ДляКаждого("Ключ")
&Тип("Число")
Перем СоответствиеЧисловыхКлючей Экспорт;
Выполните валидацию и выведите ошибки:
Валидатор = Новый Валидатор;
Объект = Новый ТестовыйОбъект; // ваш класс с аннотациями
Результат = Валидатор.Валидировать(Объект);
Если Результат.Количество() > 0 Тогда
Сообщить(Валидатор.ОписаниеОшибокВалидации(Результат));
КонецЕсли;
Пример строки в отчете об ошибках:
[filled]: Объект: <ТипОбъекта>, Свойство: Поле2, Сообщение: Значение не заполнено
Подробные примеры работы с Валидатором
Пример 1: Создание класса с аннотациями
Создайте класс с аннотациями валидации:
// Класс ПользовательДанные.os
&Заполнено(Сообщение = "Имя пользователя обязательно для заполнения")
Перем Имя Экспорт;
&Заполнено
&Минимум(18)
&Максимум(120)
Перем Возраст Экспорт;
&Заполнено
Перем Email Экспорт;
&Минимум(0)
&Максимум(100000)
Перем Зарплата Экспорт;
&Истина
Перем Активен Экспорт;
Пример 2: Валидация данных (корректных и некорректных)
// Создаем валидатор
Валидатор = Новый Валидатор;
// Сначала валидируем корректные данные
Пользователь = Новый ПользовательДанные;
Пользователь.Имя = "Иван Иванов";
Пользователь.Возраст = 30;
Пользователь.Email = "ivan@example.com";
Пользователь.Зарплата = 50000;
Пользователь.Активен = Истина;
РезультатВалидации = Валидатор.Валидировать(Пользователь);
// Проверяем результат - для корректных данных ошибок не будет
Если РезультатВалидации.Количество() = 0 Тогда
Сообщить("Данные корректны! Валидация прошла успешно.");
Иначе
Сообщить("Неожиданные ошибки при валидации корректных данных");
КонецЕсли;
// Теперь валидируем некорректные данные
НекорректныйПользователь = Новый ПользовательДанные;
НекорректныйПользователь.Имя = ""; // Пустое имя
НекорректныйПользователь.Возраст = 15; // Меньше минимума
НекорректныйПользователь.Зарплата = 150000; // Больше максимума
НекорректныйПользователь.Активен = Ложь; // Должно быть Истина
РезультатВалидации = Валидатор.Валидировать(НекорректныйПользователь);
// Выводим все ошибки
Если РезультатВалидации.Количество() > 0 Тогда
Сообщить("Найдено нарушений: " + РезультатВалидации.Количество());
Сообщить(Валидатор.ОписаниеОшибокВалидации(РезультатВалидации));
Иначе
Сообщить("Ошибка: валидация должна была найти нарушения");
КонецЕсли;
Пример 3: Обработка отдельных нарушений
// Создаем объект с ошибками
Пользователь = Новый ПользовательДанные;
Пользователь.Возраст = 200; // Превышает максимум
// Остальные поля не заполнены
РезультатВалидации = Валидатор.Валидировать(Пользователь);
// Обрабатываем каждое нарушение отдельно
Для Каждого Нарушение Из РезультатВалидации Цикл
ИмяСвойства = Нарушение.ИмяСвойства();
Сообщение = Нарушение.Сообщение();
КодОшибки = Нарушение.Код();
// Можно обрабатывать разные типы ошибок по-разному
Если КодОшибки = "filled" Тогда
Сообщить("Поле не заполнено: " + ИмяСвойства + " - " + Сообщение);
ИначеЕсли КодОшибки = "max" Тогда
Сообщить("Превышен максимум для поля: " + ИмяСвойства + " - " + Сообщение);
ИначеЕсли КодОшибки = "min" Тогда
Сообщить("Значение меньше минимума для поля: " + ИмяСвойства + " - " + Сообщение);
Иначе
Сообщить("Ошибка валидации [" + КодОшибки + "]: " + ИмяСвойства + " - " + Сообщение);
КонецЕсли;
КонецЦикла;
Пример 4: Валидация вложенных объектов
// Класс ПользовательДанные.os (сокращенная версия)
&Заполнено
Перем Имя Экспорт;
&Валидно // Эта аннотация указывает, что нужно валидировать вложенный объект
Перем Адрес Экспорт;
// Класс Адрес.os
&Заполнено
Перем Город Экспорт;
&Заполнено
&Минимум(100000)
&Максимум(999999)
Перем Индекс Экспорт;
// Создаем пользователя с адресом
Пользователь = Новый ПользовательДанные;
Пользователь.Имя = "Петр Петров";
// Создаем адрес с ошибкой
Адрес = Новый Адрес;
Адрес.Город = "Москва";
Адрес.Индекс = 12345; // Меньше минимума
Пользователь.Адрес = Адрес;
// Валидация проверит и основной объект, и вложенный
// благодаря аннотации &Валидно у поля Адрес
РезультатВалидации = Валидатор.Валидировать(Пользователь);
Если РезультатВалидации.Количество() > 0 Тогда
Сообщить("Ошибки валидации:");
Сообщить(Валидатор.ОписаниеОшибокВалидации(РезультатВалидации));
КонецЕсли;
Поддерживаемые аннотации
&Заполнено(Сообщение = "...")— значение поля должно быть заполнено. Код нарушения:filled.&Истина— булево значение должно быть Истина. Код нарушения:true.&Ложь— булево значение должно быть Ложь. Код нарушения:false.&Минимум(<число>)— значение не меньше минимума. Код нарушения:min.&Максимум(<число>)— значение не больше максимума. Код нарушения:max.&Размер(Минимум = <число>, Максимум = <число>)— размер значения в заданных границах. Код нарушения:size.&Кратно(<число>)— значение кратно указанному числу. Код нарушения:multipleOf.&Шаблон(<строка>)— значение соответствует регулярному выражению. Код нарушения:pattern.&Формат(<строка>)— значение соответствует известному формату. Код нарушения:format.&ОдинИз(<строка>)— значение входит в список допустимых. Код нарушения:oneOf.&Тип(<строка>)— значение должно иметь указанный тип. Код нарушения:type.&Валидно— рекурсивная проверка вложенного объекта. Код нарушения:valid.
&Минимум и &Максимум сравнивают само значение, &Размер — его размер: длину строки либо количество элементов коллекции. Для строки &Максимум(10) означает лексикографическое сравнение, а &Размер(Максимум = 10) — ограничение длины. Ноль в Максимум означает отсутствие верхней границы.
&Шаблон проверяет значение целиком: выражение неявно привязано к началу и концу строки, поэтому \d+ не пропустит abc123.
У &ОдинИз параметр Значение повторяемый: допустимые значения перечисляются повторением параметра. Сравнение строковое, поэтому ограничение работает и для чисел.
&Кратно допускает дробную кратность: &Кратно(0.5) пропустит 1.5 и не пропустит 1.2.
&Формат знает email, uuid, uri, date, date-time и ipv4. Список намеренно открытый: неизвестное имя формата значение не отбраковывает — формат это ещё и способ описать поле для потребителя, и ограничивать разметку тем, что библиотека умеет проверять, незачем. Выражения нестрогие: их задача — отсечь явно непохожее, а не заменить собой разбор адреса или даты.
&Размер(Минимум = 2, Максимум = 20)
Перем Имя Экспорт;
&Шаблон("\d{3}-\d{2}")
Перем Код Экспорт;
&Формат("email")
Перем Почта Экспорт;
&Кратно(0.5)
Перем Часы Экспорт;
&ОдинИз(Значение = "создан", Значение = "оплачен", Значение = "отгружен")
Перем Статус Экспорт;
Переключение контекста коллекций задаётся аннотацией &ДляКаждого; её можно указывать несколько раз для вложенных коллекций.
Сообщение об ошибке можно переопределить параметром аннотации Сообщение.
Примеры для коллекций
- Элементы массива в диапазоне 0..10:
&Тип("Массив")
&ДляКаждого
&Тип("Число")
&Минимум(0)
&Максимум(10)
Перем МассивЧиселСДиапазоном Экспорт;
- Ключи соответствия больше 5 (минимум 6):
&Тип("Соответствие")
&ДляКаждого("Ключ")
&Тип("Число")
&Минимум(6)
Перем СоответствиеКлючиБольше5 Экспорт;
Примечание: при &ДляКаждого("Ключ") для коллекций без ключей (например, Массив) будет выброшено исключение.
Расширение и кастомизация
- Конструктор валидатора поддерживает подмену фабрики валидаций и контейнера аннотаций:
Валидатор = Новый Валидатор(МояФабрикаВалидаций, МойКонтейнерАннотаций);
- По умолчанию используется
СтандартнаяФабрикаВалидаций, где назначено соответствие аннотаций и классов валидаций (ВалидацияОграниченияЗаполнено,...Минимум,...Максимум,...Истина,...Ложь,...Тип,...Валидно). - Можно добавлять собственные аннотации в контейнер и свои реализации классов валидаций/ограничений.
Запуск тестов
В проект включены авто-тесты на 1testrunner. Запустить можно так:
oscript tasks/test.os
Результаты в формате JUnit сохраняются в каталоге out.
Покрытие кода
Для прогона тестов со сбором покрытия используйте задачу из tasks/coverage.os:
oscript tasks/coverage.os
Скрипт сохранит статистику в out/stat.json и сформирует отчеты:
out/genericCoverage.xml— Generic Coverage (используется Sonar)out/cobertura.xml— отчет в формате Cobertura (используется плагином Coverage Gutters в VSCode)
Лицензия
Этот проект лицензируется под лицензией MIT. Подробности см. в файле LICENSE.md.