1.1.3 • Published 7 years ago

pinput v1.1.3

Weekly downloads
7
License
MIT
Repository
github
Last release
7 years ago

pinput

Travis Coveralls Code Climate npm

Fluent API parameter validation with 0 dependencies

pinput was written to make working with API input easy. Get started by adding the project to your dependencies:

$ npm install pinput --save

Usage

Parameter

Parameter is typically used to validate some input from an API endpoint. Here's a basic example of using pinput in an Express app:

let Parameter = require('pinput');

let validateName = function(input) {
    // Let's say for simplicity a name is a string of alphabetic characters and spaces
    return /^[A-Z ]$/i.test(input);
};

app.get('/person/:name', function(req, res, next) {
    // Let's create a minimal Parameter to validate a name
    let name = new Parameter({
        name: 'name',
        rawInput: req.params.name,
        validate: validateName,
        errorMessage: 'your message here'
    });

    if (!name.valid) {
        // name.error is populated with some useful error information
        return next(name.error);
    }

    res.json(...);
});

What if we need to add an optional parameter? This is pretty straightforward with pinput, add optional: true to your configuration:

app.get('/my-endpoint', function(req, res, next) {
    let foo = new Parameter({
        name: 'foo',
        rawInput: req.query.foo,
        validate: fooValidationFunction,
        errorMessage: 'I was required!'
    });
    let bar = new Parameter({
        name: 'bar',
        rawInput: req.query.bar,
        validate: barValidationFunction,
        errorMessage: "Even if req.query.bar is undefined, I'll still be valid!",
        optional: true
    });

    assert.ok(foo.valid);
    assert.ok(bar.valid);

    // Send response here
});

This way, even if the user did not pass a value for 'bar', its Parameter will still be valid.

pinput also supports array input. Let's say we need an endpoint that validates a list of names. All we need to do is add to our configuration:

app.get('/my-endpoint', function(req, res, next) {
    let names = new Parameter({
        name: 'names',
        rawInput: req.query.names,
        validate: namesValidationFunction,
        errorMessage: 'your message here',
        array: true
    });

    assert.ok(Array.isArray(names.value));
});

By default, arrays are split by commas, but this can be changed by specifying the arraySeparator property.

Let's say we need to take a number as input from our API. pinput makes this very simple with the postprocess property:

let parseBase10Int = function(input) {
    return parseInt(input, 10);
};

app.get('/my-endpoint', function(req, res, next) {
    let number = new Parameter({
        name: 'number',
        rawInput: req.query.number,
        validate: validateInputCanBeParsedAsNumber,
        postprocess: parseBase10Int
    });

    assert.equal(typeof number.value, 'number');
});

Protip: Use postprocess with array: true to process a list of numbers

See the full configuration below for more options.

Contract

A Contract is a binding between to Parameters. Contracts are only applied after Parameters have been validated.

let Contract = require('pinput/contract');

router.get('/range', function(req, res, next) {
    let start = new Parameter({
        name: 'start',
        // ...
    })
    let end = new Parameter{
        name: 'end',
        // ...
    });

    if (!name.valid || !end.valid) {
        // handle invalid Parameters here
    }

    let contract = new Contract({
        names: ['start', 'end'],
        verify: (start, end) => start <= end,
        messageOnBroken: 'start must be less than or equal to end'
    });

    contract.check([start, end]);

    if (!contract.valid) {
        // handle broken contract here
    }
});

Full Reference

Parameter

Configuration

These properties are recognized by Parameter when passed as an object, e.g.

let configuration = {
    name: 'foo',
    // ...
};
let p = new Parameter(configuration);

name (string) (required)

rawInput (string) (required) Raw input from the user. May be undefined.

validate (function) (required) A function that takes the raw input as a parameter and returns any value. If that value is truthy, this Parameter is considered valid. If that value is falsey, then this Parameter is considered invalid. Note that there are some exceptions to this rule. If optional is truthy and the raw input is undefined, then this function will not be called. Similarly, if defaultAllowed is truthy and this function returns a falsey value, the Parameter will be considered valid anyway.

errorMessage (string|function) A message to be shown to the user if this Parameter is invalid. May also be a function that takes the configuration as a parameter.

errorStatus (number) Recommended HTTP status code to send to the client if this Parameter is invalid. Defaults to 400 ("Bad Request").

optional (boolean) If truthy, marks this Parameter as not required. Simply, if rawInput is undefined, this Parameter will be valid.

array (boolean) If truthy, the value of this Parameter is meant to be treated as an array. Defaults to false.

arraySeparator (string) If array, will split() the value by this string. Defaults to ','

arrayTrim (boolean) If array, will trim() every element after splitting. Defaults to true.

defaultAllowed (boolean) If the input is determined to be invalid, defaultValue will be used instead. Defaults to false.

defaultValue (*) The value used if the input for this Parameter is invalid or undefined, and defaultAllowed is truthy. Defaults to null.

preprocess (function) A one-argument function that takes the value of the Parameter and returns a modified value. If array is truthy, then this function will be called with each element of the array. Defaults a function that returns the value it's passed.

postprocess (function) Similar to preprocess, but is only called after successful validation. Defaults to a function that returns the value it's passed.

Properties

name (string) Copied straight from the configuration

valid (boolean)

optional (boolean) Boolean value of the configuration's optional property. Will always be a boolean.

error (object) Null if valid

  • error.message Copied straight from the configuration's errorMessage property
  • error.code Copied straight from the configuration's errorStatus property
  • error.data An object with one property whose key is the name of the Parameter and whose value is the value of the Parameter

Contract

Functions

apply Takes an array of Parameters as input. Two of those Parameters must have names such that p1Name === parameter.name. Creates the valid and error properties in the Contract.

Configuration

These properties are recognized by Contract when passed as an object, e.g.

let configuration = {
    name: 'foo',
    // ...
};
let c = new Contract(configuration);

names (string[]) (required) List of parameter names. Each value should be equal to a Parameter's name.

verify (function) (required) Checks if the agreement between the Parameters have broken the agreement. If this function returns a truthy value, this Contract is intact. Similarly, if this function returns a falsey value, this Contract is considered broken. Arguments to this function are the values of the Parameters specified by names.

messageOnBroken (string) (required) Value of contract.error.message when broken

statusOnBroken (number) Value of contract.error.status when broken. Defaults to 400.

Properties

names (string[]) Copied from the configuration

valid (boolean)

error (object) Null if valid

  • error.message (string) Copied from the configuration's messageOnBroken property

  • error.status (number) Copied from the configuration's statusOnBroken property

  • error.data (object) An object with two properties, each key being the name of the Parameter being analyzed and each value being the value of that Parameter

Contributing

pinput is built with Grunt. The default Grunt task runs the unit tests and jshint.

Legal

Copyright 2017 Matthew Dean via MIT license.

See the LICENSE file for full license.

1.1.3

7 years ago

1.1.1

7 years ago

1.1.0

7 years ago

1.0.0

7 years ago