JSPM

lakmus-michaelmyers

0.3.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q29472F
  • License MIT

Fluent validation.

Package Exports

  • lakmus-michaelmyers

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (lakmus-michaelmyers) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Lakmus

Fluent validation in TypeScript.

Features

  • 20+ built-in validators
  • Refactoring-friendly (generic property selectors)
  • Multilanguage

Inspired by .NET FluentValidation

Demo

export class Person {
    public id: number;
    public name: string;
    public address: Address;
    public phoneNumbers: PhoneNumber[];
    public hasDiscount: boolean;
    public discountValue: number;
}

export class Address {
    public country: string;
    public city: string;
    public street: string;
    public houseNumber: string;
}

export class PhoneNumber {
    public country: string;
    public code: string;
    public number: string;
}

export class PersonValidator extends Validator<Person> {
    constructor() {
        super();

        // not null & max length;
        this.ruleFor(x => x.name)
            .notNull()
            .maxLength(100);

        // nested objection validation;
        this.ruleFor(x => x.address)
            .notNull()
            .setValidator(new AddressValidator());

        // collection validation;
        this.ruleFor(x => x.phoneNumbers)
            .notNull()
            .setCollectionValidator(new PhoneNumberValidator());

        this.when(x => x.hasDiscount, () => {
            this.ruleFor(x => x.discountValue)
                .notNull();
        });
    }
}

export class AddressValidator extends Validator<Address> {
    constructor() {
        super();

        this.ruleFor(x => x.city)
            .notNull().maxLength(50);

        this.ruleFor(x => x.street)
            .notNull().maxLength(50);
    }
}

export class PhoneNumberValidator extends Validator<PhoneNumber> {
    constructor() {
        super();

        this.ruleFor(x => x.country)
            .notNull().maxLength(3);

        this.ruleFor(x => x.code)
            .notNull().maxLength(5);

        // predicate and custom error message;
        this.ruleFor(x => x.number)
            .notNull().maxLength(7)
            .must((number, phoneNumber) => (phoneNumber.code || "").length + (phoneNumber.country || "").length + (phoneNumber.number || "").length == 11)
            .withMessage("Please enter a valid phone number.");
    }
}

// set custom property name resolver: discountValue -> Discount Value
ValidatorOptions.propertyNameResolver = ApStyleTitleCasePropertyNameResolver;

// initialize object to validate;
var person = new Person();

// create validator;
var validator = new PersonValidator();
// or get it from factory (recommended) 
validator = ValidatorFactory.getValidator(PersonValidator);

// validate;
var result = validator.validate(person);

// process result;
if (result.isValid) {
    console.log("Is valid.");
}
else {
    console.log(result.errors.map(x => x.errorMessage).join("\n"));
}

License

MIT