Schema-Inspector is an JSON API sanitisation and validation module.

Overview

schema-inspector logo

Schema-Inspector is a powerful tool to sanitize and validate JS objects. It's designed to work both client-side and server-side and to be scalable with allowing asynchronous and synchronous calls.

NPM version

See a live example: http://schema-inspector.github.io/schema-inspector/

Installation

Node.js

npm install schema-inspector

Browser

Bower uses have reported success using the library this way, using bower overrides in bower.json.

image

Bower is not officially-supported as a build tool and references to it will be removed from the repository in versions 3.0.0+.

Version 2.0.0

To fix a security vulnerability in the 1.x.x email Regex expression used, a new Regex expression was used which may be less flexible than the expression used in 1.x.x. Therefore, version 2.0.0 was released with this new expression. It's highly-recommended to upgrade to this new version after testing it.

If you need the old, insecure behavior, use version 1.x.x or use the custom validation function feature for your field and perform email address validation any way you like.

How it looks like

schema-inspector demo Click to see it live!

Usage

var inspector = require('schema-inspector');

// Data that we want to sanitize and validate
var data = {
    firstname: 'sterling  ',
    lastname: '  archer',
    jobs: 'Special agent, cocaine Dealer',
    email: 'NEVER!',
};

// Sanitization Schema
var sanitization = {
    type: 'object',
    properties: {
        firstname: { type: 'string', rules: ['trim', 'title'] },
        lastname: { type: 'string', rules: ['trim', 'title'] },
        jobs: {
            type: 'array',
            splitWith: ',',
            items: { type: 'string', rules: ['trim', 'title'] },
        },
        email: { type: 'string', rules: ['trim', 'lower'] },
    },
};
// Let's update the data
inspector.sanitize(sanitization, data);
/*
data is now:
{
    firstname: 'Sterling',
    lastname: 'Archer',
    jobs: ['Special Agent', 'Cocaine Dealer'],
    email: 'never!'
}
*/

// Validation schema
var validation = {
    type: 'object',
    properties: {
        firstname: { type: 'string', minLength: 1 },
        lastname: { type: 'string', minLength: 1 },
        jobs: {
            type: 'array',
            items: { type: 'string', minLength: 1 },
        },
        email: { type: 'string', pattern: 'email' },
    },
};
var result = inspector.validate(validation, data);
if (!result.valid)
    console.log(result.format());
/*
 Property @.email: must match [email], but is equal to "never!"
*/

Tips: it's recommended to use one schema for the sanitization and another for the validation,

In the browser

<script type="text/javascript" src="async.js"></script>
<script type="text/javascript" src="schema-inspector.js"></script>
<script type="text/javascript">
    var schema = { /* ... */ };
    var candidate = { /* ... */ };
    SchemaInspector.validate(schema, candidate, function (err, result) {
    if (!result.valid)
        return alert(result.format());
 });
</script>

In the example below, the inspector variable will be used. For the client-side use SchemaInspector instead of inspector.

Documentation

Validation

Sanitization

Custom fields

Asynchronous call

Thanks to

Validation

type

  • type: string, array of string.
  • usable on: any.
  • possible values
    • string
    • number
    • integer
    • boolean
    • null
    • date (instanceof Date), you can use the validDate: true to check if the date is valid
    • object (typeof element === 'object') Note: array, null, or dates don't match the object type
    • array (constructor === Array)
    • A function (candidate isinstance)
    • any (it can be anything)

Allow to check property type. If the given value is incorrect, then type is not checked.

Example

var inspector = require('schema-inspector');

function Class() {}

var schema = {
    type: 'object',
    properties: {
        lorem: { type: 'number' },
        ipsum: { type: 'any' },
        dolor: { type: ['number', 'string', 'null'] },
        sit: { type: Class },
    },
};

var c1 = {
    lorem: 12,
    ipsum: 'sit amet',
    dolor: 23,
    sit: new Class(),
};
var c2 = {
    lorem: 12,
    ipsum: 34,
    dolor: 'sit amet',
    sit: new Class(),
};
var c3 = {
    lorem: 12,
    ipsum: ['sit amet'],
    dolor: null,
    sit: new Class(),
};
var c4 = {
    lorem: '12',
    ipsum: 'sit amet',
    dolor: new Date(),
    sit: {},
};

inspector.validate(schema, c1); // Valid
inspector.validate(schema, c2); // Valid
inspector.validate(schema, c3); // Valid
inspector.validate(schema, c4); // Invalid: @.lorem must be a number, @dolor must be a number, a string or null, @.sit must be an instance of Class, but is object

optional

  • type: boolean.
  • default: false.
  • usable on: any.

This field indicates whether or not property has to exist.

Example

var inspector = require('Roadspector');

var schema1 = {
    type: 'object',
    properties: {
        lorem: { type: 'any', optional: true },
    },
};

var schema2 = {
    type: 'object',
    properties: {
        lorem: { type: 'any', optional: false }, // default value
    },
};

var c1 = { lorem: 'ipsum' };
var c2 = {};

inspector.validate(schema1, c1); // Valid
inspector.validate(schema1, c2); // Valid
inspector.validate(schema2, c1); // Valid
inspector.validate(schema2, c2); // Invalid: "@.lorem" is missing and not optional

uniqueness

  • type: boolean.
  • default: false.
  • usable on: array, string.

If true, then we ensure no element in candidate exists more than once.

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'array',
    uniqueness: true,
};

var c1 = [12, 23, 34, 45];
var c2 = [12, 23, 34, 12];

inspector.validate(schema, c1); // Valid
inspector.validate(schema, c2); // Invalid: 12 exists twice in @.

pattern

  • type: string, RegExp object, array of string and RegExp.
  • usable on: string.
  • Possible values as a string: void, url, date-time, date, coolDateTime, time, color, email, numeric, integer, decimal, v4uuid, alpha, alphaNumeric, alphaDash, javascript, upperString, lowerString.

Ask Schema-Inspector to check whether or not a given matches provided patterns. When a pattern is a RegExp, it directly test the string with it. When it's a string, it's an alias of a RegExp.

Example

var inspector = require('schema-inspector');

var schema1 = {
    type: 'array',
    items: { type: 'string', pattern: /^[A-C]/ },
};

var c1 = ['Alorem', 'Bipsum', 'Cdolor', 'DSit amet'];

var schema2 = {
    type: 'array',
    items: { type: 'string', pattern: 'email' },
};

var c2 = ['[email protected]', '[email protected]', 'amet@consectetur'];

inspector.validate(schema1, c1); // Invalid: @[3] ('DSit amet') does not match /^[A-C]/
inspector.validate(schema2, c2); // Invalid: @[2] ('amet@consectetur') does not match "email" pattern.

minLength, maxLength, exactLength

  • type: integer.
  • usable on: array, string.

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    properties: {
        lorem: { type: 'string', minLength: 4, maxLength: 8 },
        ipsum: { type: 'array', exactLength: 6 },
    },
};
var c1 = {
    lorem: '12345',
    ipsum: [1, 2, 3, 4, 5, 6],
};

var c2 = {
    lorem: '123456789',
    ipsum: [1, 2, 3, 4, 5],
};

inspector.validate(schema, c1); // Valid
inspector.validate(schema, c2); // Invalid: @.lorem must have a length between 4 and 8 (here 9)
// and @.ipsum must have a length of 6 (here 5)

lt, lte, gt, gte, eq, ne

  • type: number (string, number and boolean for eq).
  • usable on: number (string, number and boolean for eq).

Check whether comparison is true:

  • lt: <
  • lte: <=
  • gt: >
  • gte: >=
  • eq: ===
  • ne: !==

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    properties: {
        lorem: { type: 'number', gt: 0, lt: 5 }, // Between ]0; 5[
        ipsum: { type: 'number', gte: 0, lte: 5 }, // Between [0; 5]
        dolor: { type: 'number', eq: [0, 3, 6, 9] }, // Equal to 0, 3, 6 or 9
        sit: { type: 'number', ne: [0, 3, 6, 9] }, // Not equal to 0, 3, 6 nor 9
    },
};

var c1 = { lorem: 3, ipsum: 0, dolor: 6, sit: 2 };
var c2 = { lorem: 0, ipsum: -1, dolor: 5, sit: 3 };

inspector.validate(schema, c1); // Valid
inspector.validate(schema, c2); // Invalid

someKeys

  • type: array of string.
  • usable on: object.

Check whether one of the given keys exists in object (useful when they are optional).

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    someKeys: ['lorem', 'ipsum'],
    properties: {
        lorem: { type: 'any', optional: true },
        ipsum: { type: 'any', optional: true },
        dolor: { type: 'any' },
    },
};

var c1 = { lorem: 0, ipsum: 1, dolor: 2 };
var c2 = { lorem: 0, dolor: 2 };
var c3 = { dolor: 2 };

inspector.validate(schema, c1); // Valid
inspector.validate(schema, c2); // Valid
inspector.validate(schema, c3); // Invalid: Neither @.lorem nor @.ipsum is in c3.

strict

  • type: boolean.
  • default: false.
  • usable on: object.

Only keys provided in field "properties" may exist in the object. Strict will be ignored if properties has the special key '*'.

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    strict: true,
    properties: {
        lorem: { type: 'any' },
        ipsum: { type: 'any' },
        dolor: { type: 'any' },
    },
};

var c1 = { lorem: 0, ipsum: 1, dolor: 2 };
var c2 = { lorem: 0, ipsum: 1, dolor: 2, sit: 3 };

inspector.validate(schema, c1); // Valid
inspector.validate(schema, c2); // Invalid: @.sit should not exist.

exec

  • type: function, array of function.
  • usable on: any.

Custom checker =). "exec" functions take two three parameter (schema, post [, callback]). To report an error, use this.report([message], [code]). Very useful to make some custom validation.

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    properties: {
        lorem: {
            type: 'number',
            exec: function (schema, post) {
                // here schema === schema.properties.lorem and post === @.lorem
                if (post === 3) {
                    // As soon as `this.report()` is called, candidate is not valid.
                    this.report('must not equal 3 =('); // Ok...it's exactly like "ne: 3"
                }
            },
        },
    },
};

var c1 = { lorem: 2 };
var c2 = { lorem: 3 };

inspector.validate(schema, c1); // Valid
inspector.validate(schema, c2); // Invalid: "@.lorem must not equal 3 =(".

properties

  • type: object.
  • usable on: object.

For each property in the field "properties", whose value must be a schema, validation is called deeper in object.

The special property '*' is validated against any properties not specifically listed.

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    properties: {
        lorem: {
            type: 'object',
            properties: {
                ipsum: {
                    type: 'object',
                    properties: {
                        dolor: { type: 'string' },
                    },
                },
            },
        },
        consectetur: { type: 'string' },
        '*': { type: 'integer' },
    },
};

var c1 = {
    lorem: {
        ipsum: {
            dolor: 'sit amet',
        },
    },
    consectetur: 'adipiscing elit',
    adipiscing: 12,
};
var c2 = {
    lorem: {
        ipsum: {
            dolor: 12,
        },
    },
    consectetur: 'adipiscing elit',
};

inspector.validate(schema, c1); // Valid
inspector.validate(schema, c2); // Invalid: @.lorem.ipsum.dolor must be a string.

items

  • type: object, array of object.
  • usable on: array.

Allow to apply schema validation for each element in an array. If it's an object, then it's a schema which will be used for all the element. If it's an array of object, then it's an array of schema and each element in an array will be checked with the schema which has the same position in the array.

Example

var inspector = require('schema-inspector');

var schema1 = {
    type: 'array',
    items: { type: 'number' },
};

var schema2 = {
    type: 'array',
    items: [{ type: 'number' }, { type: 'number' }, { type: 'string' }],
};

var c1 = [1, 2, 3];
var c2 = [1, 2, 'string!'];

inspector.validate(schema1, c1); // Valid
inspector.validate(schema1, c2); // Invalid: @[2] must be a number.
inspector.validate(schema2, c1); // Invalid: @[2] must be a string.
inspector.validate(schema2, c2); // Valid

alias

  • type: string.
  • usable on: any.

Allow to display a more explicit property name if an error is encounted.

Example

var inspector = require('schema-inspector');

var schema1 = {
    type: 'object',
    properties: {
        _id: { type: 'string' },
    },
};

var schema2 = {
    type: 'object',
    properties: {
        _id: { alias: 'id', type: 'string' },
    },
};

var c1 = { _id: 1234567890 };

var r1 = inspector.validate(schema1, c1);
var r2 = inspector.validate(schema2, c1);
console.log(r1.format()); // Property @._id: must be string, but is number
console.log(r2.format()); // Property id (@._id): must be string, but is number

error

  • type: string.
  • usable on: any.

This field contains a user sentence for displaying a more explicit message if an error is encounted.

Example

var inspector = require('schema-inspector');

var schema1 = {
    type: 'object',
    properties: {
        _id: { type: 'string' },
    },
};

var schema2 = {
    type: 'object',
    properties: {
        _id: { type: 'string', error: 'must be a valid ID.' },
    },
};

var c1 = { _id: 1234567890 };

var r1 = inspector.validate(schema1, c1);
var r2 = inspector.validate(schema2, c1);
console.log(r1.format()); // Property @._id: must be string, but is number.
console.log(r2.format()); // Property @._id: must be a valid ID.

code

  • type: string.
  • usable on: any.

This field contains a user code for displaying a more uniform system to personnalize error message.

Example

var inspector = require('schema-inspector');

var schema1 = {
    type: 'object',
    properties: {
        _id: { type: 'string' },
    },
};

var schema2 = {
    type: 'object',
    properties: {
        _id: { type: 'string', code: 'id-format' },
    },
};

var c1 = { _id: 1234567890 };

var r1 = inspector.validate(schema1, c1);
var r2 = inspector.validate(schema2, c1);
console.log(r1.error[0].code); // null
console.log(r2.error[0].code); // 'id-format'

Sanitization

type

  • type: string.
  • usable on: any.
  • possible values
    • number
    • integer
    • string
    • boolean
    • date (constructor === Date)
    • object (constructor === Object)
    • array (constructor === Array)

Cast property to the given type according to the following description:

  • to number from:
    • string (ex: "12.34" -> 12.34) sanitization string to number
    • date (ex: new Date("2014-01-01") -> 1388534400000) sanitization string to number
  • to integer from:
    • number
      • 12.34 -> 12
    • string
      • "12.34" -> 12
    • boolean
      • true -> 1
      • false -> 0
    • date
      • new Date("2014-01-01") -> 1388534400000
  • to string from:
    • boolean
      • true -> "true"
    • number
      • 12.34 -> "12.34"
    • integer
      • 12 -> "12"
    • date
      • new Date("2014-01-01") -> "Wed Jan 01 2014 01:00:00 GMT+0100 (CET)"
    • array
      • [12, 23, 44] -> '12,34,45'
      • To join with a custom string, use joinWith key (example: { type: "string", joinWith: "|" } will transform [12, 23, 44] to "12|23|44").
  • to date from:
    • number / integer
      • 1361790386000 -> Wed Jan 01 2014 01:00:00 GMT+0100 (CET)
    • string
      • "2014-01-01 -> Wed Jan 01 2014 01:00:00 GMT+0100 (CET)
      • "Wed Jan 01 2014 01:00:00 GMT+0100 (CET)" -> Wed Jan 01 2014 01:00:00 GMT+0100 (CET)
  • to object from:
    • string
      • '{"love":"open source"}' -> { love: "open source" }
  • to array from:
    • string ("one,two,three" -> ["one", "two", "three"], '[1,"two",{"three":true}]' -> [ 1, 'two', { three: true } ])
    • anything except undefined and array (23 -> [ 23 ])
    • To split with a custom string (other than ","), use the key splitWith (example: { type: "array", splitWith: "|"" } will transform "one|two|three" to ["one", "two", "three"]).*

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'array',
    items: { type: 'string' },
};

var c = [12.23, -34, true, false, 'true', 'false', [123, 234, 345], { obj: "yes" }];

var r = inspector.sanitize(schema, c);
/*
r.data: [ '12.23', '-34', 'true', 'false', 'true', 'false', '123,234,345', '{"obj":"yes"}' ]
*/

def

  • type: any.
  • usable on: any.

Define default value if property does not exist, or if type casting is to fail because entry type is not valid (cf type).

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    properties: {
        lorem: { type: 'number', def: 10 },
        ipsum: { type: 'string', def: 'NikitaJS', optional: false },
        dolor: { type: 'string' },
    },
};

var c = {
    lorem: [12, 23], // convertion to number is about to fail
    // (array -> number is not possible)
    // ipsum is not privided
    dolor: 'sit amet', // "dolor" is already a string
};

var r = inspector.sanitize(schema, c);
/*
r.data: {
    lorem: 10,
    ipsum: 'NikitaJS',
    dolor: 'sit amet'
}
*/

optional

  • type: boolean.
  • default: true.
  • usable on: any.

Property is set to schema.def if not provided and if optional is false.

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    properties: {
        lorem: { type: 'number', optional: false, def: 12 },
        ipsum: { type: 'string', optional: true, def: 23 },
        dolor: { type: 'string', def: 'NikitaJS', def: 34 }, // (optional: true)
    },
};

var c = {};

var r = inspector.sanitize(schema, c);
/*
r.data: {
    lorem: 12 // Only lorem is set to 12 because it is not optional.
}
*/

rules

  • type: string, array of string.
  • usable on: string.
  • possible values:
    • upper: Every character will be changed to uppercase.
    • lower: Every character will be changed to lowercase.
    • title: For each word (/\S*/g), first letter will be changed to uppercase, and the rest to lowercase.
    • capitalize: Only the first letter of the string will be changed to uppercase, the rest to lowercase.
    • ucfirst: Only the first letter of the string will be changed to uppercase, the rest is not modified.
    • trim: Remove extra spaces.

Apply the given rule to a string. If several rules are given (array), then they are applied in the same order than in the array.

sanitization min/max

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    properties: {
        lorem: { type: 'string', rules: 'upper' },
        ipsum: { type: 'string', rules: ['trim', 'title'] },
    },
};

var c = {
    lorem: ' tHiS is sParTa! ',
    ipsum: '   tHiS is sParTa!    ',
};

var r = inspector.sanitize(schema, c);
/*
r.data: {
    lorem: ' THIS IS SPARTA! ',
    ipsum: 'This Is Sparta!' // has been trimed, then titled
}
*/

min, max

  • type: string, number.
  • usable on: string, number.

Define minimum and maximum value for a property. If it's less than minimum, then it's set to minimum. If it's greater than maximum, then it's set to maximum.

sanitization min/max

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'array',
    items: { type: 'number', min: 10, max: 20 },
};

var c = [5, 10, 15, 20, 25];

var r = inspector.sanitize(schema, c);
/*
 r.data: [10, 10, 15, 20, 20]
 c[0] (5) was less than min (10), so it's been set to 10.
 c[4] (25) was greater than max (20), so it's been set to 20.
*/

minLength, maxLength

  • type: integer.
  • usable on: string.

Adjust string length to the given number.

TODO: We must be able to choose which character we want to fill the string with.

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'array',
    items: { type: 'string', minLength: 8, maxLength: 11 },
};

var c = ['short', 'mediumSize', 'tooLongForThisSchema'];

var r = inspector.sanitize(schema, c);
/*
 r.data: ['short---', 'mediumSize', 'tooLongForT']
*/

strict

  • type: boolean.
  • default: false.
  • usable on: any.

Only key provided in field "properties" will exist in object, others will be deleted.

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    strict: true,
    properties: {
        good: { type: 'string' },
    },
};

var c = {
    good: 'yes',
    bad: 'nope',
};

var r = inspector.sanitize(schema, c);
/*
r.data: {
    good: 'yes'
}
*/

exec

  • type: function, array of functions.
  • usable on: any.

Custom checker =). "exec" functions take two three parameter (schema, post [, callback]), and must return the new value. To report an sanitization, use this.report([message]). Very useful to make some custom sanitization.

NB: If you don't want to return a differant value, simply return post, do not return nothing (if you do so, the new value will be undefined).

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'array',
    items: {
        type: 'string',
        exec: function (schema, post) {
            if (typeof post === 'string' && !/^nikita$/i.test(post)) {
                this.report();
                return '_INVALID_';
            }
            return post;
        },
    },
};

var c = ['Nikita', 'lol', 'NIKITA', 'thisIsGonnaBeSanitized!'];

var r = inspector.sanitize(schema, c);
/*
 r.data: [ 'Nikita', '_INVALID_', 'NIKITA', '_INVALID_' ]
*/

properties

  • type: object.
  • usable on: object.

Work the same way as validation "properties".


items

  • type: object, array of object.
  • usable on: array.

Work the same way as validation "items".

Custom fields

punctual use

When you need to use the same function in exec field several time, instead of saving the function and declaring exec several times, just use custom field. First you have to provide a hash containing a function for each custom field you want to inject. Then you can call them in your schema with $"your field name". For example if you provide a custom field called "superiorMod", you can access it with name "$superiorMod".

Example

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    properties: {
        lorem: { type: 'number', $divisibleBy: 5 },
        ipsum: { type: 'number', $divisibleBy: 3 },
    },
};

var custom = {
    divisibleBy: function (schema, candidate) {
        var dvb = schema.$divisibleBy;
        if (candidate % dvb !== 0) {
            this.report('must be divisible by ' + dvb);
        }
    },
};

var c = {
    lorem: 10,
    ipsum: 8,
};
inspector.validate(schema, candidate, custom); // Invalid: "@.ipsum must be divisible by 3"

extension

Sometime you want to use a custom field everywhere in your program, so you may extend Schema-Inspector to do so. Just call the method inspector.Validation.extend(customFieldObject) or inspector.Sanitization.extend(customFieldObject). If you want to reset, simply call inspector.Validation.reset() or inspector.Sanitization.reset(). You also can remove a specific field by calling inspector.Validation.remove(field) or inspector.Sanitization.remove(field).

Example

var inspector = require('schema-inspector');

var custom = {
    divisibleBy: function (schema, candidate) {
        var dvb = schema.$divisibleBy;
        if (candidate % dvb !== 0) {
            this.report('must be divisible by ' + dvb);
        }
    },
};

var schema = {
    type: 'object',
    properties: {
        lorem: { type: 'number', $divisibleBy: 5 },
        ipsum: { type: 'number', $divisibleBy: 3 },
    },
};

inspector.Validation.extend(custom);

var candidate = {
    lorem: 10,
    ipsum: 8,
};

inspector.validate(schema, candidate);
/*
 As you can see, no more object than schema and candidate has been provided.
 Therefore we can use `$divisibleBy` everywhere in all schemas, for each
 inspector.validate() call.
*/

Context

Every function you declare as a custom parameter, or with exec field will be called with a context. This context allows you to access properties, like this.report() function, but also this.origin, which is equal to the object sent to inspector.validate() or inspector.sanitize().

Example

// ...
var schema = { /* ... */ };
var custom = {
    divisibleBy: function (schema, candidate) {
        // this.origin === [12, 23, 34, 45]
        // ...
    },
};
var candidate = [12, 23, 34, 45];
var result = inspector.validate(schema, candidate, custom);
// ...

Asynchronous call

How to

All of the examples above used synchronous calls (the simplest). But sometimes you want to call validation or sanitization asynchronously, in particular with exec and custom fields. It's pretty simple: To do so, just send a callback as extra parameter. It takes 2 parameters: error and result. Actually Schema-Inspector should send back no error as it should not throw any if called synchronously. But if you want to send back and error in your custom function, inspection will be interrupted, and you will be able to retrieve it in your callback.

You also have to declare a callback in your exec or custom function to make Schema-Inspector call it asynchronously, else it will be call synchronously. That means you may use exec synchronous function normally even during and asynchronous call.

Example

var inspector = require('schema-inspector');

var schema = { /* ... */ };
var candidate = { /* ... */ };

inspector.validate(schema, candidate, function (err, result) {
    console.log(result.format());
});

Example with custom field

var inspector = require('schema-inspector');

var schema = { /* ... */ };
var candidate = { /* ... */ };
var custom = { /* ... */ };

inspector.validate(schema, candidate, custom, function (err, result) {
    console.log(result.format());
});

Here is a full example where you may have to use it:

var inspector = require('schema-inspector');

var schema = {
    type: 'object',
    properties: {
        lorem: { type: 'number', $divisibleBy: 4 },
        ipsum: { type: 'number', $divisibleBy: 5 },
        dolor: { type: 'number', $divisibleBy: 0, optional: true },
    },
};

var custom = {
    divisibleBy: function (schema, candidate, callback) {
        // Third parameter is declared:
        // Schema-Inspector will wait this function to call this `callback` to keep running.
        var dvb = schema.$divisibleBy;
        if (typeof dvb !== 'number' || typeof candidate !== 'number') {
            return callback();
        }
        var self = this;
        process.nextTick(function () {
            if (dvb === 0) {
                return callback(
                    new Error('Schema error: Divisor must not equal 0')
                );
            }
            var r = candidate / dvb;
            if ((r | 0) !== r) {
                self.report('should be divisible by ' + dvb);
            }
            callback();
        });
    },
};

var candidate = {
    lorem: 12,
    ipsum: 25,
};

inspector.validate(schema, candidate, custom, function (err, result) {
    console.log(result.format());
});
Comments
  • fix: ๐Ÿ› use of the package in browsers

    fix: ๐Ÿ› use of the package in browsers

    closes: #93

    An export problem that occurs when using the package by bower in the browser makes it useless to use it in browsers.

    There is a validation to identify whether the environment is server-side or client-side in the file, but before this file is exported, it tries to use module.exports and require, as it does not have validation in the index.js file, at a time, it breaks and makes it impossible to use the package in the browser.

    The fix is simple, but it changes structure, it is necessary that index.js be the old file lib/schema-inspector.js.

    opened by ottonielmatheus 21
  • 1.6.9 breaks older version of Node

    1.6.9 breaks older version of Node

    @Atinux When upgrading dependencies from 1.6.8 to 1.6.9 (Async), this module breaks for older versions of Node.

    While I understand the changes, to indicate a lack of support for Node versions, you need to update a major version to not mess with semver and default installation to take latest minor version.

    Ultimately 1.6.9 should have been published as 2.0.0 dropping support for < v8

    opened by Mudrekh 14
  • Problem with sanitize an array of objects

    Problem with sanitize an array of objects

    Hi!

    I'm trying to sanitize an array of objects with a custom function using exec, but when I run the sanitization, nothing happens. If I use the same function but outside the array of objects, it works perfectly.

    This is my schema:

    
    var schema = {
        type: 'object',
        properties: {
            firstName: {
                type: 'string',
                rules: ['trim', 'title']
            },
            lastName: {
                type: 'string',
                rules: ['trim', 'title']
            },
            emails: {
                type: 'array',
                items: {
                    address: {
                        type: 'string',
                        rules: ['trim', 'lower']
                    }
                }
            },
            phones: {
                type: 'array',
                items: {
                    number: {
                        type: 'string',
                        exec: function(schema, post) {
                            return '+54' + post;
                        }
                    },
                    type: {
                        type: 'string'
                    }
                }
            }
        }
    };
    
    

    Any ideas of what can be wrong?

    Thanks! Luciano

    opened by LucianoGanga 13
  • Change version of async dep to ~2.6.3 for IE compatibility.

    Change version of async dep to ~2.6.3 for IE compatibility.

    @Atinux We've been sorting out the Node and IE compatibility issue in https://github.com/Atinux/schema-inspector/issues/77. By now, we've reached consensus that version 1.6.9 of schema-inspector accidentally had breaking changes because of its udnerlying async dependency.

    I think moving from the version 3 branch to version 2 branch of async is a great next step because it resolves the breaking changes issue and async's maintainers have committed to maintaining their version 2 branch with IE compatibility and it will receive patches for CVEs until further notice: https://github.com/caolan/async/issues/1661#issuecomment-634374314

    This PR changes us to 2.6.3 of async, and should keep us on the version 2 branch because of specifiying ~2.6.3. It doesn't use ^2.6.3, because we don't need new async features, just patches for CVEs. The PR does not increment the version of schema-inspector, because I notice you do the version increment in separate commits, so I'm respecting that pattern.

    opened by mattwelke 10
  • Sanitization

    Sanitization "exec" does not set new value as "undefined"

    I am using the "exec" function on a property that checks if a string follows a certain pattern, if it does not, I want the property to be deleted (or become "undefined").

    According to the documentation (https://github.com/Atinux/schema-inspector#s_exec), if I return "undefined", this will be the new value. This is not the behaviour I am getting: if I return undefined, the property just remains the same.

    My schema is similar to this:

    {
        type: 'string',
        optional: true,
        exec: (schema, post) => {
            if (isValid(post)) {
                 return post;
            } else {
                return undefined;
            }
        },
    }
    
    bug 
    opened by hscasn 7
  • Provide a global strict option

    Provide a global strict option

    Instead of requiring each object set it's strict option, it'd be handy to just have a global type strict option. Most of the time, if I want one of my object rules to be strict, I want them all to be strict.

    enhancement 
    opened by danwkennedy 7
  • run exec as first step to allow dynamic schema

    run exec as first step to allow dynamic schema

    set exec as the first attribute to make exec the first Validation/Sanitization step. By this way, all the schema could be modified by the exec Fn (not only properties & items for instance)

    Stale 
    opened by mmouterde 7
  • Avoid sanitization in some fields

    Avoid sanitization in some fields

    There is a way to avoid sanitization in some fields?

    I'm interested on sanitization to parse date strings into date object(otherwise, validation fails), but at the same time i don't want to sanitize other fields. I want them to fail.

    opened by YagoQuinoy 6
  • when element === nil this line throws TypeError: Cannot read property 'constructor' of null

    when element === nil this line throws TypeError: Cannot read property 'constructor' of null

    https://github.com/schema-inspector/schema-inspector/blob/af0ea2762525bf3bfe086ab9ddd3be0229dafcf5/lib/schema-inspector.js#L141

    Offered solution: change the order of conditions in this line.

    bug 
    opened by tevel 5
  • Sanitization of an object to array

    Sanitization of an object to array

    The example bellow works like a charm:

    // Data
    {
        tab: {
            prop: 'value'
        }
    }
    
    // Schema
    {
        type: 'object',
        properties: {
            tab: {
                type: 'array',
                optional: false,
                def: [],
                items: { type: 'object' }
            }
        }
    }
    
    // Result
    {
        "tab": [
            {
                "prop": "value"
            }
        ]
    }
    

    but, when the property is in the root of object, the sanitization do not work:

    // Data
    {
        prop: 'value'
    }
    
    // Schema
    {
        type: 'array',
        optional: false,
        def: [],
        items: { type: 'object' }
    }
    
    // Result
    {
        "prop": "value"
    }
    

    I was expecting this:

    [{
        "prop": "value"
    }]
    

    This is useful when you are receiving a REST body that the data can be only one object or an array of objects.

    Thank you.

    opened by conradoqg 5
  • Bump async from 2.6.3 to 3.2.0

    Bump async from 2.6.3 to 3.2.0

    Bumps async from 2.6.3 to 3.2.0.

    Changelog

    Sourced from async's changelog.

    v3.2.0

    • Fix a bug in Safari related to overwriting func.name
    • Remove built-in browserify configuration (#1653)
    • Varios doc fixes (#1688, #1703, #1704)

    v3.1.1

    • Allow redefining name property on wrapped functions.

    v3.1.0

    • Added q.pushAsync and q.unshiftAsync, analagous to q.push and q.unshift, except they always do not accept a callback, and reject if processing the task errors. (#1659)
    • Promises returned from q.push and q.unshift when a callback is not passed now resolve even if an error ocurred. (#1659)
    • Fixed a parsing bug in autoInject with complicated function bodies (#1663)
    • Added ES6+ configuration for Browserify bundlers (#1653)
    • Various doc fixes (#1664, #1658, #1665, #1652)

    v3.0.1

    Bug fixes

    • Fixed a regression where arrays passed to queue and cargo would be completely flattened. (#1645)
    • Clarified Async's browser support (#1643)

    v3.0.0

    The async/await release!

    There are a lot of new features and subtle breaking changes in this major version, but the biggest feature is that most Async methods return a Promise if you omit the callback, meaning you can await them from within an async function.

    const results = await async.mapLimit(urls, 5, async url => {
        const resp = await fetch(url)
        return resp.body
    })
    

    Breaking Changes

    • Most Async methods return a Promise when the final callback is omitted, making them await-able! (#1572)
    • We are now making heavy use of ES2015 features, this means we have dropped out-of-the-box support for Node 4 and earlier, and many old versions of browsers. (#1541, #1553)
    • In queue, priorityQueue, cargo and cargoQueue, the "event"-style methods, like q.drain and q.saturated are now methods that register a callback, rather than properties you assign a callback to. They are now of the form q.drain(callback). If you do not pass a callback a Promise will be returned for the next occurrence of the event, making them await-able, e.g. await q.drain(). (#1586, #1641)
    • Calling callback(false) will cancel an async method, preventing further iteration and callback calls. This is useful for preventing memory leaks when you break out of an async flow by calling an outer callback. (#1064, #1542)
    • during and doDuring have been removed, and instead whilst, doWhilst, until and doUntil now have asynchronous test functions. (#850, #1557)
    • limits of less than 1 now cause an error to be thrown in queues and collection methods. (#1249, #1552)
    • memoize no longer memoizes errors (#1465, #1466)
    • applyEach/applyEachSeries have a simpler interface, to make them more easily type-able. It always returns a function that takes in a single callback argument. If that callback is omitted, a promise is returned, making it awaitable. (#1228, #1640)

    New Features

    • Async generators are now supported in all the Collection methods. (#1560)
    • Added cargoQueue, a queue with both concurrency and payload size parameters. (#1567)
    • Queue objects returned from queue now have a Symbol.iterator method, meaning they can be iterated over to inspect the current list of items in the queue. (#1459, #1556)

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 4
  • Delete stale GHA workflow.

    Delete stale GHA workflow.

    We don't have frequent enough contributions to address bugs and feature requests. So having a workflow that marks issues as stale just causes issues where we have to consantly unmark them. And if we forget, issues get closed automatically. We're better off without the workflow for now.

    opened by mattwelke 1
  • Email Pattern May Be Too Strict

    Email Pattern May Be Too Strict

    It appears that the email pattern that was generated with email-regex-safe was done so with the gmail option enabled which results in a regex that prevents - and _. I think this may be too strict for a general email validator. Is it possible to regenerate the regex with the gmail option disabled?

    Specifically, the gmail rules include the following

    can contain letters (a-z), numbers (0-9), and periods (.). cannot contain an ampersand (&), equals sign (=), underscore (_), apostrophe ('), dash (-), plus sign (+), comma (,), brackets (<,>), or more than one period (.) in a row

    https://github.com/spamscanner/email-regex-safe/blob/master/src/index.js#L40-L47

    I believe underscore and dash should be allowed in the email.

    bug 
    opened by joshwils82 8
  • Replace use of async dependency with native async code

    Replace use of async dependency with native async code

    Since ES6 came out, we have native language tools for managing async work, like Promise and Promise.all. We can remove a dependency to simplify using the library and increase its maintainability by replacing async with these native tools. If when attempting this, we find that async provides good value compared to native code alone (and we'd be reinventing the wheel), then we can keep it.

    Stale maintainability 
    opened by mattwelke 2
Releases(v2.0.2)
  • v2.0.2(Nov 21, 2022)

    What's Changed

    • remove lockfile, add .npmignore by @mattwelke in https://github.com/schema-inspector/schema-inspector/pull/100
    • Clean up package.json by @Yash-Singh1 in https://github.com/schema-inspector/schema-inspector/pull/101
    • Switch to GitHub Actions from Travis for running tests by @Yash-Singh1 in https://github.com/schema-inspector/schema-inspector/pull/103
    • Switch from Make to NPM for tests by @mattwelke in https://github.com/schema-inspector/schema-inspector/pull/137
    • Add linting with semistandard by @mattwelke in https://github.com/schema-inspector/schema-inspector/pull/138
    • Bump mocha from 8.4.0 to 10.0.0 by @dependabot in https://github.com/schema-inspector/schema-inspector/pull/136
    • Add "Comparison with JSON Schema" to README by @Yash-Singh1 in https://github.com/schema-inspector/schema-inspector/pull/111
    • package.json, GitHub Actions cleanup by @mattwelke in https://github.com/schema-inspector/schema-inspector/pull/139
    • fix undefined return on exec in "properties" by @mattwelke in https://github.com/schema-inspector/schema-inspector/pull/141
    • Change order of object type detection by @mattwelke in https://github.com/schema-inspector/schema-inspector/pull/142

    Full Changelog: https://github.com/schema-inspector/schema-inspector/compare/v2.0.1...v2.0.2

    Source code(tar.gz)
    Source code(zip)
  • v2.0.1(Nov 11, 2022)

    What's Changed

    • Fix links and lint markdown by @Yash-Singh1 in https://github.com/schema-inspector/schema-inspector/pull/96
    • Typo by @Yash-Singh1 in https://github.com/schema-inspector/schema-inspector/pull/98
    • Add updated Bower documentation. by @mattwelke in https://github.com/schema-inspector/schema-inspector/pull/99
    • Implement sanatize.strict on custom classes by @Yash-Singh1 in https://github.com/schema-inspector/schema-inspector/pull/97

    Full Changelog: https://github.com/schema-inspector/schema-inspector/compare/2.0.0...v2.0.1

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Mar 14, 2021)

    To fix a security vulnerability (CVE-2021-21267) in the 1.x.x email Regex expression used, a new Regex expression was used which may be less flexible than the expression used in 1.x.x. Therefore, version 2.0.0 was released with this new expression. It's highly-recommended to upgrade to this new version after testing it.

    If you need the old, insecure behavior, use version 1.x.x or use the custom validation function feature for your field and perform email address validation any way you like.

    Source code(tar.gz)
    Source code(zip)
  • 1.7.0(Jun 10, 2020)

    • Adds support for v4 UUID strings (ex. a4c46b74-cf00-4cd0-9100-e121ce4b67de) using regex. See README for usage example. See https://github.com/Atinux/schema-inspector/pull/79 (PR by @ViniciusFXavier )
    Source code(tar.gz)
    Source code(zip)
  • v1.6.10(Jun 1, 2020)

  • v1.6.9(Jan 20, 2020)

  • v1.6.8(Nov 11, 2016)

  • v1.6.7(Nov 10, 2016)

Convert JSON examples into JSON schema (supports Swagger 2, OpenAPI 3 and 3.1)

json-to-json-schema Convert JSON examples into JSON schema. Supports JSON Schema draft-05 used in Swagger 2.0 and OpenAPI 3.0 and new draft draft-2020

Redocly 9 Sep 15, 2022
TypeScript-first schema validation for h3 and Nuxt applications

h3-zod Validate h3 and Nuxt 3 requests using zod schema's. Install npm install h3-zod Usage import { createServer } from 'http' import { createApp } f

Robert Soriano 48 Dec 28, 2022
Dead simple Object schema validation

Yup Yup is a JavaScript schema builder for value parsing and validation. Define a schema, transform a value to match, validate the shape of an existin

Jason Quense 19.2k Jan 2, 2023
Schema validation utilities for h3, using typebox & ajv

h3-typebox JSON schema validation for h3, using typebox & ajv. Install # Using npm npm install h3-typebox # Using yarn yarn install h3-typebox # Usi

Kevin Marrec 43 Dec 10, 2022
FieldVal - multipurpose validation library. Supports both sync and async validation.

FieldVal-JS The FieldVal-JS library allows you to easily validate data and provide readable and structured error reports. Documentation and Examples D

null 137 Sep 24, 2022
Tiny Validator for JSON Schema v4

Tiny Validator (for v4 JSON Schema) Use json-schema draft v4 to validate simple values and complex objects using a rich validation vocabulary (example

Geraint 1.2k Dec 21, 2022
Validate for XML schema and returns all the possible failures

detailed-xml-validator Validate for XML schema and returns all the possible failures Sample Rules file <?xml version = "1.0"?> <students nillable="fa

Natural Intelligence 11 Dec 20, 2022
Validate graphql operations against a schema

@graphql-validate With the power of GraphQL-Tools and GraphQL-JS, we are able to provide a smooth experience for validation your GraphQL operations du

Saihajpreet Singh 13 Dec 23, 2022
:white_check_mark: Easy property validation for JavaScript, Node and Express.

property-validator โœ… Easy property validation for JavaScript, Node and Express Built on top of validator.js, property-validator makes validating reque

Netto Farah 160 Dec 14, 2022
Lightweight and powerfull library for declarative form validation

Formurai is a lightweight and powerfull library for declarative form validation Features Setup Usage Options Methods Rules Examples Roadmap Features ?

Illia 49 May 13, 2022
Facile is an HTML form validator that is inspired by Laravel's validation style and is designed for simplicity of use.

Facile is an HTML form validator that is inspired by Laravel's validation style and is designed for simplicity of use.

upjs 314 Dec 26, 2022
Simple, smart and pleasant validation solution.

nice-validator Simple, smart and pleasant validation solution. Download the latest release or install package via npm or bower $ npm install nice-vali

Jony 608 Nov 18, 2022
Themis is a validation and processing library that helps you always make sure your data is correct.

Dataffy Themis - The advanced validation library Themis is a validation and processing library that helps you always make sure your data is correct. ยท

Dataffy 14 Oct 27, 2022
jQuery Validation Plugin library sources

jQuery Validation Plugin - Form validation made easy The jQuery Validation Plugin provides drop-in validation for your existing forms, while making al

null 10.3k Jan 3, 2023
String validation

validator.js A library of string validators and sanitizers. Strings only This library validates and sanitizes strings only. If you're not sure if your

null 20.7k Jan 5, 2023
Lightweight JavaScript form validation library inspired by CodeIgniter.

validate.js validate.js is a lightweight JavaScript form validation library inspired by CodeIgniter. Features Validate form fields from over a dozen r

Rick Harrison 2.6k Dec 15, 2022
Cross Browser HTML5 Form Validation.

Validatr Cross Browser HTML5 Form Validation. Getting Started View the documentation to learn how to use Validatr. Changelog Version 0.5.1 - 2013-03-1

Jay Morrow 279 Nov 1, 2022
jQuery Validation Plugin library sources

jQuery Validation Plugin - Form validation made easy The jQuery Validation Plugin provides drop-in validation for your existing forms, while making al

null 10.3k Jan 3, 2023