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

ts.validator.fluent

v1.3.0

Published

TypeScript based generic, fluent validation framework library.

Downloads

680

Readme

ts.validator.fluent

TypeScript based generic validation framework library

NPM package

Demo Angular 6 CLI app using the framework library

| Rules | Description | | ------------ | ------------------------------------------------------------------------------ | | If | Used for program flow. The then part is only evaluated if the if part is true. | | ForEach | Used to iterate and apply validations to an array. | | ForStringProperty | Used to stack multiple validations against a single String property. | | ForDateProperty | Used to stack multiple validations against a single Date property. | | ForNumberProperty | Used to stack multiple validations against a single Number property. | | For (deprecated) | Used to stack multiple validations against a single property. | | ForType | Used to chain validation rules for a type against a single property. | | Required | Used to test if a property is true to a conditon. | | NotNull | Used to test if a property is not null. | | IsNull | Used to test if a property is null. | | ToResult | Returns the validation result. |

| String Rules | Description | | ------------ | --------------------------------------------------------------------- | | NotEmpty | Used to test if a string is not empty. | | IsEmpty | Used to test if a string is empty. | | Length | Used to test if a string length is between specified lengths. | | Matches | Used to test if a string matches a regular expression. | | NotMatches | Used to test if a string does not match a regular expression. | | Email | Used to test if a string is a valid email address. | | IsCreditCard | Used to test if a string is a valid credit card number. | | IsLowercase | Used to test if a string is lower case. | | IsUppercase | Used to test if a string is upper case. | | IsMixedcase | Used to test if a string is mixed case. | | IsNumeric | Used to test if a string is numeric. | | IsAlpha | Used to test if a string is alpha. | | IsAlphaNumeric | Used to test if a string is alpha numeric. | | IsGuid | Used to test if a string is guid/uuid. | | IsBase64 | Used to test if a string is base64. | | IsUrl | Used to test if a string is an url. | | IsCountryCode | Used to test if a string is a 2 letter country code. | | Contains | Used to test if a sub string is contained in the string. |

| Date Rules | Description | | ------------ | ------------------------------------------------------------------ | | IsDateOn | Used to test if a date is on the specified date. | | IsDateAfter | Used to test if a date is after the specified date. | | IsDateOnOrAfter | Used to test if a date is on or after the specified date. | | IsDateBefore | Used to test if a date is before the specified date. | | IsDateOnOrBefore | Used to test if a date is on or before the specified date. | | IsDateBetween | Used to test if a date is between two specified dates. | | IsDateLeapYear | Used to test if a date is in a leap year. |

| Number Rules | Description | | ------------ | ------------------------------------------------------------------ | | IsNumberEqual | Used to test if a number is equal to a specified number. | | IsNumberNotEqual | Used to test if a number is not equal to a specified number. | | IsNumberLessThan | Used to test if a number is less than a specified number. | | IsNumberLessThanOrEqual | Used to test if a number is less than or equal to a specified number. | | IsNumberGreaterThan | Used to test if a number is greater than a specified number. | | IsNumberGreaterThanOrEqual | Used to test if a number is greater than or equal to a specified number. | | CreditCard | Used to test if a number is a valid credit card number. |

  • These rules are used to lay the validation rules for any model.
  • These rules can be chained in a fluent manner.
  • These rules are available via IValidator<T> interface the framework provides.

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 = "[email protected]";

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

  • The models are Employee, Credit Card, Super.
  • The Employee model has CreditCard and Super as the child models.
  • The rules for Super, CreditCard and Employee validation are laid in the validateSuperRules, validateCreditCardRules and validateEmployeeRules functions, using the IValidator<T> interface the framework provides.
  • The Super and CreditCard rules are chained and used in the Employee validation.
  • The rules are the same for both Sync and Async.
  • For Sync and Async validation, the Validate and ValidateAsync methods on the framework class Validator are used.
  • The Employee object is passed to this class and goes through the validation rules laid.
  • Each validation rule comprises of a property on which the validation will apply, a message for any error and an identifier string for the error.
  • The identifier string is used to group messages together for a field.
  • The framework provides an API called IdentifierStartsWith which fetches all the validation errors for a particular identifier starts with the text.
  • Eg. "Employee.Password" will fetch all errors whose identifier starts with Employee.Password.

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 = "[email protected]";

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

  • The Accountant model inherits from Employee.
  • The validation rules for Accountant model (validateAccountantRules) only validate the properties of the Accountant class.
  • The base class Employee is validated using ValidateBase and ValidateBaseAsync methods and the Employee validation rules.