0.11.1 • Published 2 years ago

nodejs-schema-validator v0.11.1

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

nodejs-schema-validator

version CircleCI MIT License

NodeJS validation middleware for express router using schemas for both body and url parameters.

This library allows you to use any validation library, even your own. Examples are using validator

Table of contents

  1. Installation
  2. Basic usage
  3. Schema structure
  4. Optional fields
  5. Validating both body and parameters
  6. Custom validation output
  7. Using field values in messages
  8. Async/await validation
  9. Cross field validation
  10. Conditional validation
  11. Using sanitizers
  12. Contributing

Installation

npm i nodejs-schema-validator

Basic usage

This validates a post request by looking into req.body for email value.

// Import SchemaValidator
const SchemaValidator = require('nodejs-schema-validator');

// Import a validator library of your choice
const validator = require('validator');

// Create a new schema validator instance
const schemaValidatorInstance = new SchemaValidator();

// Define your schema (or import it from a dedicated file)
const userEmailSchema = {
    email: {
        rules: [
            {
                rule: (input) => !input || validator.isEmpty('input'),
                message: 'Email address is required'
            },
            {
                rule: (input) => !validator.isEmail(input),
                message: 'This is not a valid email address'
            }
        ]
    }
};

// Add body schema validator as a middleware to your router endpoints
router.post(
    '/user/:id',
    schemaValidatorInstance.validateBody(userEmailSchema),
    (req, res) => { /* Data is valid, add your logic */ }
);

Schema structure

Here's a breakdown of how the schema is structured:

// Schema is an object containing the fields we want to validate from req.body
const schemaExample = {
    name: {
        // A field can have multiple rules
        rules: [
            // A rule contains the validation function and a message for failure
            {
                rule: (input) => !input || validator.isEmpty(input),
                message: 'Name is required'
            },
            {
                rule: (input) => !validator.isLength(3, 20),
                message: 'Name should have a length between 3 and 20 characters'
            }
        ]
    },
    bitcoin_address: {
        // Some fields can be optional
        optional: true,
        rules: [
            rule: (input) => !validator.isBtcAddress(input),
            message: 'This is not a valid Bitcoin address'
        ]
    }
};

Optional fields

Marking fields as optional will validate only when they are not empty.

const schema = {
    vatNo: {
        // Some fields can be optional
        optional: true,
        rules: [
            rule: (input) => !validator.isValidVatNo(input),
            message: 'Please insert a valid VAT number of leave empty'
        ]
    }
};

Validating both body and parameters

Example of how to validate both body and url parameters

// Schema for validating id as a valid UUID v4
const userParamSchema = {
    id: {
        rules: [
            {
                rule: (input) => !validator.isUUID(input, 4),
                message: 'User ID should be a valid v4 UUID'
            }
        ]
    }
};

const userBodySchema = {
    name: {
        rules: [
            {
                rule: (input) => !input || input === '',
                message: 'User name is mandatory'
            }
        ]
    }
};

// This validates user data
router.post(
    '/user/',
    schemaValidatorInstance.validateBody(userBodySchema),
    (req, res) => { /* Your logic */ }
);

// This validates both user id and user data
router.put(
    '/user/:id',
    schemaValidatorInstance.validateParams(userParamSchema),
    schemaValidatorInstance.validateBody(userBodySchema),
    (req, res) => { /* Your logic */ }
)

Custom validation output

Validation failure returns status code 422 with a body in this format:

{
    "message": [
        {
            "field": "name",
            "message": "Name is required"
        }
    ]
}

In case you want to customize the output and status code of the failure you can pass a function in the SchemaValidator constructor:

// Define your function in this format
const myCustomValidationOutput = (req, res, errors) => {
    res.status(422).json({ message: errors });
};

// Pass it in constructor
const schemaValidatorInstance = new SchemaValidator(myCustomValidationOutput);

Using field values in messages

Field names wrapped in double curly braces will be replaced with their values. Please note that there should be no space between the field name and the braces.

const schema = {
    amount: {
        rules: [
            {
                rule: async (input) => amount < 100,
                message: 'You entered {{amount}} but should be at least 100'
            }
        ]
    }
};

Async/await validation

Schema rules support async methods. Here's an example:

const schema = {
    email: {
        rules: [
            {
                rule: async (input) => await emailExists(input),
                message: 'Email address {{email}} already exists'
            }
        ]
    }
};

Cross field validation

Validation rules can depend on other values:

const schema = {
    min: {
        rules: [
            {
                rule: (input) => !input,
                message: 'Min is required'
            }
        ]
    },
    max: {
        rules: [
            {
                rule: (input) => !input,
                message: 'Max is required'
            }
        ]
    },
    value: {
        rules: [
            {
                rule: (input, { min, max }) => input < min || input > max,
                message: 'This field must be between {{min}} and {{max}}'
            }
        ]
    }
};

Conditional validation

Fields and rules can have validation skipped based on conditions using when function. Validation skips in case it returns false.

const schema = {
     type: {
        rules: [
            {
                rule: (input) => !input || input === '',
                message: 'Type is required'
            }
        ]
    },
    resolution: {
        rules: [
            {
                rule: (input) => !input || input === '',
                message: 'Resolution is required',
                // Only validate this rule when type is 'monitor'
                when: ({ type }) => type === 'monitor'
            }
        ]
    },
    watts: {
        // Only validate this field when type is 'speaker'
        when: ({ type }) => type === 'speaker',
        rules: [
            {
                rule: (input) => !input || input === '',
                message: 'Power in watts is required',
            }
        ]
    }
}

Using sanitizers

You can add an array of sanitizers that will be processed after validation:

const lowercaseSanitizer = (input) => input.toLowerCase();
const reverseSanitizer = (input) => input.split('').reverse().join('');

const schema = {
    name: {
        rules: [
            {
                rule: async (input) => !input,
                message: 'Name is required'
            }
        ],
        sanitizers: [
            lowercaseSanitizer,
            reverseSanitizer
        ]
    }
};

Example payload:

{ name: 'ELON MUSK' }

Sanitized output:

{ name: 'ksum nole' }

Contributing

Pull requests are welcome. Run tests with:

npm run test

License (MIT)

Copyright (c) 2021 Angelin Sirbu <angelin.sirbu@yahoo.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0.11.0

2 years ago

0.11.1

2 years ago

0.10.4

2 years ago

0.10.3

2 years ago

0.10.2

2 years ago

0.10.1

2 years ago

0.10.0

2 years ago

0.9.6

2 years ago

0.9.5

2 years ago

0.9.2

2 years ago

0.9.1

2 years ago

0.9.0

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago