Изменения в API

Validator.js — популярная библиотека для валидации и санитизации строковых данных в JavaScript и Node.js. За время развития библиотеки API неоднократно изменялся: часть методов переименовывалась, некоторые функции объявлялись устаревшими, менялись сигнатуры вызовов и структура импорта.

Изменения API особенно важны в следующих сценариях:

  • миграция между версиями;
  • обновление зависимостей в крупных проектах;
  • совместимость CommonJS и ES Modules;
  • изменение поведения валидаторов;
  • переход на tree-shaking и модульные сборки;
  • обновление TypeScript-типов.

Эволюция способов подключения библиотеки

Старый подход CommonJS

Ранние версии библиотеки ориентировались преимущественно на Node.js и CommonJS.

const validator = require('validator');

validator.isEmail('admin@example.com');

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


Современный импорт через ES Modules

С развитием экосистемы JavaScript библиотека начала активно поддерживать ESM.

import validator from 'validator';

validator.isEmail('admin@example.com');

Также появилась возможность импортировать отдельные методы.

import isEmail from 'validator/lib/isEmail';

isEmail('admin@example.com');

Переход к модульной архитектуре

Причины изменений

Ранние версии библиотеки экспортировали единый объект со всеми методами:

validator.isEmail(...)
validator.isURL(...)
validator.isUUID(...)

Недостатки такого подхода:

  • увеличение размера bundle;
  • невозможность эффективного tree-shaking;
  • подключение неиспользуемых функций;
  • ухудшение производительности фронтенд-сборок.

Новая стратегия импорта

Современные версии позволяют импортировать только конкретные валидаторы.

import isURL from 'validator/lib/isURL';
import isJSON from 'validator/lib/isJSON';

Преимущества:

  • уменьшение размера сборки;
  • ускорение загрузки;
  • оптимизация frontend-приложений;
  • более эффективная работа bundlers.

Изменения структуры путей импорта

Устаревшие пути

В старых версиях встречались конструкции:

import isEmail from 'validator/es/lib/isEmail';

или:

import isEmail from 'validator/lib/isEmail.js';

Позднее часть путей была унифицирована.


Современный рекомендуемый вариант

import isEmail from 'validator/lib/isEmail';

Изменение структуры путей стало важным при миграции между major-версиями.


Изменения поведения валидаторов

Изменения в isEmail

Метод isEmail() постепенно получал новые параметры и более строгие правила проверки.


Старое поведение

Ранее некоторые невалидные email-адреса проходили проверку.

validator.isEmail('test@test');

В отдельных версиях результат мог отличаться.


Современное поведение

Теперь проверка стала значительно строже.

validator.isEmail('admin@example.com');

Дополнительно поддерживаются настройки:

validator.isEmail('admin@example.com', {
  allow_display_name: true,
  require_tld: true
});

Новые параметры isEmail

Параметр Назначение
allow_display_name Разрешает формат "John <john@mail.com>"
require_tld Требует наличие доменной зоны
allow_utf8_local_part Поддержка UTF-8
allow_ip_domain Разрешает IP вместо домена
domain_specific_validation Дополнительные проверки популярных доменов

Изменения в isURL

Старые версии

Метод имел ограниченный набор опций.

validator.isURL(url);

Современные версии

Появилось множество параметров конфигурации.

validator.isURL(url, {
  protocols: ['http', 'https'],
  require_protocol: true,
  require_host: true,
  require_port: false
});

Расширение возможностей URL-валидации

Современный API поддерживает:

  • проверку протоколов;
  • whitelist и blacklist хостов;
  • валидацию портов;
  • работу с query string;
  • IPv6;
  • Unicode-домены.

Изменения в UUID-валидации

Старый API

validator.isUUID(value);

Проверка выполнялась без указания версии UUID.


Новый API

validator.isUUID(value, 4);

или:

validator.isUUID(value, '4');

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • all

Изменения в isDate

Старый вариант

validator.isDate('2023-10-01');

Новый вариант

validator.isDate('2023-10-01', {
  format: 'YYYY-MM-DD',
  strictMode: true
});

Причины изменений

Проблемы старого API:

  • неоднозначная интерпретация дат;
  • зависимость от локали;
  • различия между браузерами;
  • нестабильность Date.parse().

Новый API сделал поведение более предсказуемым.


Появление строгих режимов

Многие валидаторы получили параметр строгой проверки.

Пример:

validator.isNumeric('123');
validator.isNumeric('123', {
  no_symbols: true
});

Изменения санитайзеров

Устаревшие методы

Некоторые методы санитизации были признаны небезопасными.

Например:

validator.toString(value);

Поведение могло быть неоднозначным для null и undefined.


Современные рекомендации

Использование явного преобразования:

String(value);

или:

value?.toString();

Удаление устаревших методов

Некоторые функции были полностью удалены из API.


Пример deprecated-функций

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

  • toDate()
  • toFloat()
  • toInt()
  • часть внутренних helper-функций

Причины:

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

Изменения TypeScript-поддержки

Старые версии

Типы часто подключались отдельно.

npm install @types/validator

Современные версии

Библиотека включает встроенные типы.

import isEmail from 'validator/lib/isEmail';

const result: boolean = isEmail('admin@example.com');

Изменения сигнатур функций

Старый стиль

Многие методы принимали ограниченный набор аргументов.

validator.isLength(str, 5);

Новый стиль

Используется объект конфигурации.

validator.isLength(str, {
  min: 5,
  max: 20
});

Преимущества объектной конфигурации

  • лучшая читаемость;
  • расширяемость API;
  • обратная совместимость;
  • уменьшение количества positional arguments.

Изменения в isLength

Ранние версии

validator.isLength(str, 5, 10);

Современный API

validator.isLength(str, {
  min: 5,
  max: 10
});

Изменения обработки Unicode

Старые ограничения

Ранние версии плохо работали с Unicode.

Проблемы:

  • кириллица;
  • emoji;
  • surrogate pairs;
  • UTF-16 символы.

Современная поддержка Unicode

Современные версии корректнее работают с:

validator.isAlpha('Привет', 'ru-RU');
validator.isAlphanumeric('東京', 'ja-JP');

Расширение локалей

API постепенно получил поддержку большого количества локалей.

Примеры:

validator.isMobilePhone(phone, 'ru-RU');
validator.isPostalCode(code, 'DE');

Изменения в isMobilePhone

Старое поведение

Поддержка стран была ограниченной.


Современное поведение

Поддерживаются десятки регионов.

validator.isMobilePhone('+77001234567', 'kk-KZ');

Также появилась возможность:

validator.isMobilePhone(phone, 'any');

Изменения безопасности API

Усиление проверок

Многие изменения API были связаны с безопасностью:

  • защита от ReDoS;
  • ограничение сложных регулярных выражений;
  • улучшение обработки URL;
  • корректная работа с Unicode.

Изменения sanitize-функций

Некоторые методы были переработаны для предотвращения:

  • XSS;
  • injection-атак;
  • некорректного экранирования.

Изменения поведения escape

Старый API

validator.escape('<script>');

Современное поведение

Функция стала лучше учитывать HTML entities.

validator.escape('<div>Hello</div>');

Результат:

&lt;div&gt;Hello&lt;/div&gt;

Изменения совместимости с Node.js

Старые версии

Поддерживались очень старые версии Node.js.


Современные версии

Поддержка legacy-сред постепенно удалялась.

Причины:

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

Breaking Changes в major-релизах

Типичные breaking changes

Изменение Последствие
Изменение сигнатуры Старый код перестаёт работать
Удаление методов Ошибки импорта
Изменение default behavior Некорректная логика
Более строгая валидация Ранее валидные данные становятся невалидными
Изменение путей импорта Ошибки bundler

Стратегии миграции

Фиксация версии

Перед обновлением рекомендуется фиксировать текущую версию.

{
  "dependencies": {
    "validator": "13.11.0"
  }
}

Изучение changelog

При переходе между major-версиями необходимо анализировать:

  • breaking changes;
  • deprecated API;
  • изменения импортов;
  • изменения TypeScript-типов.

Постепенная миграция

Крупные проекты часто используют промежуточные этапы:

  1. обновление minor-версий;
  2. исправление warning;
  3. удаление deprecated-кода;
  4. переход на новый API;
  5. обновление major-версии.

Изменения в работе с null и undefined

Старое поведение

Некоторые методы автоматически приводили значения к строке.

validator.isEmpty(null);

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


Современные рекомендации

Явная проверка типов:

if (typeof value === 'string') {
  validator.isEmpty(value);
}

Изменения философии API

Современный Validator.js постепенно сместился в сторону:

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

Проблемы обратной совместимости

Наиболее частые ошибки после обновления:

Ошибки импортов

Cannot find module 'validator/lib/isEmail'

Изменения поведения валидаторов

validator.isURL('example.com');

После обновления строка может считаться невалидной без протокола.


Изменения типов

TypeScript может начать выдавать ошибки:

Argument of type 'null' is not assignable

Практика адаптации legacy-кода

Старый код

validator.isLength(name, 3, 20);

Новый код

validator.isLength(name, {
  min: 3,
  max: 20
});

Старый импорт

const validator = require('validator');

Современный импорт

import validator from 'validator';

Рекомендации по работе с API Validator.js

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

import isEmail from 'validator/lib/isEmail';

Избегание deprecated-методов

Следует регулярно проверять changelog библиотеки.


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

Лучше избегать reliance на default behavior.

validator.isURL(url, {
  require_protocol: true
});

Проверка breaking changes

Особенно важна при обновлении:

  • CI/CD;
  • backend API;
  • frontend forms;
  • TypeScript-проектов;
  • SSR-приложений.