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

pojo-fluent-validator

v1.1.7

Published

Validation and conversion tool for plain old javascript objects.

Downloads

62

Readme

pojo-fluent-validator

pojo-fluent-validator is javascript library used to check and convert plain old javascript objects with fluent configuration syntax.

NOTE: Validator works with plain old javascript objects only. That means no classes, no functions, no prototypes - it works with object literals, primitive types and arrays. Validator doesn't change source object, instead it makes a copy of the object but doesn't call constructor and don't copy prototype.

Features

  • Validates and converts primitive types - numbers, strings, and any type - with custom validation rule.
  • Validates objects by validating each object property.
  • Validates hashes (maps) - objects where each property value has the same structure.
  • Validates arrays of primitive types or objects.
  • Composability - validators for complex objects uses regular validators, so nested value can be object, array, hash or primitive type.
  • Fluent syntax - validation rules are configured using chained method calls.

Usage

Installation

npm install pojo-fluent-validator

NOTE: validate function which returns a promise is not included in package, it looks like:

Javascript


import { validate as validateWithCallback } from "pojo-fluent-validator";

export function validate(value: any, ...validators) {
    if (!validators || !validators.length) {
        throw new Error("At least one validator is required");
    }

    return new Promise((resolve, reject) => {
        validateWithCallback(
            value,
            (errors, result) => {
                if (errors) {
                    reject(errors);
                }
                else {
                    resolve(result);
                };
            },
            ...validators);
    });
}

Typescript

import { validate as validateWithCallback, ValidationRule } from "pojo-fluent-validator";

export function validate<T>(value: any, ...validators: ValidationRule<T>[]): Promise<T> {
    if (!validators || !validators.length) {
        throw new Error("At least one validator is required");
    }

    return new Promise((resolve, reject) => {
        validateWithCallback(
            value,
            (errors, result) => {
                if (errors) {
                    reject(errors);
                }
                else {
                    resolve(result);
                };
            },
            ...validators);
    });
}

Single value validation example.

import { rules } from "pojo-fluent-validator";


const rule = rules.num().must(v => v > 0, { errorMessage: "Must be greater than zero!" });

validate("10", rule).then(v => {
    // Value successfuly converted to number and validated
    console.log(v, v + 2); // Outputs 10 12
}).catch(err => { 
    // Don't reach this point until value is invalid.
});

validate("sdf", rule).then(v => {
    // Value is invalid number, then block is not executed
).catch(err => {
    // err[""] contains validation messages for whole object
    console.log(err[""]); // Outputs ["Value is not a valid number"]
});

Object validation example. Shows validator composability.

import { rules } from "pojo-fluent-validator";


const positiveNumberRule = rules.num().must(v => v > 0);

const productRule = rules.obj({
    // Use previously defined rule
    id: positiveNumberRule,
    // Or inlined rule
    title: rules.str().notEmpty(),
    // Rule can be extended with additional conditions using fluent syntax.
    // .required() call need to fail on null values. Number validator by default passes nulls.    
    vendorPrice: positiveNumberRule.required(),
    // Second parameter of `must` rule is validating object
    // Inside .must(..) check we don't assume retailPrice can be null.
    // That's because required() rule stop rule chain on fail.
    // To control this use { stopOnFailure: false } as rule options.
    retailPrice: positiveNumberRule.required()
        .must((v, product) => product.retailPrice > product.vendorPrice, 
            { errorMessage: "Product should be profitable" })
});


// Valid object 
validate({
    id: 1,
    title: "Melon",
    // rules.num() parses number by default. 
    vendorPrice: "12.3",
    retailPrice: 14.44
}, productRule).then(p => {
    // Product successfuly validated
    // p.vendorPrice is now number.
    console.dir(p); 
}).catch(err => { 
    // Don't reach this point until value is invalid.
});

// Valid object 
validate({
    id: 1,
    title: "Melon",
    // rules.num() parses number by default. 
    vendorPrice: "12.3",
    retailPrice: 4.44
}, productRule).then(p => { })
.catch(err => { 
    // err is hash of "path.to.error.property.or[index]": ["validation", "messages"]
    console.log(err["deliveryPrice"]); // Outputs ["Product should be profitable"] 
});

Array validation

import { rules } from "pojo-fluent-validator";

const numArrayRule = rules.arr(
        rules.num().required().must(v => v > 0));

validate([1, 2, "3"], numArrayRule)
    .then(arr => {
        // Array validated. Third element converted from string.
        console.log(arr); // Outputs [1, 2, 3]
    });

validate([1, 2, "three"],  numArrayRule)
    .catch(err => {
        // For arrays error path is "[2]"
        console.log(err["[2]"]); // Outpus ["Value is not a valid number"] 
    }); 

Array of objects validation

import { rules } from "pojo-fluent-validator";

const objArrayRule = rules.arr(
        rules.obj({
            id: rules.num().required(),
            title: rules.str().required()
        }).required() // rule.obj passes null values by default
          .expandable() // Expandable object allows to have extra non-validatable properties
    );

const invalidArray = [{
    id: 1,
    title: "First"
}, {
    id: null,
    title: "Second"
}];

validate(invalidArray, objArrayRule)
    .catch(err => {
        // Rules pathes are nested in the way of plain javascript access operations
        console.log(err["[1].id"]); // Outputs ["Value is required"]
    });