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

treacherous

v0.17.6

Published

A modern async validation framework with a raft of features for node or the browser.

Downloads

68

Readme

Treacherous

A modern async validation framework with a raft of features for node or the browser.

treacherous-image

Build Status Npm Version Npm Downloads Join Gitter Chat

Treacherous is an attempt to bring some consistency to validation in the javascript world, allowing you to write your validation rules for your models once, and re-use them on any platform with any framework.

Benefits

  • Fully async validation
  • Separation of rules and validation allowing composable rule sets
  • Supports nested complex objects/arrays
  • Outside in validation, does not augment your models in any way
  • Works in browser or server
  • Write once, use anywhere
  • Can be integrated with any view framework (i.e vue, knockout, aurelia etc)
  • Generic pipeline for localization customization

Features

Reactive Validation

Treacherous can optionally watch your model to see if any properties it is validating change and automatically re-validate those fields when changed, even in nested objects or arrays.

Composite Rules / Virtual Properties

Support for validating at property level using normal rules or for creating composite rules which are applied at the model level, allowing you to validate multiple properties within the same context.

Predicate Based Validation

You can specify predicates to only apply certain validation rules when criteria are met allowing your model validity to be contextual and flexible.

Property Alias'

This is mainly for when you are using treacherous within the browser, but you can provide alias' to properties so when errors are reported the property alias is displayed rather than the actual property name, as who wants to see hasConfirmedTermsAndConditions when you could just alias that field as T&Cs.

Full Support for Typescript

The whole of Treacherous was written in typescript and can bring some nice time saving features to typescript users like async/await and lambda style interactions.

Don't worry if you dont use/like typescript, you can still use all of treacherous' features as if it were a native javascript framework.


Installing

Via NPM

Just do an npm install treacherous

In browser

As this is distributed as a commonjs module it is recommended that you consume it via your existing module loader, or in the scenario where you do not have one it is recommended that you use webpack to just package it up as a UMD module to consume with a global name, this may automatically happen when typescript 2.0 provides this functionality for UMD modules out of the box.


Simple Examples

Validating simple models

import {createRuleset, createGroup} from "treacherous";

const simpleModel = {
    foo: 20,
    bar: "hello"
};

const ruleset = createRuleset()
    .forProperty("foo")
        .addRule("required")        // The property is required
        .addRule("maxValue", 20)    // The property needs a value <= 20
    .forProperty("bar")
        .addRule("maxLength", 5)     // The property neds a length <= 5
    .build();
    
const validationGroup = createGroup()
    .build(simpleModel, ruleset);

validationGroup.validate()
    .then((isValid) => {
        console.log(isValid); // should write true
    });

Ruleset Shorthand

const ruleset = createRuleset()
    .forProperty("foo")
        .required()
        .maxValue(20)
    .forProperty("bar")
        .maxLength(5)
    .build()

Validating simple arrays in models

const simpleModel = {
    foo: [10, 20, 30]
};

const ruleset = createRuleset()
    .forProperty("foo")
        .addRule("maxLength", 5)        // The array can only contain <= 5 elements
        .addRuleForEach("maxValue", 20) // Each element needs a value <= 20
    .build();
    
const validationGroup = createGroup().build(simpleModel, ruleset);

validationGroup.getModelErrors(true) // the true value indicates a full revalidation
    .then((errors) => {
        console.log(errors); // should contain { "foo[2]": "<some error about max value>" }
    });

Nested validation on the fly

const complexObject = {
    foo: {
       bar: "hello"
    }
};

const ruleset = createRuleset()
    .forProperty("foo")
    .then(fooBuilder => {
        fooBuilder.forProperty("bar")
            .required()
            .maxLength(2)
    })
    .build();

const validationGroup = createGroup().build(complexObject, ruleset);

validationGroup.getModelErrors(true)
    .then((errors) => {
        console.log(errors); // should contain { "foo.bar": "<some error about max length>" }
    });

Creating Validation Groups

The validation group is the object which manages validation state, you can find out a lot more information on this within the docs.

Here are a few simple examples to save you trawling the docs.

Check current validity

const validationGroup = createGroup()
    .build(...);

validationGroup.validate()
    .then((isValid) => {
        // true is valid, false is invalid
    ));

Get all errors

const validationGroup = createGroup()
    .build(...);

validationGroup.getModelErrors()
    .then((propertyErrors) => {...));

Subscribe validation changes

const validationGroup = createGroup()
    .build(...);

validationGroup.propertyStateChangedEvent.subscribe((propertyValidationChangedEvent) => {...));

Typescript users

As typescript users you can get some nicer features and intellisense so you can create typed rules allowing you to use lambda style property location like so:

const ruleset = createRuleset<SomeModel>()
    .addProperty(x => x.SomeProperty)
        .required()
        .matches(x => x.SomeOtherProperty)
    .build();

You can also make use of async/await for almost all async methods like so:

const modelErrors = await validationGroup.getModelErrors();
console.log(modelErrors);

Validation rules

The framework comes with built in validators for the following:

  • date - The value is expressible as a date
  • decimal - The value is expressible as a float/single
  • email - The value conforms to a valid email address
  • equal - The value is equal to another value
  • isoDate - The value conforms to a valid ISO date format
  • maxLength - The value must have a length <= value
  • maxValue - The value must have a value <= value
  • minLength - The value must have a length >= value
  • minValue - The value must have a value >= value
  • notEqual - The value is not equal to another value
  • number - The value is expressible as an integer
  • regex - The value matches the regex pattern
  • required - The value is not a null-like value
  • step - The value conforms to the numeric steps provided
  • matches - The value must match another property in the model

Creating custom rules

Creating custom rules is pretty easy, you need to:

  • Implement IValidationRule with your custom logic (JS users just match the signatures of the interface)
  • Add validation messages for supported locales
  • Register your rule with the ruleRegistry

There is a whole doc on the subject which can be found in the docs section.


Localization

There is a whole doc on the subject, but at a high level BY DEFAULT treacherous will pre-load the en-us locale for you which will be used by the library, but you can easily supplement that locale, or register and use new locales. You can also completely replace the default localization handler, but see the docs for more info on this.


Documentation

Just look in the docs folder for more documentation on certain scenarios or subject matters.

DOCS ARE HERE


Related Libraries

This library is the core treacherous framework, which purely handles the validation of models, however there are a few other libraries which build on top of this such as:


Developing

If you want to develop it further just clone the repo, npm install and gulp it should then provide you a working version to play with. If you want to minify it you can do gulp minify which will minify the output files, we don't minify by default.

You can also run gulp run-tests which will run the tests to make sure everythign works as expected.


Credits

"Mountains" Icon courtesy of The Noun Project, by Aleksandr Vector, under CC 3.0