npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

meta-validate

v2.2.3

Published

TypeScript validation utils

Downloads

48

Readme

meta-validate

Декораторы для валидации классов.

Общие принципы:

1 - валидаторы складываются в цепочку.

Цепочка всегда начинается с @MetaValidate. и заканчивается на .make()

2 - ошибки складываются в объект следующего вида:

{
    errors: {
        %ПОЛЕ%: {
            %КЛЮЧ_ОШИБКИ_1%: boolean,
            %КЛЮЧ_ОШИБКИ_2%: boolean,
        },
        %ПОЛЕ_КОМПОЗИЦИЯ%: {
            %ПОЛЕ_КЛАССА_КОМПОЗИЦИИ_1%: {
                %КЛЮЧ_ОШИБКИ_1%: boolean
                ...
            }
        }
    }
}

3 - есть пренастроенные классы валидаторов и можно будет регистрировать свои(скоро)

Это значит, что сам по себе @MetaValidate просто хранилище всяких классов с валидаторами. Сейчас их несколько:

  • Number<T> - класс с частыми валидаторами чисел
  • String<T> - класс с частыми валидаторами строк
  • Trigger - класс-триггер, нужен для связывания полей
  • Nested - класс, обозначающий что поле содержит сложный экземпляр, который тоже умеет валидироваться
  • Base - класс с базовыми методами, предполагающий использование только кастомных валидаторов Дженерики принимают класс, поля которого вы валидируете.

4 - ваши классы должны реализовывать интерфейс ReceiveValidity

В вашем классе обязательно должно быть поле validity$: Subject<Validity>, в который будут валиться ошибки.

5 - семантика валидаторов.

Валидаторы возвращают false, если значение валидно. true - если есть ошибка. Т.е. валидатор отвечает на вопрос - есть-ли ошибка?

Это сделано для того, чтобы использовать объект с ошибками в шаблонах без всяких плясок вокруг ng-if. Пишем <span class="error" ng-if="validity.field.min">Ошибочка min, маловато ввели</span>

6 - преднастроенные валидаторы умеют принимать как значение, так и функцию от экземпляра

7 - валидаторы запускаются на каждый чих над полем или связанными полями

Базовое использование

Пример

class Foo {
    validity$: BehaviorSubject<Validity> = new BehaviorSubject();

    @MetaValidate.MVString<Foo>().required().make()
    bar: number = null;
}

Здесь

  • @MetaValidate - тот самый базовый декоратор
  • MVString - один из преднастроенных классов с валидаторами
  • .make() - метод, делающий декорацию

Базовый класс валидаторов и его методы

Базовый класс валидаторов - от него наследуются все конкретные классы с валидаторами.

Содержит общие методы, которые нужны всем.

Список методов

  • required() - делает поле обязательным к проверке. Ключ ошибки: required
  • skipIf(condition: (instance) => boolean) - метод, который можно повесить после валидатора, он запустит переданную функцию-условие с экземпляром вашего класса в качестве аргумента, и в зависимости от этого запустит или нет валидатор для предыдущего поля. В случае, если функция-условие вернет true - валидатор не будет запущен, ошибка будет false для него.
  • skip(condition: (instance) => boolean) - метод, который обычно стоит вешать первым в цепочке, по условию определяет - запускать все валидаторы на поле или игнорировать его. В случае, если функция-условие вернет true - ни один валидатор для поля не будет запущен, во всех ключах ошибок будет false.
  • with(fields: Array<string>) - список полей, с изменением которых будут вызваны проверки данного поля. Эти зависимые поля должны быть либо так же валидируемы, либо если они не требуют специальной валидации - декорированы специальным классом Trigger
  • custom(name: string, validator: (value: any, instance: any) => boolean) - кастомный валидатор, который можно повесть на поле. Обязательно должен возвращать boolean, в любом случае.
  • make() - конечный метод цепочки, декорирует свойство

Класс String

Использование

@MetaValidate.String<T>()...make()
field: string = null;

Валидаторы:

  • minLength(len: number | (instance) => number) - минимальная длина значения должна быть len. Ключ ошибки - minLength
  • maxLength(len: number | (instance) => number) - максимальная длина значения должна быть len. Ключ ошибки - maxLength
  • length(len: number | (instance) => number) - Длина значения должна быть строго len. Ключ ошибки - length
  • regex(pattern: RegExp | (instance) => RegExp, name) - Значение должно соответствовать регулярке. Рекомендуется не забывать в регулярке ^$. Ключ ошибки - переданный name
  • alphanum - Поле должно содержать только цифры и буквы. Ключ ошибки - alphanum
  • token - Поле должно содержать только цифры, буквы, тире и подчеркивание. Ключ ошибки - token

Класс Number

Использование

@MetaValidate.Number<T>()...make()

Преднастроенные валидаторы пытаются привести значение к числу. Т.е. например ng-model инпута может быть забито на поле с этими валидаторами, и они будут приовдить значение к числу. Но только для проверки. Приведение для хранения - пока ваша задача. Скоро будет метод convert в цепочке валидаторов, он будет отвечать за приведение

Валидаторы:

  • min(len: number | (instance) => number) - число должно быть строго больше переданного значения
  • greater(len: number | (instance) => number) - число должно быть больше или равно переданного значения
  • max(len: number | (instance) => number) - число должно быть строго меньше переданныого значения
  • less(len: number | (instance) => number) - число должно быть меньше или равно переданного значения
  • integer() - число должно быть без знаков после запятой
  • negative() - число должно быть отрицательным
  • positive() - число должно быть положительным
  • divideBy(arg: number | (instance) => number) - число делится на переданный аргумент

Объект с ошибками Validity

Вид объекта представлен выше в документации. У него есть дополнительный метод .isFullValid(ignoreFields: Array<string>) - вернет true, если все поля валидны. Исключает поля из списка ignoreFields. Они могут быть вложенными, например: document.number

###Пример использования

import { MetaValidate, ReceiveValidity, Validity } from 'meta-validate';

class Document implements ReceiveValidity {
    validity$: BehaviorSubject<Validity> = new BehaviorSubject(null);

    @MetaValidate.Trigger().make()
    docType: string = null;

    @MetaValidate.String<Document>()
    .with(['docType'])
    .required().skipIf(instance => instance.docType === 'dumb')
    .alphanum()
    .custom('length', (value, instance) => instance.docType === 'pass_rf' ? !value || value.length !== 4 : !value || value.length === 0)
    .make()
    docNumber: string = null;

    @MetaValidate.String<Document>()
    .with(['docType'])
    .required()
    .minLength(2)
    .maxLength(4)
    .make()
    docSeries: string = null;

    @MetaValidate.String<Document>()
    .skip(instance => instance.docType !== 'zagranpasport')
    .length(9)
    .make()
    additionalDocumentNumber: string = null;
}

class Customer implements ReceiveValidity {
    validity$: BehaviorSubject<Validity> = new BehaviorSubject();

    @MetaValidate.Nested().make()
    document: Document = new Document();

    @MetaValidate.String<Customer>().required().make()
    name: string = null;
}

Объект ошибок будет следующим:

customerErrors = {
    errors: {
        document: {
            docNumber: {
                required: true,
                alphanum: true,
                length: true
            },
            docSeried: {
                required: true,
                minLength: true,
                maxLength: true
            },
            additionalDocumentNumber: {
                length: true
            }
        }
        name: {
            required: true
        }
    }
}

Пользоваться следующим образом:

const customer = new Customer();
customer.validity$.subscribe((validity: Validity) => {
    this.errors = validity.errors;
    this.isFullValid = validity.isFullValid();
});