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

Библиотека Validator.js предоставляет широкий набор предопределённых функций для проверки строковых значений: email, URL, длина, числовые диапазоны, форматы дат и множество других сценариев. Однако прикладные задачи редко ограничиваются стандартным набором правил. В реальных системах возникает необходимость в создании собственных проверок, учитывающих бизнес-логику, структуру данных и доменные ограничения.

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

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

Основой кастомной проверки является функция, принимающая значение и возвращающая результат логической проверки. В простейшем виде она строится следующим образом:

function isValidPostalCode(value) {
  return /^[0-9]{6}$/.test(value);
}

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

import validator from 'validator';

function isCorporateEmail(email) {
  if (!validator.isEmail(email)) {
    return false;
  }

  return email.endsWith('@company.com');
}

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

Композиция проверок как основной механизм расширения

Кастомные методы редко существуют изолированно. Чаще они представляют собой композицию нескольких правил, объединённых логикой AND или OR.

function isStrongUsername(username) {
  return (
    validator.isLength(username, { min: 6, max: 20 }) &&
    /^[a-zA-Z0-9_]+$/.test(username) &&
    !username.includes('admin')
  );
}

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

Абстрагирование кастомных правил в переиспользуемые модули

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

// validators/userValidators.js

import validator from 'validator';

export function isValidLogin(login) {
  return validator.isAlphanumeric(login) && validator.isLength(login, { min: 4, max: 16 });
}

export function isValidPassword(password) {
  return (
    validator.isLength(password, { min: 8 }) &&
    /[A-Z]/.test(password) &&
    /[0-9]/.test(password)
  );
}

Такой подход упрощает сопровождение кода и снижает дублирование логики.

Интеграция кастомных методов в цепочки валидации

В системах, использующих цепочки вызовов (например, при построении middleware-валидации), кастомные методы подключаются как часть общего потока.

function validateUser(data) {
  const errors = [];

  if (!isValidLogin(data.login)) {
    errors.push('Некорректный логин');
  }

  if (!isValidPassword(data.password)) {
    errors.push('Слабый пароль');
  }

  return errors;
}

Здесь кастомные функции выступают как строительные блоки более сложной логики проверки.

Расширение поведения через функции-обёртки

Иногда требуется не просто новая проверка, а модификация поведения существующих методов Validator.js. В таких случаях создаются обёртки:

function isRequiredEmail(value) {
  return value && validator.isEmail(value);
}

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

Более гибкий вариант предполагает параметризацию:

function isEmailDomain(email, domain) {
  return validator.isEmail(email) && email.endsWith(`@${domain}`);
}

Универсальные фабрики валидаторов

При масштабировании системы проверки часто превращаются в конфигурируемые фабрики:

function createLengthValidator(min, max) {
  return function (value) {
    return validator.isLength(value, { min, max });
  };
}

const isUsernameValid = createLengthValidator(5, 15);
const isTagValid = createLengthValidator(1, 10);

Фабричный подход снижает дублирование и делает правила декларативными.

Работа с составными структурами данных

Кастомные методы часто применяются не только к строкам, но и к объектам данных, где каждая проверка отвечает за отдельное поле:

function validateProfile(profile) {
  return (
    validator.isLength(profile.name, { min: 2 }) &&
    validator.isEmail(profile.email) &&
    typeof profile.age === 'number' &&
    profile.age >= 18
  );
}

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

Расширение через пользовательские словари и наборы правил

В сложных системах кастомные методы группируются в наборы правил, отражающих бизнес-области:

const paymentValidators = {
  isValidCardNumber(value) {
    return validator.isCreditCard(value);
  },

  isValidAmount(value) {
    return validator.isFloat(value, { min: 0.01 });
  }
};

Это позволяет логически разделять ответственность между модулями.

Асинхронные кастомные проверки

Некоторые сценарии требуют обращения к внешним источникам данных. В таких случаях кастомный метод становится асинхронным:

async function isUniqueEmail(email, db) {
  const user = await db.findUserByEmail(email);
  return !user;
}

Асинхронные проверки особенно важны при работе с базами данных, где необходимо гарантировать уникальность значений.

Обработка ошибок и единый формат результатов

Для масштабируемости важно стандартизировать возвращаемые значения кастомных методов. Вместо простого boolean часто используется структура результата:

function validateAge(age) {
  if (!validator.isInt(age.toString())) {
    return { valid: false, error: 'Возраст должен быть числом' };
  }

  if (age < 18) {
    return { valid: false, error: 'Минимальный возраст 18 лет' };
  }

  return { valid: true };
}

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

Сложные условия и контекстная валидация

Кастомные методы могут учитывать внешний контекст:

function isValidDiscount(price, discount, userType) {
  if (userType === 'premium') {
    return discount <= price * 0.5;
  }

  return discount <= price * 0.2;
}

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

Структурирование библиотеки кастомных валидаторов

При росте проекта кастомные методы объединяются в архитектурно выверенную структуру:

  • базовые проверки (строки, числа, даты)
  • доменные проверки (пользователи, платежи, товары)
  • составные правила (бизнес-логика)
  • асинхронные проверки (БД, API)

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