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

audit-var

v2.3.1

Published

Inspects variables according to a defined structure

Downloads

4

Readme

audit-var

Validates the type and structure of an incoming object. It's specially useful to validate the incoming data in endpoints of an API Rest, or in any other escenario when it's possible to receive an unexpected potentially manipulated data from the requester.

This library now is an ESM, so if you need CJS support, then use this version instead.

Contents

The problem

Usually, when you make an endpoint (with express for example) you need to validate the incoming data before to modify your server state. In those cases, just the validation part taken a lot of space in your file, for example:

import express, { json } from 'express';

const app = express();
app.use(json({ strict: false }));

// An interface to declare the expected structure of the body
interface Body {
    id: number;
    text: string;
}

// The endpoint
app.get('/test', (req, res) => {
    // Validate manually the incoming object
    const body = req.body as Body;
    if (body == null) {
        throw new Error('invalid object!');
    }

    if (typeof body.id !== 'number') {
        throw new Error('id (typeof "number") expected!');
    } else if (body.id <= 0) {
        throw new Error('invalid id!');
    }

    if (typeof body.text !== 'string') {
        throw new Error('text (typeof "string") expected!');
    } else if (body.text.length < 10) {
        throw new Error('text minimum length = 10 chars!');
    }

    // Bla bla bla bla
    // Bla bla bla bla
    // Bla bla bla bla
});

The solution

With audit-var you can apply the same validation in a less space. For example, taking the code of above and using audit-var, could be like this:

import express, { json } from 'express';
import { Auditor } from 'audit-var';

const app = express();
app.use(json({ strict: false }));

// Declare your auditor
const auditor = new Auditor({
    type: 'object',
    keys: {
        id:     { type: 'number', min:  1 },
        text:   { type: 'string', min: 10 },
    }
});

// The endpoint
app.get('/test', (req, res) => {
    // Checking if req.body meets the criteria settled
    // in the Auditor instance
    const body = auditor.audit(req.body);

    // Bla bla bla bla
    // Bla bla bla bla
    // Bla bla bla bla
});

How to use

To install this package, use this command:

npm i --save audit-var

The class Auditor makes all the job, you just must to import that class, and pass to the constructor an object that describes the type of data do you want to validate. The incoming objects compatibles with the Auditor class are:

  • 'date'.
  • 'number'.
  • 'string'.
  • 'boolean'.
  • 'array'.
  • 'object'.
  • 'record'.

As much as the Array, Object and Record types, both have support to nested arrays and objects. So with this approach you can declare complex structures as you need.

So, to declare the data expected, the Auditor class receives an object as parameter (implements BaseType<T> interface), like this:

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    // The type of value expected
    type: 'string',

    // Defaults false
    optional: true,

    // Bla bla bla
    // Bla bla bla
    // Bla bla bla
});

First you need to set this parameters (defined in BaseType<T> interface):

  • type (required): (read below);

    Sets the type of data do you want to expect. You can set any value described in this list. When you sets this value, your code editor will shows the options available of the according type selected. If the incoming value doesn't match the type specified, the Auditor instance will throws an InvalidTypeError instance.

  • optional (optional): boolean;

    By default this value is false. When this option is false, and the incoming value is null or undefined, the Auditor instance will throws an NotOptionalError instance. Otherwise, the method auditor.audit(...); will returns an undefined value either if the incoming value is null or undefined.

These options are defined in BaseType<T> interface, so you must provide in the constructor an object that implements that interface. So, the object you can provide must be one of the following (these implements BaseType<T>):

Type 'boolean'

Boolean types doesn't have additional options. An example of usage:

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'boolean',
    optional: true
});

Type 'string'

Options:

  • min (optional): number;

    If the incoming string has a length lower than the value setted, the Auditor instance will throws an WrongLengthError instance.

  • max (optional): number;

    If the incoming string has a length higher than the value setted, the Auditor instance will throws an WrongLengthError instance.

  • cut (optional): boolean;

    If this option is enabled, when the length of the incoming string is longer than the max value settled, the output value will be cutted instead to throws an error.

  • trim (optional): boolean;

    Trims the incoming string before to make any length validation.

Example:

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'string',
    min: 4,
    max: 20,
    trim: true,
});

Type 'number'

Options:

  • min (optional): number;

    If the incoming value has lower than the value setted, the Auditor instance will throws an WrongLengthError instance.

  • max (optional): number;

    If the incoming value has higher than the value setted, the Auditor instance will throws an WrongLengthError instance.

Example:

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'number',
    min: 0,
    max: 999
});

Type 'date'

Options:

  • fromJSON (optional): boolean;

    If this value is true, the Auditor instance will try to parse strings with a valid JSON Date format (like '2022-12-31T03:00:00.000Z'). If the convertion is sucessfull, the returned value will be a Date type, otherwise, the Auditor instance will throws an InvalidJSONDateError instance.

Example:

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'date',
    fromJSON: true
});

Type 'array'

Options:

  • items (required): BaseType<T>;

    With this option you can specify the structure of every item stored in the array, using the same options described in the past types described. You can declare nested arrays, object arrays, or nested dictionaries too.

  • min (optional): number;

    If the incoming array has a length lower than the value setted, the Auditor instance will throws an WrongLengthError instance.

  • max (optional): number;

    If the incoming array has a length higher than the value setted, the Auditor instance will throws an WrongLengthError instance.

Example 01 (array of string):

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'array',
    min: 10,
    max: 100,
    items: {
        type: 'string',
        min: 4
    }
});

Example 02 (array of number[]):

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'array',
    items: {
        type: 'array',
        min: 4,
        max: 4,
        items: {
            type: 'number',
            optional: true
        }
    }
});

Example 03 (array of object):

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'array',
    items: {
        type: 'object',
        keys: {
            id:     { type: number, min: 1 },
            name:   { type: string, min: 4 }
        }
    }
});

Type 'object'

Options:

  • keys (required): Record<string, BaseType<T>>;

    Defines the type of data expected for every key of the incoming object.

Example 01:

import { Auditor } from 'audit-var';

// The expected incoming object
interface Expected {
    id: number;
    name: string;
    active?: boolean;
}

// How to declare the Auditor instance
export const auditor = new Auditor({
    type: 'object',
    keys: {
        id:     { type: 'number', min: 1 },
        name:   { type: 'string', min: 4 },
        active: { type: 'boolean'. optional: true}
    }
});

Example 02 (nested objects):

import { Auditor } from 'audit-var';

// The expected incoming object
interface Incoming {
    id: number;
    config: {
        path: string;
        silent?: boolean;
    }
    data: {
        id: number;
        value: string;
    }
}

// How to declare the Auditor instance
export const auditor = new Auditor({
    type: 'object',
    keys: {
        id:     { type: 'number', min: 1 },
        config:   {
            type: 'object',
            keys: {
                path:   { type: 'string' },
                silent: { type: 'boolean', optional: true }
            }
        },
        data: {
            type: 'array',
            items: {
                type: 'object',
                keys: {
                    id:     { type: 'number' },
                    value:  { type: 'string' }
                }
            }
        }
    }
});

Type 'record'

Options:

  • items (required): BaseType<T>;

    With this option you can specify the structure of every item stored for each key inside of the object, using the same options described in the past types described. You can declare nested arrays, object arrays, or nested dictionaries too.

    import { Auditor } from 'audit-var';
      
    // The incoming data
    const target = {
        joder: { id: 666, nick: 'ghostlug' },
        shavo: { id: 666, nick: 'dir en grey' },
    };
    
    // The auditor 
    const auditor = new Auditor({
        type: 'record',
        items: {
            type: 'object',
            keys: {
                id: { type: 'number' },
                nick: { type: 'string' }
            }
        }
    });

Type 'enum'

The 'enum' type allows for the validation of values against a predefined set of allowed values. This set can include primitives (such as strings and numbers), arrays, objects, or even dates, providing flexibility for different validation scenarios. The 'enum' type ensures the value being validated exactly matches one of the values in the specified set.

Options:

  • values (required): Array<any>;

    An array containing the valid values for the enum. The values can be of any type, allowing for the validation of complex structures and data types.

  • optional (optional): boolean;

    By default, this value is false. When set to true, and the incoming value is null or undefined (and those values are not explicitly included in the values array), the Auditor instance will return undefined. This behavior allows fields to be omitted without causing validation errors. If optional is set to false and the incoming value is either null, undefined, or not included in the values array, the Auditor instance will throw an error, enforcing strict presence and value validation.

Example with primitive values:

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'enum',
    values: ['active', 'inactive', 'pending'] as const,
    optional: true
});

Example with objects:

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'enum',
    values: [
        { status: 'active', code: 1 },
        { status: 'inactive', code: 2 }
    ] as const
});

Example with arrays:

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'enum',
    values: [
        [1, 2, 3],
        ['a', 'b', 'c']
    ] as const
});

Example with dates:

import { Auditor } from 'audit-var';

export const auditor = new Auditor({
    type: 'enum',
    values: [
        new Date('2023-01-01T00:00:00.000Z'),
        new Date('2023-12-31T23:59:59.999Z')
    ] as const
});

Utilities

this.structure

Gets the actual structure of the current instance. Whith this you attach them to another more complex instance.

const auditorChild = new Auditor({
    type: 'object',
    keys: {
        id:     { type: 'number', min: 1 },
        text:   { type: 'string' }
    }
});

const auditorParent = new Auditor({
    type: 'object',
    keys: {
        objA: auditor.child.structure,
        objB: auditor.child.structure,
    }
});