Схемы валидации

Библиотека Validator.js предоставляет набор функций для проверки строковых значений, но при проектировании сложных форм и структур данных поверх неё формируется концепция схем валидации — описаний правил, по которым проверяются входные данные. Схема валидации в контексте JavaScript-приложений представляет собой формализованное описание структуры объекта, где каждому полю сопоставлен набор правил проверки и нормализации.

Схема валидации обычно реализуется как объект, в котором ключи соответствуют полям входных данных, а значения — функциям или цепочкам проверок:

const schema = {
  email: (value) => validator.isEmail(value),
  password: (value) => validator.isLength(value, { min: 8 })
};

Такая структура позволяет отделить описание правил от бизнес-логики обработки данных. Каждое поле становится независимым модулем проверки, что упрощает масштабирование.

Композиция правил

Validator.js предоставляет атомарные функции, которые легко комбинируются в более сложные проверки. Схемы строятся через последовательное применение условий:

const isStrongPassword = (value) =>
  validator.isLength(value, { min: 8 }) &&
  validator.matches(value, /[A-Z]/) &&
  validator.matches(value, /[0-9]/);

Композиция позволяет формировать переиспользуемые блоки логики, которые затем включаются в схемы разных объектов.

Схемы для объектов данных

При обработке форм или API-запросов схема часто описывает сразу весь объект:

const userSchema = {
  username: (v) => validator.isAlphanumeric(v),
  email: (v) => validator.isEmail(v),
  age: (v) => validator.isInt(v, { min: 0, max: 120 })
};

function validate(data, schema) {
  const errors = {};

  for (const key in schema) {
    const isValid = schema[key](data[key]);
    if (!isValid) {
      errors[key] = 'Invalid value';
    }
  }

  return Object.keys(errors).length ? errors : null;
}

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

Вложенные структуры

При работе со сложными объектами схемы становятся иерархическими. Вложенные структуры описываются рекурсивно:

const profileSchema = {
  name: (v) => validator.isLength(v, { min: 2 }),
  contact: {
    email: (v) => validator.isEmail(v),
    phone: (v) => validator.isMobilePhone(v, 'any')
  }
};

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

function validateObject(data, schema) {
  const errors = {};

  for (const key in schema) {
    if (typeof schema[key] === 'function') {
      if (!schema[key](data[key])) {
        errors[key] = 'Invalid value';
      }
    } else {
      const nested = validateObject(data[key] || {}, schema[key]);
      if (Object.keys(nested).length) {
        errors[key] = nested;
      }
    }
  }

  return errors;
}

Схемы массивов

Массивы требуют отдельного подхода, поскольку проверка применяется к каждому элементу:

const tagsSchema = {
  tags: (arr) =>
    Array.isArray(arr) &&
    arr.every(tag => validator.isAlphanumeric(tag))
};

Более детализированная схема может включать проверку длины массива и ограничение элементов:

const schema = {
  tags: (arr) =>
    Array.isArray(arr) &&
    arr.length <= 10 &&
    arr.every(tag => validator.isLength(tag, { min: 1, max: 20 }))
};

Условная валидация

Схемы часто включают зависимости между полями. Условная логика реализуется через функции, принимающие весь объект:

const schema = {
  password: (v) => validator.isLength(v, { min: 8 }),
  confirmPassword: (v, data) => v === data.password
};

Расширенная обработка:

function validate(data, schema) {
  const errors = {};

  for (const key in schema) {
    const valid = schema[key](data[key], data);
    if (!valid) {
      errors[key] = 'Invalid value';
    }
  }

  return errors;
}

Нормализация данных в схемах

Схемы часто совмещают валидацию и преобразование данных:

const schema = {
  email: (v) => validator.normalizeEmail(v),
  username: (v) => validator.trim(v)
};

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

Переиспользуемые схемы

Для масштабируемых приложений схемы выносятся в отдельные модули и комбинируются:

const baseUserSchema = {
  email: (v) => validator.isEmail(v)
};

const extendedUserSchema = {
  ...baseUserSchema,
  age: (v) => validator.isInt(v, { min: 0 })
};

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

Динамические схемы

В некоторых случаях схема формируется во время выполнения:

function createSchema(requiredFields) {
  const schema = {};

  requiredFields.forEach(field => {
    schema[field] = (v) => !validator.isEmpty(v);
  });

  return schema;
}

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

Ошибки и детализация результатов

Схемы часто расширяются системой кодов ошибок:

const schema = {
  email: (v) =>
    validator.isEmail(v) ? null : 'INVALID_EMAIL'
};

Результат валидации становится структурированным:

{
  email: 'INVALID_EMAIL'
}

Это упрощает интеграцию с фронтенд-логикой и системами локализации.

Масштабирование схем

При росте приложения схемы начинают делиться на слои:

  • базовые примитивные проверки
  • доменные схемы сущностей
  • схемы API-запросов
  • схемы представления данных

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