Home

Awesome

ts.validator.fluent

TypeScript based generic validation framework library

NPM package

npm

Demo Angular 6 CLI app using the framework library

RulesDescription
IfUsed for program flow. The then part is only evaluated if the if part is true.
ForEachUsed to iterate and apply validations to an array.
ForStringPropertyUsed to stack multiple validations against a single String property.
ForDatePropertyUsed to stack multiple validations against a single Date property.
ForNumberPropertyUsed to stack multiple validations against a single Number property.
For (deprecated)Used to stack multiple validations against a single property.
ForTypeUsed to chain validation rules for a type against a single property.
RequiredUsed to test if a property is true to a conditon.
NotNullUsed to test if a property is not null.
IsNullUsed to test if a property is null.
ToResultReturns the validation result.
String RulesDescription
NotEmptyUsed to test if a string is not empty.
IsEmptyUsed to test if a string is empty.
LengthUsed to test if a string length is between specified lengths.
MatchesUsed to test if a string matches a regular expression.
NotMatchesUsed to test if a string does not match a regular expression.
EmailUsed to test if a string is a valid email address.
IsCreditCardUsed to test if a string is a valid credit card number.
IsLowercaseUsed to test if a string is lower case.
IsUppercaseUsed to test if a string is upper case.
IsMixedcaseUsed to test if a string is mixed case.
IsNumericUsed to test if a string is numeric.
IsAlphaUsed to test if a string is alpha.
IsAlphaNumericUsed to test if a string is alpha numeric.
IsGuidUsed to test if a string is guid/uuid.
IsBase64Used to test if a string is base64.
IsUrlUsed to test if a string is an url.
IsCountryCodeUsed to test if a string is a 2 letter country code.
ContainsUsed to test if a sub string is contained in the string.
Date RulesDescription
IsDateOnUsed to test if a date is on the specified date.
IsDateAfterUsed to test if a date is after the specified date.
IsDateOnOrAfterUsed to test if a date is on or after the specified date.
IsDateBeforeUsed to test if a date is before the specified date.
IsDateOnOrBeforeUsed to test if a date is on or before the specified date.
IsDateBetweenUsed to test if a date is between two specified dates.
IsDateLeapYearUsed to test if a date is in a leap year.
Number RulesDescription
IsNumberEqualUsed to test if a number is equal to a specified number.
IsNumberNotEqualUsed to test if a number is not equal to a specified number.
IsNumberLessThanUsed to test if a number is less than a specified number.
IsNumberLessThanOrEqualUsed to test if a number is less than or equal to a specified number.
IsNumberGreaterThanUsed to test if a number is greater than a specified number.
IsNumberGreaterThanOrEqualUsed to test if a number is greater than or equal to a specified number.
CreditCardUsed to test if a number is a valid credit card number.

Sample usage:

Models

    class Employee {
        Name: string;
        Password: string;
        PreviousPasswords: string[];
        CreditCards: CreditCard[];
        Super: Super;
        Email: string;
    }

    class CreditCard {
        Number: string;
        Name: string;
        ExpiryDate: Date;
    }
 
    class Super {
        Name: string;
        Code: string;
    }

Validation rules

/* Install npm package ts.validator.fluent and then import like below */
import { IValidator, Validator, ValidationResult } from 'ts.validator.fluent/dist';
 let validateSuperRules =  (validator: IValidator<Super>) : ValidationResult => {
   return validator
            .NotNull(m => m.Name, "Should not be null", "Super.Name.Null")
            .NotNull(m => m.Code, "Should not be null", "Super.Code.Null")
            .If(m => m.Name != null && m.Code != null, validator => validator 
                                                    .NotEmpty(m => m.Name, "Should not be empty", "Super.Name.Empty")
                                                    .Matches(m => m.Code, "^[a-zA-Z]{2}\\d{4}$", "Should not be invalid", "Super.Code.Invalid")
                                                .ToResult())
         .ToResult();
 };
 let validateCreditCardRules =  (validator: IValidator<CreditCard>) : ValidationResult => {  
  return validator
            .NotNull(m => m.Name, "Should not be null", "CreditCard.Name.Null")
            .NotNull(m => m.Number, "Should not be null", "CreditCard.Number.Null")
            .NotNull(m => m.ExpiryDate, "Should not be null", "CreditCard.ExpiryDate.Null")
            .If(m => m.Name != null && m.ExpiryDate != null, validator => validator 
                                                        .NotEmpty(m => m.Name, "Should not be empty", "CreditCard.Name.Empty")
                                                        .IsCreditCard(m => m.Number, "Should not be invalid", "CreditCard.Number.Invalid")
                                                        .IsDateOnOrAfter(m => m.ExpiryDate, new Date(), "Should be on or after today's date", "CreditCard.ExpiryDate.Invalid")
                                                    .ToResult())
        .ToResult();
 };
 let validateEmployeeRules = (validator: IValidator<Employee>) : ValidationResult => {
    return validator                              
          .NotEmpty(m => m.Name, "Should not be empty", "Employee.Name.Empty")
          .NotNull(m => m.CreditCards, "Should not be null", "CreditCard.Null")
          .NotNull(m => m.Super, "Should not be null", "Super.Null")
          .NotEmpty(m => m.Email, "Should not be empty", "Employee.Email.Empty")
          .If(m => m.Super != null, validator => validator.ForType(m => m.Super, validateSuperRules).ToResult())
          .If(m => m.Email != '', validator => 
                                              validator.Email(m => m.Email, "Should not be invalid", "Employee.Email.Invalid")
                                  .ToResult())  
          .Required(m => m.CreditCards, (m, creditCards) => creditCards.length > 0, "Must have atleast 1 credit card", "Employee.CreditCards.Required")
          .If(m => m.CreditCards != null && m.CreditCards.length > 0, 
                      validator => validator
                                    .ForEach(m => m.CreditCards, validateCreditCardRules)
                            .ToResult())
          .If(m => m.Password != '', validator => validator
                                    .ForStringProperty(m => m.Password, passwordValidator => passwordValidator
                                            .Matches("(?=.*?[0-9])(?=.*?[a-z])(?=.*?[A-Z])", "Password strength is not valid", "Employee.Password.Strength")
                                            .Required((m, pwd) => pwd.length > 3, "Password length should be greater than 3", "Employee.Password.Length")
                                            .Required((m, pwd) => !m.PreviousPasswords.some(prevPwd => prevPwd == pwd), "Password is already used", "Employee.Password.AlreadyUsed")
                                        .ToResult())
                                .ToResult())                                                                                                                    
    .ToResult();
 };

Populate models

    let model = new Employee();
    model.Name = "John Doe";

    model.Password = "sD4A3";
    model.PreviousPasswords = new Array<string>()     
    model.PreviousPasswords.push("sD4A");
    model.PreviousPasswords.push("sD4A1");
    model.PreviousPasswords.push("sD4A2");

    var expiryDate = new Date();

    model.CreditCards = new Array<CreditCard>();
    var masterCard = new CreditCard();
    masterCard.Number = "5105105105105100";
    masterCard.Name = "John Doe"
    masterCard.ExpiryDate = expiryDate;
    var amexCard = new CreditCard();
    amexCard.Number = "371449635398431";
    amexCard.Name = "John Doe"
    amexCard.ExpiryDate = expiryDate;
    model.CreditCards.push(masterCard);
    model.CreditCards.push(amexCard);

    model.Super = new Super();
    model.Super.Name = "XYZ Super Fund";
    model.Super.Code = "XY1234";

    model.Email = "john.doe@xyx.com";

Synchronous validation

    let validationResult = new Validator(model).Validate(validateEmployeeRules);   

Asynchronous validation

    let validationResult = await new Validator(model).ValidateAsync(validateEmployeeRules);

Validation result

    //Check if the model is valid.
    let isValid = validationResult.IsValid;

    //Get all errors.
    let allErrors = validationResult.Errors;

    //Get error for a particular identifier
    let employeeNameError = validationResult.Identifier("Employee.Name.Empty");

    //Get all errors which start with some identifier string. 
    //Below code will return Employee.Password.Strength and Employee.Password.Length and 
    //Employee.Password.AlreadyUsed errors
    let superCodeErrors = validationResult.IdentifierStartsWith("Employee.Password");

Summary of above code snippets

Inheritance support

Let us say there is a class Accountant that inherits from Employee.

Models

 class Accountant extends Employee {
   Code: string;
 }

Validation rules

let validateAccountantRules = (validator: IValidator<Accountant>) : ValidationResult => {
  return validator
            .NotEmpty(m => m.Code, "Should not be empty")
        .ToResult();
};

Populate models

    let accountant = new Accountant();
    accountant.Code = "ACC001";

    //Employee data
    accountant.Name = "John Doe";

    accountant.Password = "sD4A3";
    accountant.PreviousPasswords = new Array<string>()     
    accountant.PreviousPasswords.push("sD4A");
    accountant.PreviousPasswords.push("sD4A1");
    accountant.PreviousPasswords.push("sD4A2");

    var expiryDate = new Date();

    accountant.CreditCards = new Array<CreditCard>();
    var masterCard = new CreditCard();
    masterCard.Number = "5105105105105100";
    masterCard.Name = "John Doe"
    masterCard.ExpiryDate = expiryDate;
    var amexCard = new CreditCard();
    amexCard.Number = "371449635398431";
    amexCard.Name = "John Doe";
    amexCard.ExpiryDate = expiryDate;
    accountant.CreditCards.push(masterCard);
    accountant.CreditCards.push(amexCard);

    accountant.Super = new Super();
    accountant.Super.Name = "XYZ Super Fund";
    accountant.Super.Code = "XY1234";

    accountant.Email = "john.doe@xyx.com";

Synchronous validation

    let validationResult = new Validator(accountant).ValidateBase(validateEmployeeRules)
                                                    .Validate(validateAccountantRules); 

Asynchronous validation

    let validationResult = await new Validator(accountant).ValidateBaseAsync(validateEmployeeRules)
                                                          .ValidateAsync(validateAccountantRules); 

Summary of above code snippets