ts-generate-validator
v0.0.10
Published
Task to generate validation functions to check whether JSON data conforms to a schema described as typescript classes
Downloads
5
Maintainers
Readme
Tool for code generation validators by typescript model description
Кодогенерация валидаторов на основе typescript моделей
Содержание:
Мотивация
В ходе анализа популярных библиотек для валидации, таких как:
- validator.js
- class-validator
- yup
- joi
- ajv
стало понятно, что все они заставляют разработчика вручную писать валидационную схему. Т.е. во многом дублировать код на typescript.
Поэтому возникла идея сделать кодогенерацию валидации на основании TS описания. По примеру нашей библиотеки https://www.npmjs.com/package/grunt-generate-view-model
Что хотим от валидации:
- изоморфность (возможность использования как на клиенте, так и на сервере);
- не описывать отдельную схему валидации, а использовать typescript-описание;
- для случаев, выходящих за рамки TS (проверка на соотвествие regexp, минимального значения, максимального значения и т.п.) использовать декораторы;
- возможность использования кастомной валидации в виде функции, возможно асинхронной;
- мультиязычность (вывод ошибок валидации на разных языках);
- удобство использования;
Установка
npm install ts-generate-validator -D
Использование
- Создать внутри папки
src
класс-модель на typescript и добавить к этому классу декоратор@Validation
:
// src/model.ts
import { Validation } from 'ts-generate-validator';
@Validation
export class User {
public name: string = '';
public age: number = 0;
public website?: string;
}
- Добавить в раздел
scripts
файлаpackage.json
инициализирующую команду "generateValidator", например:
"scripts": {
"generation": "generateValidator"
}
- Запустить кодогенерацию
npm run generation
В папке
src/generated/validators
появится новый файлsrc.model.ts
экспортирующий функцию-валидаторuserValidator
Использовать валидатор для проверки соответствия данных json схеме, описанной в typescript моделе:
// src/index.ts
import { ValidationException } from 'ts-generate-validator';
import { userValidator } from 'src/generated/validators';
const data = {
name: 'John',
age: 30
};
try {
userValidator(data, { stopAtFirstError: true });
} catch (exception) {
if (exception instanceof ValidationException) {
console.log(`Неправильный формат данных`);
exception.errors.map(({ field, message }) => `[${field}] - ${message}`).forEach((msg) => console.log(msg));
} else {
throw exception;
}
}
Как это работает
Конфигурация кодогенерации
Для изменения конфигурации по умолчанию, создайте файл "ts-generate-validator-config.json
" в корне проекта, содержащий объект с любыми из следующих свойств:
inputPath
(string) - путь к папке с моделями для которых необходимо сгенерировать валидаторы (по умолчанию "src").
outputPath
(string) - путь к папке, в которой появятся сгенерированные валидаторы (по умолчанию "src/generated/validators").
unknownPropertySeverityLevel
(number) - уровень проверки неизвестных параметров (параметров, имеющих 1) тип в виде ссылки на другие классы моделей без @Validation
декораторов или 2) не поддерживаемые типы без @CustomValidation
декораторов). Может иметь следующие значения:
2
(error) - при генерации валидаторов выбрасывается ошибка1
(warning) - кодогенерация проходит, но в консоли появляется предупреждение об отсутствии валидации0
(silent) - кодогенерация проходит
по умолчанию: 1
("warning")
Например:
{
"inputPath": "src/models",
"outputPath": "generated/validators",
"unknownPropertySeverityLevel": 2
}
Конфигурация валидаторов
Конфигурацию валидаторов можно изменить двумя способами
- Изменения глобальной конфигурации валидаторов с помощью функции
changeConfig
:
import { changeConfig } from 'ts-generate-validator';
changeConfig({ stopAtFirstError: true });
- Изменение конфигурации только для текущего вызова валидатора:
import { userValidator } from 'src/generated/validators';
userValidator(data, { stopAtFirstError: true });
Следующие параметры могут быть сконфигурированы:
stopAtFirstError
(boolean) - не продолжать валидацию после первой найденной ошибки (по умолчанию false).
emailRegExp
(RegExp) - заменяет регулярное выражение по умолчанию для проверки email.
messages
(object) - словарь с сообщениями об ошибках (по умолчанию используются стандартные сообщения на английском).
Валидатор
Сгенерированная из класса-модели функция-валидатор данных является асинхронной, если хотя бы для одного из свойств в классе-модели добавлен асинхронный custom валидатор. Она принимает в качестве аргументов:
data
(any) (обязательный) - JSON данные для проверки
config
(object) (необязательный) - объект с параметрами конфигурации
context
(any) (необязательный) - любое пользовательское значение, которое будет доступно в пользовательских валидаторах
Результат выполнения:
Пустой результат в результате успешной валидации. Если валидация завершилась неудачей, то выбрасывается ValidationException
.
Локализация
Сообщения об ошибке по умолчанию на английском языке, но они могут быть заменены на любые другие с помощью декораторов свойств классов-моделей (смотрите раздел декораторы для свойств классов), либо через установку параметра messages
в конфигурации валидаторов (смотрите раздел конфигурация валидаторов).
Декораторы
Декораторы могут быть применены на классах, и на свойствах классов.
Для классов
@Validation(config?: ValidationConfig)
- помечает класс, как требующий генерации функции-валидатора.@RequiredOneOfValidation(fields: string[], message?: Message)
- добавляет к нескольким свойствам класса, перечисленным в первом аргументе fields, валидатор, проверяющий заполненность как минимум одного из указанных полей.
Для свойств классов
all supported types (смотрите поддерживаемые типы)
@TypeValidation(message: Message)
- заменяет стандартное сообщение об ошибке для валидатора типа.
all types
@CustomValidation(validator: CustomValidator, message: Message)
- добавляет к свойству пользовательскую функцию-валидатор, которая принимает в качестве первого аргумента объект со следующими свойствами:property
(any) - значение свойства для валидацииpropertyName
(string) - имя свойства для валидацииdata
(object) - объект с JSON данными для валидацииconfig
(object) - объект с текущей конфигурацией валидаторовcontext
(any) - пользовательский контекст, переданный в сгенерированную функцию-валидаторВозвращаемое значение: в случае успешной валидации - ничего не возвращает, в случае когда данные не соответствуют типу - должна выбрасываться ошибка
ValidationError
, например:import { ValidationError } from 'ts-generate-validator'; ({ property, propertyName }) => { const allowedValues = [1, 4, 9]; if (!allowedValues.includes(property)) { throw new ValidationError(propertyName, 'is invalid'); } };
@IgnoreValidation
- помечает свойство как игнорируемое в функции-валидаторе - оно не будет проверяться на соответствие типу, а любые примененные декораторы для дополнительной валидацией будут проигнорированы.
boolean, number, string, null, enum, union(boolean, number, string, null), array(boolean, number, string, null)
@EqualValidation(value: EqualToValue, message?: Message)
- добавляет валидатор, который проверяет соответствие значения свойства - значению, переданному в первом аргументе (в первом аргументе допускаются любые уровни вложенности в массивах).@EqualToValidation(propName: string, message?: Message)
- добавляет валидатор, который проверяет соответствие значения свойства, на котором был использован декоратор - свойству, содержащемуся в свойствеpropName
.
number, number[]
@MinValidation(threshold: number, message?: Message)
- добавляет валидатор, который проверяет число на соответствие минимальному значениюthreshold
(включительно).@MaxValidation(threshold: number, message?: Message)
- добавляет валидатор, который проверяет число на соответствие максимальному значениюthreshold
(включительно).@NegativeValidation(message?: Message)
- добавляет валидатор, который проверяет - является ли число отрицательным.@PositiveValidation(message?: Message)
- добавляет валидатор, который проверяет - является ли число положительным.@IntegerValidation(message?: Message)
- добавляет валидатор, который проверяет - является ли число целым.@FloatValidation(message?: Message)
- добавляет валидатор, который проверяет - содержит ли число плавающую точку.@LessThanValidation(propName: string, message?: Message)
- добавляет валидатор, который проверяет - является ли число меньшим, чем число в свойствеpropName
.@MoreThanValidation(propName: string, message?: Message)
- добавляет валидатор, который проверяет - является ли число большим, чем число в свойствеpropName
.
string, string[]
@TrimValidation(message?: Message)
- добавляет валидатор, который проверяет отсутствие пробелов в начале и конце строки.@LowercaseValidation(message?: Message)
- добавляет валидатор, который проверяет отсутствие заглавных букв в строке.@UppercaseValidation(message?: Message)
- добавляет валидатор, который проверяет отсутствие строчных букв в строке.@MinLengthValidation(threshold: number, message?: Message)
- добавляет валидатор, который проверяет длину строки на соответствие максимальному значениюthreshold
(включительно).@maxLength(threshold: number, message?: Message)
- добавляет валидатор, который проверяет длину строки на соответствие максимальному значениюthreshold
(включительно).@EmailValidation(message?: Message)
- добавляет валидатор, который проверяет - является ли строка корректным email адресом.@UrlValidation(message?: Message)
- добавляет валидатор, который проверяет - является ли строка корректным url адресом.@MatchValidation(regexp: RegExp, message?: Message)
- добавляет валидатор, который проверяет строку на соответствие регулярному выражению, переданному в первом аргументе.
Поддерживаемые типы
| Тип | Поддержка | Определение типа по значению |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| boolean
| Да | Да |
| number
| Да | Да |
| string
| Да | Да |
| null
| Да | Да |
| undefined
| Нет | Нет |
| enum
| Да | Нет |
| array
| Частично (поддерживаются только массивы, элементы которых являются поддерживаемыми типами) | Нет |
| union
| Частично (поддерживаются только объединения из свойств, имеющих поддерживаемый тип) | Нет |
| class
| Частично (поддерживаются только классы, имеющие декоратор @Validation
и находящиеся в каталогах, доступных для генерации валидаций - смотрите в конфигурации кодогенерации свойство inputPath
) | Нет |
| interface
| Нет | Нет |
| type
| Нет (кастомные typescript типы не поддерживаются) | Нет |
| typeof
| Нет | Нет |