@fczbkk/config-mask
v1.16.0
Published
Helper that takes care of validating, sanitizing and coercing of complex config objects.
Downloads
7
Readme
Config Mask
Helper that takes care of validating, sanitizing and coercing of complex config objects.
How to use
Install the library via NPM:
npm install @fczbkk/config-mask --save
Then use in your project like this:
import ConfigMask from '@fczbkk/config-mask';
Simple value
The simplest use is a coercion of input value.
var numeric_value = new ConfigMask({
type: 'number',
default: 0
});
// use default value when input is missing
numeric_value.sanitze(); // 0
// use default value when input is invalid
numeric_value.sanitize('xxx'); // 0
// use valid value
numeric_value.sanitize(100); // 100
// convert value to expected type if possible
numeric_value.sanitize('100'); // 100
Any value
You can use type any
to accept any type of input. It will not check the type nor sanitize it to any specific type.
var any_value = new ConfigMask({
type: 'any'
});
any_value.sanitize(); // undefined
any_value.sanitize('aaa') // 'aaa'
any_value.sanitize(123) // '123'
You can still use any other options. For example default value, which will be used when input is undefined:
var any_value = new ConfigMask({
type: 'any',
default: 'n/a'
});
any_value.sanitize(); // 'n/a'
any_value.sanitize('aaa') // 'aaa'
Or you can use parser to transform input value:
var any_value = new ConfigMask({
type: 'any',
parse: function (input) {return typeof input;}
});
any_value.sanitize(); // 'undefined'
any_value.sanitize('aaa') // 'string'
Set
You can define set of valid values that can be used.
var set_value = new ConfigMask({
type: 'set',
values: ['aaa', 'bbb'],
default: 'aaa'
});
// use valid value
set_value.sanitize('aaa'); // 'aaa'
// use default value on missing or invalid input
set_value.sanitize(); // 'aaa'
set_value.sanitize('xxx'); // 'aaa'
If you don't set default value, first of the valid values will be used:
var set_value = new ConfigMask({
type: 'set',
values: ['aaa', 'bbb']
});
set_value.sanitize(); // 'aaa'
List
Same as set
, but for lists of values from defined set.
var list_value = new ConfigMask({
type: 'list',
values: ['aaa', 'bbb']
});
// valid values are fine, invalid ones are filtered out
list_value.sanitize(['aaa', 'xxx', 'bbb']); // ['aaa', 'bbb']
// single value is converted to array
list_value.sanitize('aaa'); // ['aaa']
// default value is always empty array
list_value.sanitize(); // []
List of...
Type list_of
will produce an array with values of specific type.
- You can use
subtype
property to define type of values in array. - You can use
submask
property to define ConfigMask that will be applied to values in array. - If both
subtype
andsubmask
properties are defined,submask
will be used. - If neither
subtype
norsubmask
property is defined, the array will accept values of any types.
var list_of_strings = new ConfigMask({
type: 'list_of',
subtype: 'text'
});
list_of_strings.sanitize(['aaa', null, 123]); // ['aaa', '', '123']
var list_of_objects = new ConfigMask({
type: 'list_of',
submask: {
type: 'object',
properties: {
value: 'number',
unit: 'text'
},
default: {
value: 0,
unit: 'px'
}
}
});
list_of_objects.sanitize([{value: 10, unit: 'cm'}, 'xxx']);
// [{value: 10, unit: 'cm'}, {value: 0, unit: 'px'}]
You can use filter
property to define function for filtering out unwanted values.
var list_of_short_strings = new ConfigMask({
type: 'list_of',
subtype: 'text',
filter: function (input) {return input.length <= 3;}
});
list_of_short_strings.sanitize(['aaa', 'abcdefgh', 'bbb']); // ['aaa', 'bbb']
Custom value types
You can write your own value types, using Coerce.
var array_of_strings = new ConfigMask({
type: {
string: function (input) {
return [input];
},
array: function (input) {
return input.map(function (item) {
return item.toString();
})
}
},
default: []
});
array_of_strings.sanitize(); // []
array_of_strings.sanitize('aaa'); // ['aaa']
array_of_strings.sanitize(['aaa', 'bbb']); // ['aaa', 'bbb']
Custom validation
You can create masks with very specific rules using custom validation method.
var positive_number = new ConfigMask({
type: 'number',
validate: function (input) {return number > 0;},
default: 1
});
positive_number.sanitize(10); // 10
positive_number.sanitize(-10); // 1 (default value)
To simplify debugging or error reporting, you can use on_invalid
method. It will be called when sanitizing the input and it will receive the input as parameter.
var positive_number = new ConfigMask({
type: 'number',
validate: function (input) {return number > 0;},
on_invalid: function (input) {
console.log('Only positive numbers allowed. You have used ' + input + '.');
},
default: 1
});
In some cases, it may be helpful to validate the result after it has been sanitized. For example when dealing with complex objects with various sub-properties, where the end result of sanitation may depend on results of sanitation of properties.
var value_with_unit = ConfigMask({
type: 'object',
properties: {
value: {type: 'number'},
unit: {type: 'string'}
},
default: null,
validate_after: function (input) {
// if either `value` or `unit` is not set, sanitize to `nul` (default value)
return input.value !== 0 && value.unit !== '';
}
});
Simple objects
You can simply set the value to be an object:
var my_object = new ConfigMask({
type: 'object'
});
my_object.sanitize(); // {}
my_object.sanitize('aaa'); // {}
my_object.sanitize({aaa: 'bbb'}); // {aaa: 'bbb'}
You can define a list of properties that the resulting object should have. Properties not on the list will be ignored. Missing properties will be added with undefined
value:
var person_name = new ConfigMask({
type: 'object',
properties: ['first_name', 'last_name']
});
var sanitized_name = person_name.sanitize({
first_name: 'John',
occupation: 'programmer'
});
sanitized_name.first_name; // 'John'
sanitized_name.last_name; // undefined
sanitized_name.occupation; // undefined (ignored)
Complex objects
This is why I created ConfigMask. Sanitize complex configuration objects without going through all the properties and checking them manually.
var value_config = {
type: 'number',
default: 0
};
var unit_config = {
type: 'set',
values: ['px', '%'],
default: 'px'
};
var size_config = new ConfigMask({
type: 'object',
properties: {
value: value_config,
unit: unit_config
}
});
// use default values when input is missing
size_config.sanitize(); // {value: 0, unit: 'px'}
// add missing properties
size_config.sanitize({value: 100}); // {value: 100, unit: 'px'}
// ignore unknown properties
size_config.sanitize({xxx: 'yyy'}); // {value: 0, unit: 'px'}
Keep properties
By default, all undefined properties will be removed:
var my_config = {
type: 'object',
properties: {
aaa: 'text'
}
}
// property `ccc` will be removed
my_config.sanitize({aaa: 'bbb', ccc: 'ddd'}); // {aaa: 'bbb'}
If you want to keep undefined properties intact, add keep_property
to config with truthy value:
var my_config = {
type: 'object',
properties: {
aaa: 'text'
},
keep_properties: true
}
// property `ccc` will remain unchanged
my_config.sanitize({aaa: 'bbb', ccc: 'ddd'}); // {aaa: 'bbb', ccc: 'ddd'}
Nesting
You can nest ConfigMask objects together, creating very complex and interconnected types.
// Both of these objects work as standalone config mask...
var value_config = new ConfigMask({
type: 'number',
default: 0
});
var unit_config = new ConfigMask({
type: 'set',
values: ['px', '%'],
default: 'px'
});
// ... but they are also used in this config mask to create more complex type.
var size_config = new ConfigMask({
type: 'object',
properties: {
value: value_config,
unit: unit_config
}
});
Combined configs
If you need to accept various input types in configs, you can use "combined" type. It will sanitize input value through all the submasks and use first non-null result.
var navigation_config = {
type: 'set',
values: ['previous', 'next'],
default: null
};
var index_config = {
type: 'number',
default: 0
}
var combined_config = new ConfigMask({
type: 'combined',
submasks: [navigation_config, index_config]
});
combined_config.sanitize('previous'); // 'previous'
combined_config.sanitize(123); // 123
combined_config.sanitize('xxx'); // 0
Cloning to make variations
Sometimes you want to create a variation of existing ConfigMask. For example, you want the same config, but different default value. The easy way to do this is to use clone()
method.
var person_age = new ConfigMask({
type: 'number',
default: 0
});
var old_person_age = person_age.clone({default: 60});
person_age.sanitize('xxx'); // 0
old_person_age.sanitize('xxx'); // 60
Documentation
Configuration
ConfigMask's configuration object.
Properties
type
[(string | Object)] Identifier of item type (e.g. "number", "array") or custom config for Coerce object (https://github.com/InlineManual/coerce/).default
[any] Default value to be used when input is invalid or missing.values
[Array] Iftype
is "set", this is the list of valid values.properties
[Object] Iftype
is "object", this is the list of its properties. The values should beConfiguration
objects.keep_properties
[boolean] If type is "object" and "properties" are defined, unspecified properties of the object will not be removed.submasks
[Array<(Configuration | ConfigMask)>] List of sub-masks to be used when type is set to "combined". Sub-masks are evaluated in given order. First one that returns non-null value is used.submask
[(Configuration | ConfigMask)] Mask to be used when type is set tolist_of
. This property has priority oversubtype
subtype
[(string | Object)] Type of value allowed to be used when type is set tolist_of
.parse
[Function] If set, it will be used to transform input before it is being sanitized.validate
[Function] When sanitizing, passes parsed input through validator. If it does not pass, default value is used instead.validate_after
[Function] Same asvalidate
, but applied after the sanitation is done. This is useful for complex object types, where end result of sanitation may depend on result of sanitation of some of the properties.on_invalid
[Function] Called when input is evaluated as invalid when sanitizing.filter
[Function] If set, it will be used bylist_of
type to filter out values from result.
ConfigMask
Class representing ConfigMask.
constructor
Create ConfigMask.
Parameters
config
[Configuration](default {})
setOptions
Sets object's options.
Parameters
config
Configuration
updateOptions
Adds new properties and replaces existing properties in object's options.
Parameters
config
Configuration
sanitize
Applies config mask to input and returns sanitized value.
Parameters
input
[any]param
[any] Parameter that will be added to all subsequent calls ofsanitize()
,parse()
andvalidate()
.
Returns any
parse
Apply parse function on input, return unchanged input if not set.
Parameters
input
param
any Will be passed as second parameter to the parse function.
Examples
Add prefix to all texts.
var prefixed_text = new ConfigMask({
type: 'text',
parse: function (input) {return 'bbb' + input;}
});
prefixed_text.sanitize('aaa'); // 'aaabbb'
Returns any
validate
Validates input. Used to check parsed input before being used in sanitation.
Parameters
input
param
any Will be passed as second parameter to the validate function.validation_function
[Function](default this._options.validate) Function to be used to validate input.
Examples
Limit maximum length of input.
var max_three_characters = new ConfigMask({
type: 'text',
validate: function (input) {return input.length <= 3;}
});
max_three_characters.sanitize('aaa'); // 'aaa'
max_three_characters.sanitize('aaabbb'); // ''
Returns boolean
clone
Creates exact copy of original object, updates the options with new ones.
Parameters
config
[Configuration](default {})
Returns ConfigMask
ensureArray
Makes sure that input is an array. If input is undefined, an empty array is returned.
Parameters
input
any
Returns Array
applyFilter
If filter function is defined, applies it to data. Otherwise returns data unchanged.
Parameters
Returns Array
Bug reports, feature requests and contact
If you found any bugs, if you have feature requests or any questions, please, either file an issue at GitHub or send me an e-mail at [email protected].
License
Config Mask is published under the MIT license.