pinput
v1.1.3
Published
Fluent API parameter validation
Downloads
14
Readme
pinput
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'smessageOnBroken
propertyerror.status (
number
) — Copied from the configuration'sstatusOnBroken
propertyerror.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.