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

rule-filter-validator

v1.5.9

Published

A object and scope validator based on structured rules

Downloads

1,474

Readme

The idea

Given a specific scope what is the easiest way to write various rules that be tested against the scope for various reasons

Useful for testing & validation Business Logic stored as json.

Getting started

npm install rule-filter-validator

Usage

// Initial state/scope/payload
const SCOPE = {
    person: {
        id: 1,
        dob: "1998-02-18",
        age: 23,
        active: true,
        gender: 'F'
    }
}
// Validate and return errors
const rule: Filter = {
    "person": {
        "age": {
            "_gt": 18,
            "_lt": 25
        }
    }
}

let errors = validatePayload(rule, SCOPE);
return ! errors.length // true
// Simply validate
// Using field alter functions
isValidPayload({ person: { 'year(dob)': { _eq: 1998 } } }, SCOPE) // true


// Using $NOW
isValidPayload({ person: { 'dob': { _gt: '$NOW(-6 years)' } } }, SCOPE) // false

View all methods and functions

By default tests are case and type insensitive, meaning:

| Rule | Fn | Scope | Result | | ---- | ----- | ----- | ------ | | 1 | _eq | '1' | true | 'ABC' | _eq | 'abc' | true | 'zxc3' | _contains | 3 | true | 'zxc3' | _contains | 'ZXC' | true

Calling validatePayload(filter, payload, [strict = false]) with strict = true will make the validator to be case and type sensitive.

| Rule | Fn | Scope | Result | | ---- | ----- | ----- | ------ | | 1 | _eq | '1' | false | 'ABC' | _eq | 'abc' | false | 'zxc3' | _contains | 3 | true | 'zxc3' | _contains | 'ZXC' | false

_contains always compares as strings and is therefore not type sensitive

Advance Usage

const prices = [
    {
        label: 'Child price'
        price: 100,
        logic: {
            "person": {
                "age": {
                    "_lt": 18
                }
            }
        }
    },
    {
        label: 'Adult price'
        price: 200,
        logic: {
            "person": {
                "age": {
                    "_gte": 18
                }
            }
        }
    }
]

const scope = getUserScope(); // You implement this.

const priceToPay = prices.find(({ price, logic }) => {
    let e = validatePayload(logic, scope)
    return ! e.length
})
const filter: Filter = {
    _or: [{
        permissions: {
            _$: {
                action: {
                    _eq: 'update',
                },
                collection: {
                    _eq: 'membership',
                },
                fields: {
                    _contains: 'status',
                },
            },
        },
    },
    {
        role: {
            _eq: 'admin',
        },
    }],
};

const scope = {
    role: 'author',
    permissions: [
        {
            action: 'create',
            collection: 'membership',
            fields: ['person', 'status'],
        },
        {
            action: 'read',
            collection: 'membership',
            fields: ['id', 'person', 'status'],
        },
        {action: 'update', collection: 'membership', fields: ['status']},
    ],
};

const canAccess = validatePayload(filter, scope, strict?).length === 0
// passes
validatePayload(
    { person: {'year(dob)': {_eq: 2009}} },
    { person: { dob: '2009-02-18' } }
);

// passes (IF the year is currently 2021)
validatePayload(
    { person: {'year(dob)': {_eq: '$NOW(-12 years).year'}} },
    { person: { dob: '2009-02-19' } }
);

Methods

  • isValidPayload(Filter, Payload, strict?)

    This is a simple function that returns true if the payload is valid against the filter, and false otherwise.

  • validatePayload(Filter, Payload, strict?)

    This is the main function that validates the payload against the filter. It returns an array of errors, if any.

  • invertFilter(Filter)

    Inverts the filter, so that the filter will return the opposite of what it would have returned before.

  • extractFieldFromFilter(Filter, Field, Path?)

    This extracts the given field from the passed Filter and returns a new Filter object that only contains only the given field and its children, if any.

  • adjustDate(date, adjustment)

    The function applies adjustments to the Date using built-in methods such as setUTCMonth, setUTCHours, etc., based on the type of adjustment requested. If no supported adjustment type is supplied, it returns undefined.

    eg. -1 month will return the date 1 month before the given date.

    Supports years, months, days, hours, minutes, seconds, milliseconds, and weeks.


Dynamic values

Currently only supporting one dynamic value, which is $NOW.

Examples:

  • $NOW(-1 month) will test the payload with the date 1 month before the current date.
  • $NOW(-12 years).year will test the payload with the year 12 years before the current date.

Supports all field functions that can be applied to a date.

Operands

Special Operands

| Fn | Description | Accepted Types | | ---- | ----- | ----- | | _and | All of the specified filters must be true for the expression to be true | array of filters | _or | At least one of the specified filters must be true for the expression to be true | array of filters | _$ | Used as an index for array of objects, whereby at least one item must pass the filter for the expression to be true. | object

Field Functions

Used on fields to perform operations on them. eg. year(dob) will test with the year of the date of birth.

| Fn | Description | Accepted Types | | ---- | ----- | ----- | | year() | the year of the date | date, isoString | month() | the month of the date | date, isoString | week() | the week of the date | date, isoString | day() | the day of the date | date, isoString | hour() | the hour of the date | date, isoString | minute() | the minute of the date | date, isoString | second() | the second of the date | date, isoString | count() | the number of items in the array | array

All Operands (Functions)

| Fn | Description | Accepted Types | | ---- | ----- | ----- | | _eq | equal to | string, number, boolean | _neq | not equal to | string, number, boolean | _contains | string/array contains | string, number | _ncontains | string/array does not contain | string, number | _starts_with | starts with | string, number | _nstarts_with | does not start with | string, number | _ends_with | ends with | string, number | _nends_with | does not end with | string, number | _in | in | string, Array | _nin | not in | string, Array | _between | between | string, number, Date | _nbetween | not between | string, number, Date | _gt | greater than | string, number, Date | _gte | greater than or equal to | string, number, Date | _lt | less than | string, number, Date | _lte | less than or equal to | string, number, Date | _null | null = | string, number, boolean, Date, Array | _nnull | not null = | string, number, boolean, Date, Array | _empty | empty = | string, Array | _nempty | not empty = | string, Array | _submitted | submitted = | string, number, boolean, Date, Array | _regex | matching regex | string, number, boolean, Date

_$

Given the following data record:

const data = {
    colors: [{
        name: 'red',
        hex: '#ff0000',
    }, {
        name: 'green',
        hex: '#00ff00',
    }, {
        name: 'blue',
        hex: '#0000ff',
    }]
};

The following filter will pass:

{
    colors: {
        _$: {
            name: {
                _eq: 'red',
            },
        },
    },
}

And the following will fail:

{
    colors: {
        _$: {
            name: {
                _eq: 'yellow',
            },
        },
    },
}

You could also have multiple properties that have to match

// Will pass
{
    colors: {
        _$: {
            name: {
                _eq: 'red',
            },
            hex: {
                _eq: '#ff0000',
            },
        },
    },
}

// Will fail
{
    colors: {
        _$: {
            name: {
                _eq: 'red',
            },
            hex: {
                _eq: '#ff4444',
            },
        },
    },
};