sml-mirror / ts-generate-validator

MIT License
0 stars 0 forks source link

Tool for code generation validators by typescript model description

Кодогенерация валидаторов на основе typescript моделей

Содержание:

Мотивация

В ходе анализа популярных библиотек для валидации, таких как:

стало понятно, что все они заставляют разработчика вручную писать валидационную схему. Т.е. во многом дублировать код на typescript.

Поэтому возникла идея сделать кодогенерацию валидации на основании TS описания. По примеру нашей библиотеки https://www.npmjs.com/package/grunt-generate-view-model

Что хотим от валидации:

  1. изоморфность (возможность использования как на клиенте, так и на сервере);
  2. не описывать отдельную схему валидации, а использовать typescript-описание;
  3. для случаев, выходящих за рамки TS (проверка на соотвествие regexp, минимального значения, максимального значения и т.п.) использовать декораторы;
  4. возможность использования кастомной валидации в виде функции, возможно асинхронной;
  5. мультиязычность (вывод ошибок валидации на разных языках);
  6. удобство использования;

Установка

npm install ts-generate-validator -D

Использование

  1. Создать внутри папки 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;
}
  1. Добавить в раздел scripts файла package.json инициализирующую команду "generateValidator", например:
  "scripts": {
    "generation": "generateValidator"
  }
  1. Запустить кодогенерацию
npm run generation
  1. В папке src/generated/validators появится новый файл src.model.ts экспортирующий функцию-валидатор userValidator

  2. Использовать валидатор для проверки соответствия данных 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 декораторов). Может иметь следующие значения:

по умолчанию: 1 ("warning")

Например:

{
  "inputPath": "src/models",
  "outputPath": "generated/validators",
  "unknownPropertySeverityLevel": 2
}

Конфигурация валидаторов

Конфигурацию валидаторов можно изменить двумя способами

  1. Изменения глобальной конфигурации валидаторов с помощью функции changeConfig:
import { changeConfig } from 'ts-generate-validator';

changeConfig({ stopAtFirstError: true });
  1. Изменение конфигурации только для текущего вызова валидатора:
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 в конфигурации валидаторов (смотрите раздел конфигурация валидаторов).

Декораторы

Декораторы могут быть применены на классах, и на свойствах классов.

Для классов

Для свойств классов

Поддерживаемые типы

Тип Поддержка Определение типа по значению
boolean Да Да
number Да Да
string Да Да
null Да Да
undefined Нет Нет
enum Да Нет
array Частично (поддерживаются только массивы, элементы которых являются поддерживаемыми типами) Нет
union Частично (поддерживаются только объединения из свойств, имеющих поддерживаемый тип) Нет
class Частично (поддерживаются только классы, имеющие декоратор @Validation и находящиеся в каталогах, доступных для генерации валидаций - смотрите в конфигурации кодогенерации свойство inputPath) Нет
interface Нет Нет
type Нет (кастомные typescript типы не поддерживаются) Нет
typeof Нет Нет

Лицензия

MIT License