apom.js
Asynchronous Partial Object Match provides asynchronous functions to determine if chosen properties between javascript object literals match. A match between properties can be equal value and type (default), a regular expression test, a missing property, a custom match function or a combination of those for different properties.
Install with npm install apom
.
Tested with node versions of 4.2, 5.5, 0.10, 0.12.
Examples
Determine if properties are equal value and type between 2 objects.
// test if fido's tail color is gray
var apom = require('apom');
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
var pObj = {tail: {color: 'gray'}};
apom.matches(pObj, fido, function(doesMatch){
console.log(doesMatch); //true
})
Or build the match function first to include match options and for better performance.
// test if fido has a gray tail regardless if grey or gray
var apom = require('apom');
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
// select the properties to be tested and the options
var propsToTest = ['tail.color'];
var options = {regExpMatch:true};
// include the regular expression in the 'pattern object'
var pObj = {tail:{color: /gr.y/}};
// create the match function
var matchFn = apom.makeMatchFn(propsToTest, options);
// test it
matchFn(pObj, fido, function(doesMatch){
console.log(doesMatch); // true
})
Filter an array of objects:
// find which pets have 4 paws
var apom = require('apom');
var pets = [
{ name: 'fido',
paws: {color: 'gray', count: 3},
},
{ name: 'rover',
paws: {color: 'white', count: 4},
},
];
// create the pattern object
var pObj = {paws:{count: 4}};
// select properties to test
var propsToTest = ['paws.count'];
// create the filter function
var filter = apom.makeFilterTargetObjectsFn(propsToTest);
// filter
filter(pObj, pets, function(matchedPets){
console.log(matchedPets); //matchedPets = {name: 'rover'...};
})
See test/test.js for an extensive list of examples.
Documentation
Match and Filter Functions
-
matches
-
makeMatchFn
returns a custommatches
function -
makeFilterTargetObjectsFn
returns a customfilterTargetObjects
function -
makeFilterPatternObjectsFn
returns a customfilterPatternObjects
function
Options
matches(pObj, tObj, callback)
Returns true
as result of callback if properties identified to be tested between pObj
and tObj
match; otherwise returns false
.
Which properties are tested and if they match is determined by whether matches
is called directly or created via the makeMatchFn
.
If matches
is created via makeMatchFn
then the propsToTest
and options
parameters determine which properties are tested for match and how the properties are tested for match. Calling the resulting matches
function created via makeMatchFn
also provides better performance than calling matches
directly.
If matches
function is called directly without creating it via makeMatchFn
, every property in the pObj
object is tested for a match and all options
values are default. Options
cannot be modified if calling matches
directly.
Arguments
Examples
// test if fido's tail color is gray
var apom = require('apom');
var fido ={
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
var pObj = {tail: {color: 'gray'}};
apom.matches(pObj, fido, function(doesMatch){
console.log(doesMatch); //true
});
// Or, create the matches function to include option
// such as regular expression matches.
// select the properties to be tested and the options
var propsToTest = ['tail.color'];
var options = {regExpMatch:true};
// create the custom match function
var matchFn = apom.makeMatchFn(propsToTest, options);
// include the regular expression in the 'pattern object'
var pObj = {tail:{color: /gr.y/}};
// test it
matchFn(pObj, fido, function(doesMatch){
console.log(doesMatch); // true
})
makeMatchFn(propsToTest, options)
Creates and returns a matches
function that is configured to test the properties included in propsToTest
and options
to determine how properties are tested for a match. This created function will run faster than calling the matches
function directly and allows for greater control, via propsToTest
and options
, of which properties are tested and how.
Arguments
propsToTest
-
options
- optional Applies to each property inpropsToTest
unlessoptions
values are included for properties inpropsToTest
.options
precedence is (1)propsToTest
options
values if set (2)options
as included here as a parameter, otherwise (3)options
default values.
Examples
// test if fido has a gray tail regardless if grey or gray
var apom = require('apom');
var fido ={ tail: {color: 'gray', count: 1}};
// select the properties to be tested and the options
var propsToTest = ['tail.color'];
var options = {regExpMatch:true};
// create the match function
var matchFn = apom.makeMatchFn(propsToTest, options);
// include the regular expression in the 'pattern object'
var pObj = {tail:{color: /gr.y/}};
// test it
matchFn(pObj, fido, function(doesMatch){
console.log(doesMatch); // true
});
It would give the same result to set the options
in propsToTest
var propsToTest = {'tail.color':{regExpMatch:true}};
var matchFn = apom.makeMatchFn(propsToTest); // options not included here
matchFn(pObj, fido, function(doesMatch){
console.log(doesMatch); // true
});
makeFilterTargetObjectsFn(propsToTest, options)
Creates and returns a filterTargetObjects
function that is configured to test the properties included in propsToTest
using options
to determine how properties are tested for a match between pObj
and tObjs
.
Arguments
propsToTest
-
options
optional Applies to each property inpropsToTest
unlessoptions
values are included for properties inpropsToTest
.options
precedence is (1)propsToTest
options
values if set (2)options
as included here as a parameter, otherwise (3)options
default values.
Examples
See filterTargetObjects
.
filterTargetObjects(pObj, tObjs, callback)
Returns an array of tObjs
that match the pObj
based on the propsToTest
and options
parameters that were used to create this function with makeFilterTargetObjectsFn
.
This function is created by calling makeFilterTargetObjectsFn
.
Arguments
pObj
-
tObjs
- An array oftObj
objects -
callback(result)
-result
is an array oftObj
objects that matchpObj
.
Examples
// find which pets have gray paws regardeless if 'gray' or 'grey'
var apom = require('apom');
var pets = [
{ name: 'fido',
paws: {color: 'gray', count: 3},
},
{ name: 'rover',
paws: {color: 'white', count: 4},
},
];
// create the pattern object
var pObj = {paws:{color: /gr[a,e]y/}};
// select properties and options to test
var propsToTest = ['paws.color'];
var options = {regExpMatch: true};
// create the filter function
var filter = apom.makeFilterTargetObjectsFn(propsToTest, options);
// filter
filter(pObj, pets, function(matchedPets){
console.log(matchedPets);
// [ { name: 'fido', paws: { color: 'gray', count: 3 } } ]
});
makeFilterPatternObjectsFn(propsToTest, options)
Creates and returns a filterPatternObjects
function that is configured to test the properties included in propsToTest
using options
to determine how properties are tested for a match between pObjs
and tObj
.
Arguments
propsToTest
-
options
- optional Applies to each property inpropsToTest
unlessoptions
values are included for properties inpropsToTest
.options
precedence is (1)propsToTest
options
values if set (2)options
as included here as a parameter, otherwise (3)options
default values.
Examples
See filterPatternObjects
.
filterPatternObjects(pObjs, tObj, callback)
Returns an array of pObjs
that match the tObj
based on the propsToTest
and options
parameters that were used to create this function with makeFilterPatternObjectsFn
.
This function is created by calling makeFilterPatternObjectsFn
.
filterPatternObjects
allows an array of objects with regular expressions to be filtered on those regular expressions unlike filterTargetObjects
.
Arguments
-
pObjs
- An array ofpObj
objects tObj
-
callback(result)
-result
is an array ofpObj
objects that matchtObj
.
Examples
// find which pets match a request with a role of guarddog
var apom = require('apom');
// pets are the `pObjs` in this case to match on their regular expressions
var pets = [
{name: 'growler',
path: /.*role=guarddog.*/},
{name: 'fido',
path: /.*role=pet.*/},
]
// request is the tObj
var request = {path: '/pets?role=guarddog'}
// select properties and options to test
var propsToTest = ['path'];
var options = {regExpMatch: true};
// create the filter function
var filter = apom.makeFilterPatternObjectsFn(propsToTest, options);
// filter
filter(pets, request, function(matchedPets){
console.log(matchedPets);
// [ { name: 'growler', path: /.*role=guarddog.*/ } ]
});
pObj
"pattern object". Any object that is passed into a matches
, filterPatternObjects
or filterTargetObjects
function as the first parameter. It is used to test if it matches the target object(tObj
). Considered a 'pattern' object because, unlike the tObj
, it has characteristics such as :
- If
regExpMatch
is true, property/ies in pObj are tested as regular expressions against respectivetObj
property/ies. - If
variablesAllowed
is true, strings in the pObj property values can be replaced as variable names with variable values.
var apom = require('apom');
// the target object here is fido
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
// the pattern object
var pObj = {tail: {color: 'gray'}};
apom.matches(pObj, fido, function(doesMatch){
console.log(doesMatch); //true
})
tObj
"target object". Any object that is passed into a matches
, filterPatternObjects
or filterTargetObjects
function as the second parameter. The target object is the object that is being tested against the pattern object to determine if it matches. See notes and example under pObj
.
propsToTest
An array or object that contains property names and their assigned options
values, if any. Property names are strings and are in dot notation if nested; eg "tail.color" to identify the property in {tail: {color: black}}
.
Can take one of the following forms:
-
an array of strings which are the property names to be tested.
options
values cannot be specified for individual properties with this form. Example:['name', 'tail.color', 'housetrained']
-
an array of objects, one for each property to be tested, each containing a 'name' property assigned to the property name to be tested, and option property key/values (optional). Example:
// test using default options for housetrained; tail.color using reg exp match [{name: 'housetrained'}, {name: 'tail.color', regExpMatch: true}]
-
an array of combination of the above 2 (strings and objects). Example:
['housetrained', {name: 'tail.color', regExpMatch: true}]
-
an object with property names as keys and
options
objects as the values. Example:// test using default options for housetrained; tail.color using reg exp match {'housetrained':{}, 'tail.color': {regExpMatch: true}}
options
An object used to set the option values for match and filter functions.
//options properties & their default values
var options = {
regExpMatch: false, // match on regular expression in `pObj`
regExpIgnoreCase: false, // ignore case on reg exp match (str only)
regExpAnchorStart: false, // append "^" to beg of str for reg exp (str only)
regExpAnchorEnd: false, // append "$" to end of str for reg exp (str only)
matchIfPObjPropMissing: false, // matches if `pObj` property doesn't exist
matchIfTObjPropMissing: false, // matches if `tObj` property doesn't exist
variablesAllowed: false, // replace var names with var values in `pObj` props
getVariables: undefined, // function to call to get object of var names/vals
variablesStartStr: '~', // beg str in pObj prop value to find the var name
variablesEndStr: null, // end str in pObj prop value to find the var name
propMatchFn: null // function to call instead of std match function
};
regExpMatch
Property on the options
object that if equal to true
, apom filter and matches functions will use the pObj
property value as a regular expression to test against the tObj
property. If the pattern object property value is a string, the string will be converted to a javascript regular expression.
- valid values:
true
,false
- default:
false
Example:
// test if fido has a gray tail regardless if grey or gray
var apom = require('apom');
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
// select the properties to be tested and the options
var propsToTest = ['tail.color'];
var options = {regExpMatch:true};
// include the regular expression in the 'pattern object'
var pObj = {tail:{color: /gr[a,e]y/}};
// create the match function
var matchFn = apom.makeMatchFn(propsToTest, options);
// test it
matchFn(pObj, fido, function(doesMatch){
console.log(doesMatch); // true
});
regExpIgnoreCase
Property on the options
object that if equal to true
and regExpMatch
===true
and the pObj
property value is a string, then when the pObj
value is converted from a string to a regular expression object in apom matches and filter functions, the regular expression is included with the 'i' flag to ignore case on the regular expression match. This option value is only considered where the pObj
property value is a string. If the pObj
value is a regular expression object, then the ignore case flag can be included on that object; eg "/gray/i".
- valid values:
true
,false
- default:
false
Example:
// test if fido has a gray tail regardless if grey or Gray
var apom = require('apom');
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'Gray', count: 1},
body: {color: 'black'},
housetrained: true};
// select the properties to be tested and the options
var propsToTest = ['tail.color'];
var options = {regExpMatch:true, regExpIgnoreCase: true};
// include the regular expression as a string in the pattern object
var pObj = {tail:{color: 'gr[a,e]y'}};
// create the match function
var matchFn = apom.makeMatchFn(propsToTest, options);
// test it
matchFn(pObj, fido, function(doesMatch){
console.log(doesMatch); // true
});
// regExpIgnoreCase does not apply if pObj property is a regular expression
var pObj = {tail:{color: /gr[a,e]y/}};
matchFn(pObj, fido, function(doesMatch){
console.log(doesMatch); // false
});
// use the 'i' flag on the regular expression object instead
var pObj = {tail:{color: /gr[a,e]y/i}};
matchFn(pObj, fido, function(doesMatch){
console.log(doesMatch); // true
});
regExpAnchorStart
Property on the options
object that if equal to true
and regExpMatch
===true
and the pObj
property value is a string, then when the pObj
value is converted from a string to a regular expression object in apom matches and filter functions, it includes a '^' prepended to pObj
string value. This option value is only considered where the pObj
is a string. If the pObj
property value is a regular expression object, then the ^ can be included in the regular expression; eg, /^gray/.
- valid values:
true
,false
-
default:
false
This option will rarely (ever?) be needed as this can also be achieved with a
pObj
value that is a string by simply including the ^ in the string (without settingregExpAnchorStart
=true).These 3 would yield the same result:
var pObj = {tail: {color: '^gray'}} var options = {regExpMatch: true}
var pObj = {tail: {color: 'gray'}} var options = {regExpMatch: true, regExpAnchorStart: true}
var pObj = {tail: {color: /^gray/}} var options = {regExpMatch: true}
regExpAnchorEnd
Property on the options
object that if equal to true
and regExpMatch
===true
and the pObj
property value is a string, then when the pObj
value is converted from a string to a regular expression object in apom matches and filter functions, it includes a '$' appended to the end of the pObj
string value. This option value is only considered where the pObj
is a string. If the pObj
property value is a regular expression object, then the $ can be included in the regular expression; eg, /gray$/.
- valid values:
true
,false
-
default:
false
This option will rarely (ever?) be needed as this can also be achieved with a
pObj
value that is a string by simply including the $ in the string (without settingregExpAnchorEnd
=true).These 3 would yield the same result:
var pObj = {tail: {color: 'gray$'}} var options = {regExpMatch: true}
var pObj = {tail: {color: 'gray'}} var options = {regExpMatch: true, regExpAnchorEnd: true}
var pObj = {tail: {color: /gray$/}} var options = {regExpMatch: true}
matchIfTObjPropMissing
Property on the options
object that if equal to true
, apom filter and matches functions will return true
for the given property's match test if the property being tested does not exist on tObj
.
- valid values:
true
,false
- default:
false
Example:
// find which pets have a role of guarddog and (the breed is chihuahua or
// breed is not defined)
var apom = require('apom');
var pets = [
{name: 'growler',
breed: 'chihuahua',
role: 'guarddog'},
{name: 'fido',
breed: 'lab',
role: 'pet'},
{name: 'duchy',
role: 'guarddog'},
{name: 'bruiser',
breed: 'chihuahua',
role: 'cuddler'},
]
// request is the tObj
var pObj = {role:'guarddog', breed: 'chihuahua'};
// select properties to test; role with default options
var propsToTest =
{role: {}, breed: {matchIfTObjPropMissing: true}};
// create the filter function
var filter = apom.makeFilterTargetObjectsFn(propsToTest);
// filter
filter(pObj, pets, function(matchedPets){
console.log(matchedPets);
// [ { name: 'growler'...},{name: 'duchy'...} ]
});
matchIfPObjPropMissing
Property on the options
object that if equal to true
, apom filter and matches functions will return true
for the given property's match test if the property being tested does not exist on pObj
.
- valid values:
true
,false
- default:
false
Example:
This option would typically be used in a makeFilterPatternObjectsFn
, like this example, but like all options can also be used in makeFilterPatternObjectsFn
and matches
.
// find which pets match a request with a role of guarddog and
// (the breed is chihuahua or breed is not defined)
var apom = require('apom');
// pets are the `pObjs` in this case to match on their regular expressions
var pets = [
{name: 'growler',
breed: 'chihuahua',
path: /.*role=guarddog.*/},
{name: 'fido',
breed: 'lab',
path: /.*role=pet.*/},
{name: 'duchy',
path: /.*role=guarddog.*/},
{name: 'bruiser',
breed: 'chihuahua',
path: /.*role=cuddler.*/},
]
// request is the tObj
var request = {path: '/pets?role=guarddog', breed: 'chihuahua'}
// select properties and options to test
var propsToTest =
{path: {regExpMatch: true}, breed: {matchIfPObjPropMissing: true}};
// create the filter function
var filter = apom.makeFilterPatternObjectsFn(propsToTest);
// filter
filter(pets, request, function(matchedPets){
console.log(matchedPets);
// [ { name: 'growler'...},{name: 'duchy'...} ]
});
variablesAllowed
Property on the options
object that if equal to true
, replaces strings that are recognized as variable names in pObj
property values with their respective variable values from getVariables
. The varible names on the pObj
property values is matched based on the variablesStartStr
and variablesEndStr
.
- valid values:
true
,false
- default:
false
Example:
// match if fido has a grey tail and paws regardless if grey or gray
var apom = require('apom');
var fido ={
paws: {color: 'grey', count: 3},
tail: {color: 'gray', count: 1},
body: {color: 'black'},
housetrained: true};
var options =
{regExpMatch: true,
variablesAllowed:true,
variablesStartStr:"~",
variablesEndStr: "#",
getVariables: function(cb) {
return cb(null, {grayColor: /gr[a,e]y/});
}};
// variable name is identified between variablesStartStr(~) and variablesEndStr(#)
// and replaced with that name from getVariables (grayColor => /gr[a,e]y/)
var pObj = {paws:{color: '~grayColor#'},tail:{color:'~grayColor#'}};
var propsToTest = ['paws.color', 'tail.color'];
var matchFn = apom.makeMatchFn(propsToTest, options);
matchFn(pObj, fido, function(matches){
console.log(matches); //true
return;
});
getVariables
Property on the options
object that defines a function which, if variablesAllowed
is true
, takes a callback which is called with an error (null if no error) and an object of the form :
{variable1Name: `variable1Value`,
variable2Name: `variable2Value`}
See variablesAllowed
for an example.
variablesStartStr
Property on the options
object that defines a string which, if variablesAllowed
=== true
, determines the starting position of a variable name string in a pObj
property value that will be replaced with the variable value string of the respective variable name obtained from getVariables
.
See variablesAllowed
for an example.
variablesEndStr
Property on the options
object that defines a string which, if variablesAllowed
=== true
, determines the ending position of a variable name string in a pObj
property value that will be replaced with the variable value string of the respective variable name obtained from getVariables
.
See variablesAllowed
for an example.
propMatchFn
Property on the options
object that defines a function to replace the match function between pObj
and tObj
properties.
- default:
null
Function is called with 3 parameters for each property being tested:
-
pObjProp
- an object-literal with these 2 properties:-
value
: the value of thepObj
property value -
exists
:true
orfalse
depending on whether the property exists onpObj
-
-
tObjProp
- an object-literal with these 2 properties:-
value
: the value of thetObj
property value -
exists
:true
orfalse
depending on whether the property exists ontObj
-
- callback(
true
|false
) - The callback that contains your defined expression to returntrue
orfalse
.
Example:
// find pets with 3 or more paws
var apom = require('apom');
var pets = [
{ name: 'fido',
paws: {color: 'gray', count: 3}},
{ name: 'rover',
paws: {color: 'white', count: 4}},
{ name: 'slither',
paws: {count: 0}},
];
var pObj = {paws:{count: 3}};
// propMatchFn is called for each property with the
// pattern object property value and the target object property value
var matchFn = function(pObjProp, tObjProp, cb) {
var hasAtLeast3Paws = tObjProp.exists === true &&
pObjProp.exists === true &&
tObjProp.value >= pObjProp.value;
return cb(hasAtLeast3Paws);
};
var propsToTest = {'paws.count': {propMatchFn: matchFn}};
var filter = apom.makeFilterTargetObjectsFn(propsToTest);
filter(pObj, pets, function(matchedPets){
console.log(matchedPets);
//matchedPets = {name: 'fido'..., name:'rover'...};
});