Использование метаданных

В библиотеке реализована модель декларативной валидации, в которой правила описываются не в виде процедурного кода, а через аннотации классов и их свойств. Эти аннотации не выполняют проверку напрямую — они формируют структуру данных, описывающую правила. Такая структура и называется метаданными в контексте системы.

Метаданные представляют собой промежуточный слой между декларацией и выполнением валидации. Каждый декоратор добавляет в общий реестр информацию о том, какие ограничения должны применяться к конкретному свойству класса.

Ключевая идея заключается в том, что:

  • класс содержит только описание структуры данных;
  • декораторы формируют набор правил;
  • валидатор интерпретирует эти правила в момент выполнения.

Роль reflect-metadata в хранении информации

В экосистеме TypeScript и JavaScript метаданные обычно связываются с использованием пакета reflect-metadata. Он расширяет возможности рефлексии и позволяет привязывать произвольные данные к классам и их свойствам.

Базовый механизм выглядит следующим образом:

  • к классу или полю прикрепляется ключ метаданных;
  • под этим ключом хранится массив или объект описаний ограничений;
  • при вызове валидации эти данные извлекаются через Reflect API.

Типовой набор операций включает:

  • добавление метаданных;
  • получение метаданных по ключу;
  • проверку наличия метаданных;
  • наследование метаданных при расширении классов.

Используемые ключи не являются частью публичного API JavaScript и задаются библиотекой валидации.

Структура метаданных валидации

Каждое правило валидации преобразуется в объект метаданных. Эти объекты формируют массив, связанный с конкретным свойством.

Типичная структура метаданных включает:

  • target — класс, к которому относится правило;
  • propertyName — имя свойства;
  • validationType — тип проверки (например, строка, число, диапазон);
  • constraints — параметры ограничения;
  • options — дополнительные параметры поведения;
  • validationOptions — конфигурация групп, условий и сообщений об ошибках.

Каждый декоратор добавляет отдельный элемент в этот массив. Например, несколько декораторов на одном свойстве приводят к накоплению нескольких метаданных.

Механизм работы декораторов

Декораторы не выполняют проверку напрямую. Их задача — зарегистрировать описание ограничения.

При использовании декоратора:

@IsString()
name: string;

происходит следующее:

  • создаётся объект метаданных;
  • указывается тип проверки isString;
  • привязывается к свойству name;
  • добавляется в общий реестр метаданных класса.

Каждый следующий декоратор дополняет этот набор, а не заменяет его.

Внутреннее хранилище метаданных

Библиотека использует внутреннюю структуру хранения, которая организована как иерархия:

  • уровень класса;
  • уровень свойства;
  • массив правил валидации для свойства.

Такая структура позволяет эффективно:

  • извлекать все правила для конкретного класса;
  • фильтровать правила по свойствам;
  • применять групповые ограничения.

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

Наследование метаданных

При использовании наследования классов метаданные также наследуются. Это позволяет расширять модели данных без повторного описания всех ограничений.

Механизм наследования включает:

  • копирование метаданных базового класса;
  • объединение с метаданными дочернего класса;
  • приоритет дочерних правил при конфликте.

Это поведение особенно важно при построении сложных доменных моделей, где общие правила выносятся в базовые сущности.

Динамическое формирование метаданных

Метаданные могут формироваться не только статически через декораторы, но и динамически через программный API.

Поддерживаются сценарии:

  • регистрация пользовательских правил;
  • добавление ограничений во время выполнения;
  • создание сложных условий на основе конфигурации.

Для этого используется функция регистрации пользовательских валидаторов и декораторов, которая добавляет метаданные в общий реестр вручную.

Пользовательские метаданные через registerDecorator

Механизм registerDecorator позволяет создавать собственные правила, которые становятся частью системы метаданных.

При регистрации указываются:

  • имя валидатора;
  • целевой объект;
  • свойства;
  • функция проверки;
  • дополнительные параметры.

После регистрации создаётся такой же объект метаданных, как и у встроенных декораторов. Это обеспечивает единообразие обработки.

Валидатор как интерпретатор метаданных

Функция validate не содержит жёстко зашитых правил для каждого случая. Вместо этого она:

  • извлекает метаданные для класса;
  • проходит по каждому свойству;
  • применяет соответствующие функции проверки;
  • собирает результаты ошибок.

Таким образом, метаданные выступают в роли промежуточного языка описания ограничений, а валидатор — как интерпретатор этого языка.

Группировка метаданных

Метаданные поддерживают группировку, позволяющую разделять сценарии валидации.

Группы используются для:

  • частичной проверки объектов;
  • различных контекстов (создание, обновление, удаление);
  • условного применения правил.

Каждое правило может содержать список групп, к которым оно относится. При запуске валидации можно указать активные группы, и только соответствующие метаданные будут учитываться.

Условное применение метаданных

Помимо групп, метаданные могут содержать условия выполнения:

  • проверка только при наличии значения;
  • игнорирование пустых значений;
  • зависимость от других свойств объекта.

Такие условия хранятся в объекте метаданных и учитываются во время интерпретации.

Порядок выполнения и приоритет метаданных

При наличии нескольких правил на одном свойстве порядок их применения определяется порядком регистрации.

Особенности обработки:

  • метаданные сохраняются в порядке добавления;
  • при валидации выполняются последовательно;
  • ошибки собираются без остановки цепочки (если не указано иное).

Некоторые типы ограничений могут прерывать дальнейшую проверку свойства, если это предусмотрено опциями.

Связь метаданных с трансформацией типов

Метаданные используются не только для проверки, но и для преобразования данных при использовании совместно с class-transformer.

В этом случае:

  • метаданные описывают ожидаемый тип;
  • трансформер приводит входные данные к нужному формату;
  • валидатор проверяет уже преобразованное значение.

Такая связка позволяет строить полноценные пайплайны обработки входных данных.

Кэширование метаданных

Для повышения производительности система кэширует результаты извлечения метаданных.

Кэш включает:

  • список правил для класса;
  • индексированные свойства;
  • вычисленные группы и фильтры.

Это позволяет избегать повторного анализа декораторов при каждой валидации одного и того же класса.

Инспекция метаданных

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

При инспекции доступны:

  • список всех свойств с ограничениями;
  • типы проверок;
  • параметры каждого правила;
  • группы и условия применения.

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

Расширение системы через метаданные

Модель метаданных позволяет расширять систему без изменения ядра:

  • добавление новых типов валидаторов;
  • создание сложных комбинированных правил;
  • интеграция с внешними схемами (например, DTO-описаниями);
  • построение адаптеров для API-слоёв.

Метаданные выступают стабильным контрактом между декларацией и выполнением, что делает архитектуру гибкой и расширяемой.