Vest предоставляет механизм метаданных как встроенный слой описательной информации для тестов, групп и целых валидационных наборов. Метаданные используются для расширения логики проверки без изменения самой структуры валидации, позволяя отделять функциональную часть правил от вспомогательной информации: тегов, категорий, приоритетов, пользовательских атрибутов и контекста выполнения.
Валидационный набор в Vest может быть расширен объектом метаданных, который привязывается к самому набору. Это позволяет описывать общий контекст: форму, сущность данных, режим проверки или окружение.
import { create, test, enforce } from 'vest';
const suite = create('user_form', (data = {}) => {
test('username', 'invalid username', () => {
enforce(data.username).isNotEmpty();
});
}, {
meta: {
form: 'registration',
version: 2,
domain: 'auth'
}
});
Метаданные на уровне suite обычно используются для:
Каждый test может содержать собственный объект
метаданных, расширяющий описание конкретного правила. Это позволяет
выполнять фильтрацию, трассировку и динамическую обработку ошибок.
test(
'email',
'email is invalid',
() => {
enforce(data.email).isEmail();
},
{
meta: {
severity: 'high',
code: 'EMAIL_INVALID',
category: 'format'
}
}
);
Типовые сценарии применения метаданных тестов:
Vest предоставляет доступ к метаданным во время выполнения набора, что позволяет адаптировать поведение валидации динамически. Метаданные могут использоваться для условного изменения логики тестов.
import { get, meta } from 'vest';
const suite = create('profile', (data) => {
const mode = meta().get('mode');
if (mode === 'strict') {
test('age', 'too young', () => {
enforce(data.age).greaterThan(18);
});
} else {
test('age', () => {
enforce(data.age).greaterThan(16);
});
}
});
Использование runtime-метаданных применяется в случаях:
Метаданные suite могут быть изменены в процессе работы, что позволяет управлять поведением набора без пересоздания структуры.
import { meta } from 'vest';
meta().set('mode', 'strict');
meta().set('locale', 'ru-RU');
Подобный подход используется для:
Метаданные suite и тестов не конфликтуют, а существуют в разных слоях. При необходимости они объединяются на уровне логики приложения или внешнего обработчика.
Пример комбинирования:
const suite = create('order', (data) => {
test(
'price',
'invalid price',
() => {
enforce(data.price).greaterThan(0);
},
{
meta: {
field: 'price',
severity: 'critical'
}
}
);
}, {
meta: {
module: 'checkout',
domain: 'ecommerce'
}
});
Такое разделение позволяет:
Результаты выполнения suite могут обогащаться метаданными для последующей обработки в UI или API-слое. Это позволяет строить структурированные ответы, где каждая ошибка несёт не только сообщение, но и контекст.
const result = suite(data);
result.getErrors().forEach(error => {
const meta = error.meta;
if (meta.severity === 'critical') {
// обработка критических ошибок
}
});
Применение на практике:
В крупных системах метаданные становятся не вспомогательным, а структурообразующим элементом. Они позволяют превратить набор правил валидации в описательную модель предметной области.
Основные архитектурные сценарии:
Метаданные часто используются как мост между валидацией и внешними системами:
Пример расширенного использования:
test(
'password',
'weak password',
() => {
enforce(data.password).longerThan(8);
},
{
meta: {
analytics: {
event: 'validation_error',
field: 'password'
},
ui: {
highlight: true,
tooltip: 'Password too weak'
}
}
}
);
При проектировании системы метаданных в Vest важно учитывать ряд архитектурных ограничений:
Рациональная модель предполагает:
Метаданные могут формироваться не только статически, но и динамически, исходя из входных данных или внешнего контекста.
test('username', 'invalid', () => {
enforce(data.username).matches(/^[a-z]+$/);
}, {
meta: {
generatedAt: Date.now(),
requestId: data.requestId
}
});
Это позволяет:
При масштабировании приложений метаданные превращаются в независимый слой, который описывает правила, не изменяя их поведение. Такой подход облегчает интеграцию с системами визуализации, анализа и генерации отчетов, сохраняя при этом чистоту валидационной логики.