Data-Mate
A teraslice library for validating and transforming data
Installation
# Using yarn
yarn add @terascope/data-mate
# Using npm
npm install --save @terascope/data-mate
Usage
import { FieldValidator, FieldTransform } from '@terascope/data-mate';
const data = ['60,80', 'not a point'];
const points = data
.filter(FieldValidator.isGeoPoint)
.map(FieldTransform.toGeoPoint);
points === [{ lat: 60, lon: 80 }]
Functions
-
- isString
- isNumber
- isInteger
- isBoolean
- isBooleanLike
- isGeoPoint
- isGeoJSON
- isGeoShapePoint
- isGeoShapePolygon
- isGeoShapeMultiPolygon
- isEmpty
- isLength
- isAlpha
- isASCII
- isBase64
- isValidDate
- isISO8601
- isRFC3339
- isJSON
- isEmail
- isFQDN
- isURL
- isIP
- isRoutableIP
- isNonRoutableIP
- isCIDR
- isISDN
- isMACAddress
- isUUID
- isHash
- isArray
- isCountryCode
- isMIMEType
- isISSN
- isPostalCode
- inIPRange
- inNumberRange
- guard
- exists
- contains
- equals
- some
- every
-
- toBoolean
- toString
- toNumber
- toUpperCase
- toLowerCase
- toCamelCase
- toKebabCase
- toPascalCase
- toSnakeCase
- toTitleCase
- toJSON
- toGeoPoint
- toUnixTime
- toISO8601
- toISDN
- splitString
- trim
- trimStart
- trimEnd
- truncate
- decodeBase64
- decodeURL
- decodeHex
- encodeBase64
- encodeURL
- encodeHex
- encodeMD5
- encodeSHA
- encodeSHA1
- parseJSON
- dedupe
- extract
- replaceRegex
- replaceLiteral
- formatDate
- parseDate
- setDefault
- map
Note
all functions take as a second parameter a context? value. Some transforms and validations require the originating document from where the value came from to properly perform its actions. If there is no originating document, then you can simply pass in a empty object. All additional options for a function are passed into the third parameter as an object
Field Validations
Field validation functions accept an input and return a Boolean. If additional arguments are needed then an object containing parameters is passed in.
functionName(input, context, {arg1: 'ARG1', arg2: 'ARG2', etc... })
isString
isString(input, context?) - Validates that input is a string or a list of strings
FieldValidator.isString('this is a string'); // true
FieldValidator.isString(true); // false
FieldValidator.isString(['hello', 'world']); // true
FieldValidator.isString(['hello', 3]); // false
FieldValidator.isString(17.343); // false
isNumber
isNumber(input, context?) - Validates that input is a number or a list of numbers
FieldValidator.isNumber(42.32); // true;
FieldValidator.isNumber('NOT A Number'); // false
FieldValidator.isNumber([42.32, 245]); // true;
FieldValidator.isNumber([42.32, { some: 'obj' }]); // false;
FieldValidator.isNumber('1'); // false
isInteger
isInteger(input, context?) - Validates that input is a integer or a list of integers
FieldValidator.isInteger(42); // true
FieldValidator.isInteger(3.14); // false
FieldValidator.isInteger(Infinity); // false
FieldValidator.isInteger('1'); // false
FieldValidator.isInteger(true); //false
FieldValidator.isInteger([42, 1]); // true
FieldValidator.isInteger([42, 3.14]); // false
isBoolean
FieldValidator.isBoolean(input, context?) - Checks to see if input is a Boolean. If given an array, will check if all values are booleans ignoring any null/undefined values
FieldValidator.isBoolean(false); // true
FieldValidator.isBoolean('astring'); // false
FieldValidator.isBoolean(0); // false
FieldValidator.isBoolean([true, undefined]); // true
FieldValidator.isBoolean(['true', undefined]; // false
isBooleanLike
isBooleanLike(input, context?) - returns true if input is a Boolean, truthy, or falsy. If an given an array, it will check to see if all values in the array are Boolean-like, does NOT ignore null/undefined values
truthy values are 1, '1', 'true', 'yes'
falsy values are 0, '0', 'false', 'no'
FieldValidator.isBooleanLike()); // true
FieldValidator.isBooleanLike(null)); // true
FieldValidator.isBooleanLike(0)); // true
FieldValidator.isBooleanLike('0')); // true
FieldValidator.isBooleanLike('false')); // true
FieldValidator.isBooleanLike('no')); // true
FieldValidator.isBooleanLike(['no', '0', null])); // true
isGeoPoint
FieldValidator.isGeoPoint(input, context?) - Checks to see if input is a valid geo-point, or a list of valid geo-points excluding null/undefined values
FieldValidator.isGeoPoint('60,80'); // true
FieldValidator.isGeoPoint([80, 60]); // true
FieldValidator.isGeoPoint({ lat: 60, lon: 80 }); // true
FieldValidator.isGeoPoint({ latitude: 60, longitude: 80 }); // true
FieldValidator.isGeoPoint(['60,80', { lat: 60, lon: 80 }]); // true
FieldValidator.isGeoPoint(['60,80', 'hello']); // false
isGeoJSON
FieldValidator.isGeoJSON(input, context?) - Checks to see if input is a valid geo-json geometry, or a list of geo-json geometries
const polygon = {
type: "Polygon",
coordinates: [
[[10, 10], [10, 50], [50, 50], [50, 10], [10, 10]],
]
};
FieldValidator.isGeoJSON(polygon); // true
FieldValidator.isGeoJSON([polygon, { other: 'obj'}]); // false
isGeoShapePoint
FieldValidator.isGeoShapePoint(input, context?) - Checks to see if input is a valid geo-json point, or a list of geo-json points
const polygon = {
type: "Polygon",
coordinates: [
[[10, 10], [10, 50], [50, 50], [50, 10], [10, 10]],
]
};
const point = {
type: 'Point',
coordinates: [12, 12]
};
FieldValidator.isGeoShapePoint(polygon); // false
FieldValidator.isGeoShapePoint(point); // true
FieldValidator.isGeoShapePoint([polygon, point]); // false
FieldValidator.isGeoShapePoint([point, point]); // true
isGeoShapePolygon
FieldValidator.isGeoShapePolygon(input, context?) - Checks to see if input is a valid geo-json polygon, or a list of geo-json polygons
const polygon = {
type: "Polygon",
coordinates: [
[[10, 10], [10, 50], [50, 50], [50, 10], [10, 10]],
]
};
const point = {
type: 'Point',
coordinates: [12, 12]
};
FieldValidator.isGeoShapePolygon(polygon); // true
FieldValidator.isGeoShapePolygon(point); // false
FieldValidator.isGeoShapePolygon([polygon, point]); // false
FieldValidator.isGeoShapePolygon([polygon, polygon]); // true
isGeoShapeMultiPolygon
FieldValidator.isGeoShapeMultiPolygon(input, context?) - Checks to see if input is a valid geo-json multi-polygon or a list of geo-json multi-polygons
const polygon = {
type: "Polygon",
coordinates: [
[[10, 10], [10, 50], [50, 50], [50, 10], [10, 10]],
]
};
const point = {
type: 'Point',
coordinates: [12, 12]
};
const multiPolygon = {
type: 'MultiPolygon',
coordinates: [
[
[[10, 10], [10, 50], [50, 50], [50, 10], [10, 10]],
],
[
[[-10, -10], [-10, -50], [-50, -50], [-50, -10], [-10, -10]],
]
]
};
FieldValidator.isGeoShapeMultiPolygon(polygon); // false
FieldValidator.isGeoShapeMultiPolygon(point); // false
FieldValidator.isGeoShapeMultiPolygon(multiPolygon); // true
FieldValidator.isGeoShapeMultiPolygon([multiPolygon, multiPolygon]); // true
FieldValidator.isGeoShapeMultiPolygon([multiPolygon, point]); // false
inNumberRange
inNumberRange(input, context, args) - returns true if input is a Number within the min and max boundaries, or that the array on numbers are between the values
args: { min: Number, max: Number, inclusive?: Boolean } note that second parameter is parent object, if there is not any just pass an empty object
FieldValidator.inNumberRange(42, {}, { min: 0, max: 100}); // true
FieldValidator.inNumberRange([42, 11, 94], {}, { min: 0, max: 100}); // true
FieldValidator.inNumberRange([42, 11367, 94], {}, { min: 0, max: 100}); // false
FieldValidator.inNumberRange(-42, {}, { min:0 , max: 100 }); // false
FieldValidator.inNumberRange(42, {}, { min: 0, max: 42 }); // false without the inclusive option
FieldValidator.inNumberRange(42, {}, { min: 0, max: 42, inclusive: true }); // true with the inclusive option
isEmpty
isEmpty(input, context, args) - returns true for an empty string, array, or object
args: { ignoreWhitespace?: Boolean }
set ignoreWhitespace to true if you want the value to be trimmed
FieldValidator.isEmpty(''); // true
FieldValidator.isEmpty(undefined); // true
FieldValidator.isEmpty(null); // true
FieldValidator.isEmpty({ foo: 'bar' }); // false
FieldValidator.isEmpty({}); // true
FieldValidator.isEmpty([]); // true
// note that passing in arguments is the third parameter
FieldValidator.isEmpty(' ', {}, { ignoreWhitespace: true }); // true
contains
contains(input, context, args) - returns true if input contains args value, or the list of inputs contains args value
args: { value: String }
FieldValidator.contains('hello', {}, { value: 'hello' }); // true
FieldValidator.contains('hello', {}, { value: 'll' }); // true
FieldValidator.contains(['hello', 'cello'], {}, { value: 'll' }); // true
FieldValidator.contains(['hello', 'stuff'], {}, { value: 'll' }); // false
FieldValidator.contains('12345', {}, { value: '45' }); // true
equals
equals(input, context, args) - Validates that the input matches the value, of that the input array matches the value provided
args: { value: 'String' }
FieldValidator.equals('hello', { value: 'hello' }); // true
FieldValidator.equals([3, 3], { value: 3 }); // true
FieldValidator.equals('hello', { value: 'ello' }); // false
isLength
isLength(input, context, args) - Check to see if input is a string with given length ranges, or a list of valid string lengths
Optional args: { length: Number, min: Number, max: Number }
FieldValidator.isLength('astring', { size: 7 }); // true
FieldValidator.isLength('astring', { min: 3, max: 10 }); // true
FieldValidator.isLength('astring', { size: 10 }); // false
FieldValidator.isLength('astring', {}, { min: 8 }); // false
FieldValidator.isLength(['astring', 'stuff', 'other'], { min: 3, max: 10 }); // true
isAlpha
isAlpha(input, context?, args?) - Validates that the input is alpha or a list of alpha values
arg: { locale?: ANY LOCALE OPTION DEFINED BELOW }, default locale is en-US
Locale options: 'ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fr-FR', 'fa-IR', 'he', 'hu-HU', 'it-IT', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA'`
FieldValidator.isAlpha('validString'); // true
FieldValidator.isAlpha('ThisiZĄĆĘŚŁ', { locale: 'pl-PL' }); // true
FieldValidator.isAlpha('1123_not-valid'); // false
FieldValidator.isAlpha(['validString', 'more']); // true
isAlphanumeric
isAlphanumeric(input, context?, args?) - Validates that the input is alphanumeric or a list of alphanumeric values
Optional arg: { locale: ANY LOCALE OPTION DEFINED BELOW }, default locale is en-US
Locale options: 'ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fr-FR', 'fa-IR', 'he', 'hu-HU', 'it-IT', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA'`
FieldValidator.isAlphanumeric('123validString'); // true
FieldValidator.isAlphanumeric('فڤقکگ1234', { locale: 'ku-IQ' }); // true
FieldValidator.isAlphanumeric('-- not valid'); // false
FieldValidator.isAlphanumeric(['134', 'hello']); // true
isASCII
isASCII(input, context?) - Validates that the input is ASCII chars or a list of ASCII chars
FieldValidator.isASCII('ascii\s__'); // true;
FieldValidator.isASCII('˜∆˙©∂ß'); // false
FieldValidator.isASCII(['some', 'words']); // true;
isBase64
isBase64(input, context?) - Validates that the input is a base64 encoded string or a list of base64 encoded strings
FieldValidator.isBase64('ZWFzdXJlLg=='); // true
FieldValidator.isBase64('not base 64'); // false
FieldValidator.isBase64(['ZWFzdXJlLg==', 'ZWFzdXJlLg==']); // true
isValidDate
isValidDate(input, context?) - Validates that the input is a valid date or a list of valid dates (epoch/ unix time)
FieldValidator.isValidDate('2019-03-17T23:08:59.673Z'); // true
FieldValidator.isValidDate('2019-03-17'); // true
FieldValidator.isValidDate('2019-03-17T23:08:59'); // true
FieldValidator.isValidDate('03/17/2019'); // true
FieldValidator.isValidDate('03-17-2019'); // true
FieldValidator.isValidDate('Jan 22, 2012'); // true
FieldValidator.isValidDate('23 Jan 2012'); // true
FieldValidator.isValidDate(1552000139); // true
FieldValidator.isValidDate('1552000139'); // false
FieldValidator.isValidDate(['2019-03-17', 1552000139]); // true;
isISO8601
isISO8601(input, context?) - Checks to see if input is a valid ISO8601 string dates or a list of valid dates
FieldValidator.isISO8601('2020-01-01T12:03:03.494Z'); //true
FieldValidator.isISO8601('2020-01-01'); // true
FieldValidator.isISO8601('2020-01-01T12:03:03'); // true
FieldValidator.isISO8601(['2020-01-01T12:03:03', '2020-01-01']); // true
isRFC3339
isRFC3339(input, context?) - Validates that input is a valid RFC3339 dates or a list of valid RFC3339 dates
FieldValidator.isRFC3339('2020-01-01T12:05:05.001Z'); // true
FieldValidator.isRFC3339('2020-01-01 12:05:05.001Z'); // true
FieldValidator.isRFC3339('2020-01-01T12:05:05Z'); // true
FieldValidator.isRFC3339(['2020-01-01T12:05:05Z', '2020-01-01T12:05:05.001Z']); // true
isJSON
isJSON(input, context?) - Validates that input is a valid JSON string or a list of valid JSON
FieldValidator.isJSON('{ "bob": "gibson" }'); // true
FieldValidator.isJSON({ bob: 'gibson' }); // false
FieldValidator.isJSON('[]'); // true
FieldValidator.isJSON('{}'); // true
FieldValidator.isJSON(['{ "bob": "gibson" }', '[]']); // true
isEmail
isEmail(input, context?) - Return true if value is a valid email, or a list of valid emails
FieldValidator.isEmail('ha3ke5@pawnage.com') // true
FieldValidator.isEmail('user@blah.com/junk.junk?a=<tag value="junk"') // true
FieldValidator.isEmail('email@example.com'); // true
FieldValidator.isEmail(12345); // false
FieldValidator.isEmail(['email@example.com', 'ha3ke5@pawnage.com']); // true
isFQDN
isFQDN(input, context?, args) - Validate that the input is a valid domain name, or a list of domain names
args: { require_tld = true, allow_underscores = false, allow_trailing_dot = false }
FieldValidator.isFQDN('example.com.uk'); // true
FieldValidator.isFQDN('notadomain'); // false
FieldValidator.isFQDN(['example.com.uk', 'google.com']); // true
isURL
isURL(input, context?) - Validates that the input is a url or a list of urls
FieldValidator.isURL('https://someurl.cc.ru.ch'); // true
FieldValidator.isURL('ftp://someurl.bom:8080?some=bar&hi=bob'); // true
FieldValidator.isURL('http://xn--fsqu00a.xn--3lr804guic'); // true
FieldValidator.isURL('http://example.com'); // true
FieldValidator.isURL('BAD-URL'); // false
FieldValidator.isURL(['http://example.com', 'http://example.com']); // true
isIP
isIP(input, context?) - Validates that the input is an IP address, or a list of IP addresses
FieldValidator.isIP('8.8.8.8'); // true
FieldValidator.isIP('192.172.1.18'); // true
FieldValidator.isIP('11.0.1.18'); // true
FieldValidator.isIP('2001:db8:85a3:8d3:1319:8a2e:370:7348'); // true
FieldValidator.isIP('fe80::1ff:fe23:4567:890a%eth2'); // true
FieldValidator.isIP('2001:DB8::1'); // true
FieldValidator.isIP('172.16.0.1'); // true
FieldValidator.isIP(['172.16.0.1', '11.0.1.18']); // true
isRoutableIP
isRoutableIP(input, context?) - Validate is input is a routable IP, or a list of routable IP's
Works for both IPv4 and IPv6 addresses
FieldValidator.isRoutableIP('8.8.8.8'); // true
FieldValidator.isRoutableIP('2001:db8::1'); // true
FieldValidator.isRoutableIP('172.194.0.1'); // true
FieldValidator.isRoutableIP('192.168.0.1'); // false
FieldValidator.isRoutableIP(['172.194.0.1', '8.8.8.8']); // true
isNonRoutableIP
isNonRoutableIP(input, context?) - Validate is input is a non-routable IP, or a list of non-routable IP's
Works for both IPv4 and IPv6 addresses
FieldValidator.isNonRoutableIP('192.168.0.1'); // true
FieldValidator.isNonRoutableIP('10.16.32.210'); // true
FieldValidator.isNonRoutableIP('fc00:db8::1'); // true
FieldValidator.isNonRoutableIP('8.8.8.8'); // false
FieldValidator.isNonRoutableIP('2001:db8::1'); // false
FieldValidator.isNonRoutableIP(['10.16.32.210', '192.168.0.1']); // true
isCIDR
isCIDR(input, context?) - Validates that input is a CIDR or a list of CIDR values
Works for both IPv4 and IPv6 addresses
FieldValidator.isCIDR('8.8.0.0/12'); // true
FieldValidator.isCIDR('2001::1234:5678/128'); // true
FieldValidator.isCIDR('8.8.8.10'); // false
FieldValidator.isCIDR(['8.8.0.0/12', '2001::1234:5678/128']); // true
inIPRange
inIPRange(input, context, args) - Validates if the input IP is within a given range of IP's, or that a list of inputs IP are in range
Optional args: { min?: IP_ADDRESS, max?: IP_ADDRESS, cidr?: IP_ADDRESS/CIDR } default values:
- MIN_IPV4_IP = '0.0.0.0';
- MAX_IPV4_IP = '255.255.255.255';
- MIN_IPV6_IP = '::';
- MAX_IPV6_IP = 'ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff';
Works for both IPv4 and IPv6 addresses
FieldValidator.inIPRange('8.8.8.8', {}, { cidr: '8.8.8.0/24' }); // true
FieldValidator.inIPRange('fd00::b000', {}, { min: 'fd00::123', max: 'fd00::ea00' }); // true;
FieldValidator.inIPRange('8.8.8.8', {}, { cidr: '8.8.8.10/32' }); // false
const config = { min: '8.8.8.0', max: '8.8.8.64' };
FieldValidator.inIPRange(['8.8.8.64', '8.8.8.8'], {}, config); // true
isISDN
isISDN(input, context?) - Validates that the input is a valid phone Number, or a list of phone numbers. Based on googles libphonenumber library.
FieldValidator.isISDN('46707123456'); // true
FieldValidator.isISDN('1-808-915-6800'); // true
FieldValidator.isISDN('NOT A PHONE Number'); // false
FieldValidator.isISDN(79525554602); // true
FieldValidator.isISDN(['46707123456', '1-808-915-6800']); // true
isMACAddress
isMACAddress(input, context?, args?) - Validates that the input is a MACAddress, or a list of MACAddressess
Optional args { delimiter: ['colon', 'dash', 'space', 'dot', 'none', 'any'] }
delimiter can be a string of one delimiter or an array of multiple delimiters
'none' means no delimiter in the mac address and 'any' checks all delimiters for a valid mac address
Default is 'any'
FieldValidator.isMACAddress('00:1f:f3:5b:2b:1f'); // true
FieldValidator.isMACAddress('001ff35b2b1f'); // true
FieldValidator.isMACAddress('001f.f35b.2b1f',{}, { delimiter: 'dot' }); // true
const manyDelimiters = { delimiter: ['dash', 'colon', 'space'] }
FieldValidator.isMACAddress('00-1f-f3-5b-2b-1f', {}, manyDelimiters); // true
FieldValidator.isMACAddress(12345); // false
// specified colon and space delimiter only
const twoDelimiters = { delimiter: ['colon', 'space'] };
FieldValidator.isMACAddress('00-1f-f3-5b-2b-1f', {}, twoDelimiters ); // false,
FieldValidator.isMACAddress(['001ff35b2b1f', '00:1f:f3:5b:2b:1f']); // true
isUUID
isUUID(input, context?) - Validates that input is a UUID or a list of UUID's
FieldValidator.isUUID('0668CF8B-27F8-2F4D-4F2D-763AC7C8F68B'); // true
FieldValidator.isUUID('BAD-UUID'); // false
FieldValidator.isUUID([
'0668CF8B-27F8-2F4D-4F2D-763AC7C8F68B',
'123e4567-e89b-82d3-f456-426655440000'
]); // true
isHash
isHash(input, context, args) - Validates that the input is a hash, or a list of hashes
arg: { algo: 'ANY HASH OPTION DEFINED BELOW'}
Hash options: md4, md5, sha1, sha256, sha384, sha512, ripemd128, ripemd160, tiger128, tiger160, tiger192, crc32, crc32b
FieldValidator.isHash('6201b3d1815444c87e00963fcf008c1e', {}, { algo: 'md5' }); // true
FieldValidator.isHash('85031b6f407e7f25cf826193338f7a4c2dc8c8b5130f5ca2c69a66d9f5107e33', {}, { algo: 'sha256' }); // true
FieldValidator.isHash('98fc121ea4c749f2b06e4a768b92ef1c740625a0', {}, { algo: 'sha1' }); // true
FieldValidator.isHash(['6201b3d1815444c87e00963fcf008c1e', undefined],
{},
{ algo: 'md5' }
); // true
isCountryCode
isCountryCode(input, context?) - Validates that input is a valid country code or a list of country codes
FieldValidator.isCountryCode('IS'); // true
FieldValidator.isCountryCode('ru'); // true
FieldValidator.isCountryCode('USA'); // false
FieldValidator.isCountryCode(['IS', 'ru']); // true
isMIMEType
isMIMEType(input, context?) - Validates that input is a valid mimeType or a list of mimeTypes
FieldValidator.isMIMEType('application/javascript'); // true
FieldValidator.isMIMEType('application/graphql'); // true
FieldValidator.isMIMEType(12345); // false
FieldValidator.isMIMEType(['application/graphql', 'application/javascript']); // true
isISSN
isISSN(input, context?, args?) - returns true if input is a valid international standard serial Number or a list of valid ISSN's
args: { require_hyphen = false, case_sensitive = false }
FieldValidator.isISSN('0378-5955'); // true
FieldValidator.isISSN('03785955'); // true
FieldValidator.isISSN('0378-5955', {}, { requireHyphen: true }); // true
FieldValidator.isISSN(['0378-5955', '0000-006x']); // true
guard
guard(input, context?) - Will throw if input is null or undefined
FieldValidator.guard('03785955'); // true
FieldValidator.guard(); // WILL THROW
exists
exists(input, context?) - Will return false if input is null or undefined
FieldValidator.exists('03785955'); // true
FieldValidator.exists(null); // false
isArray
isArray(input, context?) - Validates that the input is an array
FieldValidator.isArray(undefined); // false
FieldValidator.isArray([1, 2, 3]); // true
FieldValidator.isArray([]); // true
some
some(input, context, args) - Validates that the function specified returns true at least once on the list of values
args: { fn: String, options: Any }
fn - must be a function name from FieldValidator options - any additional parameters necessary for the fn being evoked
const mixedArray = ['hello', 3, { some: 'obj' }];
FieldValidator.some(mixedArray, mixedArray, fn: 'isString' }); // true
FieldValidator.some(mixedArray, mixedArray, { fn: 'isBoolean' }); // false
every
every(input, context?, args) - Validates that the function specified returns true for every single value in the list
args: { fn: String, options: Any }
fn must be a function name from FieldValidator
const strArray = ['hello', 'world'];
FieldValidator.every([mixedArray, mixedArray { fn: 'isString' }); // false
FieldValidator.every(strArray, strArray, { fn: 'isString' }); // true
isPostalCode
isPostalCode(input, context?, args?) - Validates that input is a valid postal code or a list of postal codes
Optional arg: { locale?: 'ANY OF THE DEFINED LOCATIONS BELOW' }
locations: AD, AT, AU, BE, BG, BR, CA, CH, CZ, DE, DK, DZ, EE, ES, FI, FR, GB, GR, HR, HU, ID, IE, IL, IN, IS, IT, JP, KE, LI, LT, LU, LV, MX, MT, NL, NO, NZ, PL, PR, PT, RO, RU, SA, SE, SI, SK, TN, TW, UA, US, ZA, ZM
default locale is any
FieldValidator.isPostalCode('85249'); // true
FieldValidator.isPostalCode('85249', {}, { locale: 'any' }); // true
FieldValidator.isPostalCode('85249', {}, { locale: 'ES' }); // false
FieldValidator.isPostalCode('852', {}, { locale: 'IS' }); // true
FieldValidator.isPostalCode('885 49', {}, { locale: 'SE' }); // true
FieldValidator.isPostalCode(1234567890); // false
FieldValidator.isPostalCode(['85249']); // true
Field Transforms
toBoolean
toBoolean(input, context?) - Converts values to booleans, if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
FieldTransform.toBoolean('0'); // false
FieldTransform.toBoolean(['foo', 'false', null]); // [true, false];
toString
toString(input, context?) - Converts values to strings, if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
FieldTransform.toString(true); // 'true';
FieldTransform.toString([true, undefined, false]); // ['true', 'false'];
toNumber
toNumber(input, context?, args?) - Converts a value to a number if possible
args: { booleanLike: Boolean }
if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
FieldTransform.toNumber('12321'); // 12321;
FieldTransform.toNumber('000011'); // 11;
FieldTransform.toNumber('true', {}, { booleanLike: true }); // 1;
FieldTransform.toNumber(null, {}, { booleanLike: true }); // 0;
FieldTransform.toNumber(null); // null;
FieldTransform.toNumber(['000011', '12321']); // [11, 12321];
toUpperCase
toUpperCase(input, context?) - Converts strings to UpperCase, if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
FieldTransform.toUpperCase('lowercase'); // 'LOWERCASE';
FieldTransform.toUpperCase(['MixEd', null, 'lower']); // ['MIXED', 'LOWER'];
toLowerCase
toLowerCase(input, context?) - Converts strings to lowercase, if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
FieldTransform.toLowerCase('UPPERCASE'); // 'uppercase';
FieldTransform.toLowerCase(['MixEd', null, 'UPPER']); // ['mixed', 'upper'];
toCamelCase
toCamelCase(input, context?) - Will convert a string, or an array of strings to camel case
returns null if input is null/undefined
FieldTransform.toCamelCase('I need camel case'); // 'iNeedCamelCase';
FieldTransform.toCamelCase('happyBirthday'); // 'happyBirthday';
FieldTransform.toCamelCase('what_is_this'); // 'whatIsThis';
const array = ['what_is_this', 'I need camel case'];
FieldTransform.toCamelCase(array); // ['whatIsThis', 'iNeedCamelCase'];
toKebabCase
toKebabCase(input, context?) - Will convert a string, or an array of strings to kebab case
returns null if input is null/undefined
FieldTransform.toKebabCase('I need kebab case'); // 'i-need-kebab-case';
FieldTransform.toKebabCase('happyBirthday'); // 'happy-birthday';
FieldTransform.toKebabCase('what_is_this'); // 'what-is-this';
FieldTransform.toKebabCase('this-should-be-kebab'); // 'this-should-be-kebab';
const array = ['happyBirthday', 'what_is_this']
FieldTransform.toKebabCase(array); // ['happy-birthday', 'what-is-this'];
toPascalCase
toPascalCase(input, context?) - Converts a string to pascal case, or an array of strings
returns null if input is null/undefined
FieldTransform.toPascalCase('I need pascal case'); // 'INeedPascalCase';
FieldTransform.toPascalCase('happyBirthday'); // 'HappyBirthday';
FieldTransform.toPascalCase('what_is_this'); // 'WhatIsThis';
const array = ['happyBirthday', 'what_is_this']
FieldTransform.toKebabCase(array); // ['HappyBirthday', 'WhatIsThis'];
toSnakeCase
toSnakeCase(input, context?) - Converts a string, or an array of strings to snake case
returns null if input is null/undefined
FieldTransform.toSnakeCase('I need snake case'); // 'i_need_snake_case';
FieldTransform.toSnakeCase('happyBirthday'); // 'happy_birthday';
FieldTransform.toSnakeCase('what_is_this'); // 'what_is_this';
const array = ['happyBirthday', 'what_is_this']
FieldTransform.toKebabCase(array); // ['happy_birthday', 'what_is_this'];
toTitleCase
toTitleCase(input, context?) - Converts a string, or an array of strings to title case
returns null if input is null/undefined
FieldTransform.toTitleCase('I need some capitols'); // 'I Need Some Capitols';
FieldTransform.toTitleCase('happyBirthday'); // 'Happy Birthday';
FieldTransform.toTitleCase('what_is_this'); // 'What Is This';
const array = ['happyBirthday', 'what_is_this']
FieldTransform.toKebabCase(array); // ['Happy Birthday', 'What Is This'];
trim
trim(input, context?, args?) - Will trim the input, if given an array it will convert everything in the array excluding null/undefined values
args: { char?: String }
char - if provided, are the chars/words to be cut out
returns null if input is null/undefined
FieldTransform.trim('right '); // 'right';
FieldTransform.trim('fast cars race fast', {}, { char: 'fast' }); // ' cars race ';
FieldTransform.trim(' string ')).toBe('string');
FieldTransform.trim(' left')).toBe('left');
FieldTransform.trim('.*.*a regex test.*.*.*.* stuff', {}, { char: '.*' }); // 'a regex test'
FieldTransform.trim('\t\r\rtrim this\r\r', {}, { char: '\r' }); // 'trim this'
FieldTransform.trim(' '); // ''
FieldTransform.trim(['right ', ' left']); // ['right', 'left'];
trimStart
trimStart(input, context?, args) - Will trim the beginning of the input if given an array it will convert everything in the array excluding null/undefined values
args: { char?: String }
char - if provided, are the chars/words to be cut out
returns null if input is null/undefined
FieldTransform.trimStart(' Hello Bob '); // 'Hello Bob ';
FieldTransform.trimStart('iiii-wordiwords-iii', {}, { char: 'i' }); // '-wordiwords-iii';
FieldTransform.trimStart([' Hello Bob ', 'right ']); // ['Hello Bob ', 'right '];
trimEnd
trimEnd(input, context?, args) - Will trim the end of the input if given an array it will convert everything in the array excluding null/undefined values
args: { char?: String }
char - if provided, are the chars/words to be cut out
returns null if input is null/undefined
FieldTransform.trimEnd(' Hello Bob '); // ' Hello Bob';
FieldTransform.trimEnd('iiii-wordiwords-iii', {}, { char: 'i' }); // 'iiii-wordiwords';
FieldTransform.trimEnd([' Hello Bob ', 'right ']); // [' Hello Bob', 'right'];
truncate
truncate(input, context?, args) - Will truncate the input to the length of the size given. If given an array it will convert everything in the array excluding null/undefined values
args: { size: Number }
size - the size that values should be truncated
returns null if input is null/undefined
FieldTransform.truncate('thisisalongstring', {}, { size: 4 }); // 'this';
FieldTransform.truncate(['hello', null, 'world'], {}, { size: 2 }); // ['he', 'wo'];
toISDN
toISDN(input, context?) - Parses a string or number to a fully validated phone number. If given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
FieldTransform.toISDN('+33-1-22-33-44-55'); // '33122334455';
FieldTransform.toISDN('1(800)FloWErs'); // '18003569377';
FieldTransform.toISDN(['1(800)FloWErs','+33-1-22-33-44-55' ]); // ['18003569377', '33122334455'];
encodeBase64
encodeBase64(input, context?) - converts a value into a base64 encoded value if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const str = 'hello world';
const encodedValue = FieldTransform.encodeBase64(str);
const arrayOfEncodedValues = FieldTransform.encodeBase64([str]);
encodeURL
encodeURL(input, context?) - URL encodes a value if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const source = 'HELLO AND GOODBYE';
const encoded = 'HELLO%20AND%20GOODBYE';
FieldTransform.encodeURL(source); // encoded;
const arrayOfEncodedValues = FieldTransform.encodeURL([source]);
encodeHex
encodeHex(input, context?) - hex encodes the input if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const source = 'hello world';
FieldTransform.encodeHex(source);
const arrayOfEncodedValues = FieldTransform.encodeHex([source]);
encodeMD5
encodeMD5(input, context?) - MD5 encodes the input, if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const source = 'hello world';
FieldTransform.encodeMD5(source);
const arrayOfEncodedValues = FieldTransform.encodeMD5([source]);
encodeSHA
encodeSHA(input, context?, args) - SHA encodes the input to the hash specified if given an array it will convert everything in the array excluding null/undefined values
args { hash = 'sha256', digest = 'hex' }
hash - what ever is available on your node server, defaults to sha256 possible digest values (defaults to hex):
- ['ascii', 'utf8', 'utf16le', 'ucs2', 'base64', 'latin1', 'hex', 'binary']
returns null if input is null/undefined
const data = 'some string';
const config = { hash: 'sha256', digest: 'hex'};
fieldTransform.encodeSHA(data , {}, config)
const arrayOfEncodedValues = FieldTransform.encodeSHA([source], {}, config);
encodeSHA1
encodeSHA1(input, context?) - converts the value to a SHA1 encoded value, if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const source = 'hello world';
FieldTransform.encodeSHA1(source);
const arrayOfEncodedValues = FieldTransform.encodeSHA([source]);
decodeBase64
decodeBase64(input, context?) - decodes a base64 encoded value, if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const str = 'hello world';
const encoded = encodeBase64(str);
const results = FieldTransform.decodeBase64(encoded)
results === str
FieldTransform.decodeBase64([encoded]) === [str]
decodeHex
decodeHex(input, context?) - decodes the hex encoded input if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const source = 'hello world';
const encoded = encodeHex(source);
FieldTransform.decodeHex(encoded); // source;
FieldTransform.decodeHex([encoded]); // [source];
decodeURL
decodeURL(input, context?) - decodes a URL encoded value if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const source = 'HELLO AND GOODBYE';
const encoded = 'HELLO%20AND%20GOODBYE';
FieldTransform.decodeURL(encoded); // source;
FieldTransform.decodeURL([encoded]); //[source];
parseJSON
parseJSON(input, context?) - Parses the json input, if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const obj = { hello: 'world' };
const json = JSON.stringify(obj);
const results = FieldTransform.parseJSON(json);
results === obj
FieldTransform.parseJSON([json]); // [obj]
toJSON
toJSON(input, context?) - Converts input to JSON if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
const obj = { hello: 'world' };
FieldTransform.toJSON(obj); // '{"hello": "world"}'
FieldTransform.toJSON([obj]); // ['{"hello": "world"}']
dedupe
dedupe(input, context?) - returns an array with only unique values
returns null if input is null/undefined
const results = FieldTransform.dedupe([1, 2, 2, 3, 3, 3, undefined, 4])
results === [1, 2, 3, undefined, 4]
toGeoPoint
toGeoPoint(input, context?) - Converts the value into a geo-point, if given an array it will convert everything in the array excluding null/undefined values
returns null if input is null/undefined
fieldTransform.toGeoPoint('60, 40') // { lon: 40, lat: 60 };
fieldTransform.toGeoPoint([40, 60]) // { lon: 40, lat: 60 };
fieldTransform.toGeoPoint({ lat: 40, lon: 60 }) // { lon: 60, lat: 40 };
fieldTransform.toGeoPoint({ latitude: 40, longitude: 60 }) // { lon: 60, lat: 40 };
const results = FieldTransform.toGeoPoint(['60, 40', null, [50, 60]]);
results === [{ lon: 40, lat: 60 },{ lon: 50, lat: 60 }];
extract
extract(input, context, args) - Can extract values from a string input. You may either specify a regex, a jexl expression, or specify the start and end from which the extraction will take all values inbetween, if given an array it will convert everything in the array excluding null/undefined values
args - { regex?: String, isMultiValue = true, jexlExp?: String, start?: String, end?: String }
If regex is specified, it will run the regex against the value.
If isMultiValue is true, then an array containing the return results will be returned. If it is set to false, then only the first possible extraction will be returned.
start/end are used as boundaries for extraction, should not be used with jexlExp or regex
jexlExp is a jexl expression => https://github.com/TomFrost/Jexl
returns null if input is null/undefined
const results = FieldTransform.extract('<hello>', { field: '<hello>' }, { start: '<', end: '>' ;
results; // 'hello';
const results = FieldTransform.extract({ foo: 'bar' }, { foo: 'bar' } { jexlExp: '[foo]' });
results; // ['bar'];
const results = FieldTransform.extract('hello', { field: 'hello'} { regex: 'he.*' });
results; // ['hello'];
const results = FieldTransform.extract('hello', { field: 'hello'} { regex: 'he.*', isMultiValue: false });
results; // 'hello';
const context = { field: ['<hello>', '<world>'] };
const results = FieldTransform.extract(['<hello>', '<world>'], context, config);
results; // ['hello', 'world'];
replaceRegex
replaceRegex(input, context, args) - This function replaces chars in a string based off the regex value provided
args - { regex: String, replace: String, ignoreCase = false, global = false }
returns null if input is null/undefined
const config = { regex: 's|e', replace: 'd' };
const results = FieldTransform.replaceRegex('somestring', {}, config)
results1 === 'domestring'
const config = { regex: 's|e', replace: 'd', global: true };
const results = FieldTransform.replaceRegex('somestring', {}, config)
results === 'domddtring'
const results = FieldTransform.replaceRegex(['somestring', 'hello'], {}, config)
results === ['domddtring', 'hdllo']
const results = FieldTransform.replaceRegex('somestring', {}, config)
results === 'domddtring'
const config = {
regex: 'm|t', replace: 'W', global: true, ignoreCase: true
};
const results = FieldTransform.replaceRegex('soMesTring', {}, config))
results === 'soWesWring'
replaceLiteral
replaceLiteral(input, context, args) - This function replaces the searched value with the replace value
args - { search: String, replace: String }
search is the word that is to be changed to the value specified with the parameter replace
returns null if input is null/undefined
FieldTransform.replaceLiteral('Hi bob', {}, { search: 'bob', replace: 'mel' }) // 'Hi mel';
FieldTransform.replaceLiteral('Hi Bob', {}, { search: 'bob', replace: 'Mel ' }) // 'Hi Bob';
const data = ['Hi bob', 'hello bob'];
const config = { search: 'bob', replace: 'mel' };
FieldTransform.replaceLiteral(data, {}, config) // ['Hi mel', 'hello mel'];
splitString
splitString(input, context?, args?) - Converts a string to an array of characters split by the delimiter provided
args - { delimiter?: String }
delimiter defaults to an empty string
returns null if input is null/undefined
FieldTransform.splitString('astring'); // ['a', 's', 't', 'r', 'i', 'n', 'g'];
FieldTransform.splitString('astring', {}, { delimiter: ',' }); // ['astring'];
const config = { delimiter: '-' };
FieldTransform.splitString('a-stri-ng', {}, config); // ['a', 'stri', 'ng'];
const results = FieldTransform.splitString(['a-stri-ng', 'hello-world'], {}, config);
results // [['a', 'stri', 'ng'], ['hello', 'world']];
toUnixTime
toUnixTime(input, context?, args) - Converts a given date to its time in milliseconds or seconds ? args - { ms = false } set ms to true if you want time in milliseconds returns null if input is null/undefined
FieldTransform.toUnixTime('2020-01-01'); // 1577836800;
FieldTransform.toUnixTime('Jan 1, 2020 UTC'); // 1577836800;
FieldTransform.toUnixTime('2020 Jan, 1 UTC'); // 1577836800;
FieldTransform.toUnixTime(1580418907000); // 1580418907;
FieldTransform.toUnixTime(1580418907000, {}, { ms: true }); // 1580418907000;
FieldTransform.toUnixTime(['Jan 1, 2020 UTC', '2020 Jan, 1 UTC']); // [1577836800, 1577836800];
toISO8601
toISO8601(input, context?, args) - Converts a date string or number to an ISO date
args - { resolution?: String } resolution value: ['seconds', 'milliseconds'], defaults to seconds
returns null if input is null/undefined
FieldTransform.toISO8601('2020-01-01'); // '2020-01-01T00:00:00.000Z';
const config = { resolution: 'seconds' };
FieldTransform.toISO8601(1580418907, {}, config); // '2020-01-30T21:15:07.000Z';
const data = ['2020-01-01', '2020-01-02'];
FieldTransform.toISO8601(data); // ['2020-01-01T00:00:00.000Z', '2020-01-02T00:00:00.000Z'];
formatDate
formatDate(input, context, args) - Function that will format a number or date string to a given date format provided
args - { format: String, resolution?: String } format is the shape that the date will be ie(M/d/yyyy) resolution value: ['seconds', 'milliseconds'], defaults to seconds, is only needed when input is a number
returns null if input is null/undefined
const results1 = FieldTransform.formatDate('2020-01-14T20:34:01.034Z', {}, { format: 'MMM do yy' })
results1 === 'Jan 14th 20';
const results2 = FieldTransform.formatDate('March 3, 2019', {}, { format: 'M/d/yyyy' })
results2 === '3/3/2019';
const config = { format: 'yyyy-MM-dd', resolution: 'seconds' };
const results3 = FieldTransform.formatDate(1581013130, {}, config)
results3 === '2020-02-06';
const results = FieldTransform.formatDate([1581013130856, undefined], {}, { format: 'yyyy-MM-dd' })
results // ['2020-02-06']);
parseDate
parseDate(input, context?, args) - Will use date-fns parse against the input and return a date object
args - { format: String }
format is the shape that the date will be ie(M/d/yyyy)
returns null if input is null/undefined
const result = FieldTransform.parseDate('2020-01-10-00:00', {}, { format: 'yyyy-MM-ddxxx' })
result === new Date('2020-01-10T00:00:00.000Z');
const result = FieldTransform.parseDate('Jan 10, 2020-00:00', {}, { format: 'MMM dd, yyyyxxx' })
result === new Date('2020-01-10T00:00:00.000Z');
const result = FieldTransform.parseDate(1581025950223, {}, { format: 'T' })
result === new Date('2020-02-06T21:52:30.223Z');
const result = FieldTransform.parseDate(1581025950, {}, { format: 't' })
result === new Date('2020-02-06T21:52:30.000Z');
const result = FieldTransform.parseDate('1581025950', {}, { format: 't' })
result === new Date('2020-02-06T21:52:30.000Z');
const result = FieldTransform.parseDate(['1581025950', 1581025950], {}, { format: 't' })
result === [new Date('2020-02-06T21:52:30.000Z'), new Date('2020-02-06T21:52:30.000Z')];
setDefault
setDefault(input, context?, args) - This function is used to set a value if input is null or undefined, otherwise the input value is returned
args: { value: Any }
value is what will be given when input is null/undefined
const results = FieldTransform.setDefault(undefined, { value: 'someValue' });
results === 'someValue';
map
map(input, context?, args) - This function is used to map an array of values with any FieldTransform method
args: { fn: String, options: Any }
returns null if input is null/undefined
fn must be a function name from FieldTransform options are any additional parameters necessary for the fn being evoked
const array = ['hello', 'world', 'goodbye'];
const results = FieldTransform.map(array, { fn: 'truncate', options: { size: 3 } }
results === ['hel', 'wor', 'goo']
Record Validations
required
required(input, context, args) - This function will return false if input record does not have all specified keys
args - { fields: string[] }
const obj1 = { foo: 'hello', bar: 'stuff' };
const obj2 = { foo: 123412 };
const fields = ['bar'];
const results1 = RecordValidator.required(obj1, obj1, { fields });
const results2 = RecordValidator.required(obj2, obj2, { fields });
results1; // true;
results2; // false;
select
select(input, context, args) - Will return true if an object matches the xLucene expression
args - { query: xLuceneQuery, type_config?: xLuceneTypeConfig, variables?: xLuceneVariables }
const obj1 = { foo: 'hello', bar: 'stuff' };
const obj2 = { foo: 123412 };
const args = { query: '_exists_:bar' };
const results1 = RecordValidator.select(obj1, obj1, args);
const results2 = RecordValidator.select(obj2, obj2, args);
results1; // true;
results2; // false;
reject
reject(input, context, args) - Will return true if an object DOES NOT match the xLucene expression
args - { query: xLuceneQuery, type_config?: xLuceneTypeConfig, variables?: xLuceneVariables }
const obj1 = { foo: 'hello', bar: 'stuff' };
const obj2 = { foo: 123412 };
const args = { query: '_exists_:bar' };
const results1 = RecordValidator.reject(obj1, obj1, args);
const results2 = RecordValidator.reject(obj2, obj2, args);
results1; // false;
results2; // true;
Record Transforms
renameField
renameField(input, context, args) - This will migrate a fields value to a new field name
args - { from: string; to: string }
const obj = { hello: 'world' };
const config = { from: 'hello', to: 'goodbye' };
const results = RecordTransform.renameField(cloneDeep(obj), config);
results === { goodbye: 'world' };
setField
setField(input, context, args) - Sets a field on a record with the given value
args - { field: string; value: Any }
const obj = { hello: 'world' };
const config = { field: 'other', value: 'stuff' };
const results = RecordTransform.setField(cloneDeep(obj), obj, config);
results === { hello: 'world', other: 'stuff' };
dropFields
dropFields(input, context, args) - removes fields from a record
args - { fields: string[] }
const obj = { hello: 'world', other: 'stuff', last: 'thing' };
const config = { fields: ['other', 'last']} ;
const results = RecordTransform.dropFields(cloneDeep(obj), obj, config);
results === { hello: 'world' };
copyField
copyField(input, context, args) - Will copy a field to another field
args - { from: string; to: string }
const obj = { hello: 'world', other: 'stuff' };
const config = { from: 'other', to: 'myCopy' };
const results = RecordTransform.copyField(cloneDeep(obj), obj, config);
results; // { hello: 'world', other: 'stuff', myCopy: 'stuff' };
transformRecord
transformRecord(input, context, args) - Will execute a jexl expression. Can use data-mate functions inside the jexl expression. You do not need to specify the parent context argument as that is automatically the document used as to call it.
args - { jexlExp: string; field: string }
const obj = { num: 1234 };
const config = { jexlExp: 'num * 2', field: 'calc' };
const results = RecordTransform.transformRecord(
obj, obj, config
))
results === { num: 1234, calc: 1234 * 2 };
const obj = { foo: 'bar' };
const config = {
jexlExp: 'foo|extract({ jexlExp: "foo|toUpperCase" })', field: 'final'
};
const mixedData = [obj, undefined, null];
const results = RecordTransform.transformRecord(
mixedData, mixedData, config
)
results === [{ foo: 'bar', final: 'BAR' }];
Document Matcher
This takes in a lucene based query along with some configuration and allows you to run data against it to see if it matches
const { DocumentMatcher } = require('xlucene-evaluator');
// you can set the configuration at instantiation time as well if you call parse()
const matcher1 = new DocumentMatcher('some:data AND (other:stuff OR other:things)');
const data1 = { some: 'data', other: 'stuff' };
const data2 = { some: 'data', fake: 'stuff' };
matcher1.match(data1) // true
matcher1.match(data2) // false
const matcher2 = new DocumentMatcher('some:data OR (other:stuff OR other:things)');
matcher2.match(data1) // true
matcher2.match(data2) // true
// more complex queries
const matcher3 = new DocumentMatcher('key:value AND (duration:<=10000 OR ipfield:{"192.198.0.0" TO "192.198.0.255"])', {
type_config: {
ipfield: 'ip',
key: 'string',
duration: 'integer'
}
});
const data3 = { ipfield: '192.198.0.0/24', key: 'value', duration: 9263 };
const data4 = { ipfield: '192.198.0.0/24', key: 'otherValue', duration: 9263 };
matcher3.match(data3) // true
matcher3.match(data4) // false
const data5 = { location: '33.435967,-111.867710', some: 'key', bytes: 123432 };
const data6 = { location: '22.435967,-150.867710', other: 'key', bytes: 123432 };
const data7 = { location: '22.435967,-150.867710', bytes: 100 };
const matcher4 = new DocumentMatcher('location:geoBox(top_left_:"33.906320,-112.758421", bottom_right:"32.813646,-111.058902") OR (some:/ke.*/ OR bytes:>=10000)', {
type_config: {
location: 'geo',
bytes: 'integer',
some: 'string'
}
});
matcher4.match(data5) // true
matcher4.match(data6) // true
matcher4.match(data7) // false
Ranges
You may specify ranges using < > <= >=
syntax as well as []
(inclusive) and {}
signs. A *
may be used to signify infinity or -infinity depending where it is used.
const data1 = { age: 8 };
const data2 = { age: 10 };
const data3 = { age: 15 };
// This query is the same as age:{10 TO 20}
const matcher1 = new DocumentMatcher('age:(>10 AND <20)');
matcher1.match(data) // false
matcher1.match(data2) // false
matcher1.match(data3) // true
//This is functionally equivalent to the query above
const matcher2 = new DocumentMatcher('age:{10 TO 20}');
matcher2.match(data) // false
matcher2.match(data2) // false
matcher2.match(data3) // true
// This query is the same as age:[10 TO 20}
const matcher3 = new DocumentMatcher('age:(>=10 AND <20)');
matcher3.match(data) // false
matcher3.match(data2) // true
matcher3.match(data3) // true
const matcher4 = new DocumentMatcher('age:[10 TO 20}');
matcher4.match(data) // false
matcher4.match(data2) // true
matcher4.match(data3) // true
const matcher5 = new DocumentMatcher('age:{10 TO *}');
matcher5.match(data) // false
matcher5.match(data2) // false
matcher5.match(data3) // true
Types
NOTE: Strings that contain dates, ip's and the like will be treated as exact match queries unless you specify the type of the field in the configuration
IP
This has support for ipv4, ipv6 and cidr notation. Any cidr notation value need to be quoted while ipv4 and ipv6 do not
const data1 = { ipfield: '192.198.0.0/24' };
const data2 = { ipfield: '192.198.0.10' };
// not specifying types turns it into a exact match query
const staticMatcher = new DocumentMatcher('ipfield:"192.198.0.0/24"');
staticMatcher.match(data1) // true
staticMatcher.match(data2) // false
const IptypeMatcher = new DocumentMatcher('ipfield:"192.198.0.0/24"', {
type_config: {
ipfield: 'ip'
}
});
IptypeMatcher.match(data1) // true
IptypeMatcher.match(data2) // true
// can use range modifiers
const data3 = { ipfield: '192.198.0.0' };
const data4 = { ipfield: '192.198.0.1' };
const data5 = { ipfield: '192.198.0.254' };
const data6 = { ipfield: '192.198.0.255' };
const data7 = { ipfield: '192.198.0.0/30' };
const rangeIpMatcher = new DocumentMatcher('ipfield:[192.198.0.0 TO 192.198.0.255]', {
type_config: {
ipfield: 'ip'
}
});
rangeIpMatcher.match(data3) // true
rangeIpMatcher.match(data4) // true
rangeIpMatcher.match(data5) // true
rangeIpMatcher.match(data6) // true
rangeIpMatcher.match(data7) // true
Dates
Has support for date comparison
const data1 = { _created: 'Thu Oct 18 2018 11:13:20 GMT-0700' };
const data2 = { _created: '2018-10-18T18:13:20.683Z' };
// not specifying types turns it into a exact match query
const staticMatcher = new DocumentMatcher('_created:"2018-10-18T18:13:20.683Z"');
staticMatcher.match(data1) // false
staticMatcher.match(data2) // true
const data3 = { _created: 'Thu Oct 18 2018 22:13:20 GMT-0700' };
const data4 = { _created: '2018-10-18T18:13:20.683Z' };
const data5 = { _created: '2018-10-18T18:15:34.123Z' };
const data6 = { _created: 'Thu, 18 Oct 2020 18:13:20 GMT' };
const data7 = { _created: 'Thu, 13 Oct 2018 18:13:20 GMT' };
const dateTypeMatcher = new DocumentMatcher('_created:[2018-10-18T18:13:20.683Z TO *]', {
type_config: {
_created: 'date'
}
});
dateTypeMatcher.match(data3) // true
dateTypeMatcher.match(data4) // true
dateTypeMatcher.match(data5) // true
dateTypeMatcher.match(data6) // true
dateTypeMatcher.match(data7) // false
const dateTypeMatcher2 = new DocumentMatcher('_created:[2018-10-18T18:13:20.000Z TO 2018-10-18T18:13:20.783Z]', {
type_config: {
_created: 'date'
}
});
dateTypeMatcher2.match(data3) // false
dateTypeMatcher2.match(data4) // true
dateTypeMatcher2.match(data5) // false
dateTypeMatcher2.match(data6) // false
dateTypeMatcher2.match(data7) // false
Geo
Has support for geo based queries. It expects all geo points to be in the lat,lon
format.
There are 3 "geo functions" that are available for use:
-
geoDistance
which checks if a point is within range-
point
= geo point, -
distance
= distance from point specifieddistance may be set to:
- meters (can abbreviate to
m
) - yards (can abbreviate to
yd
) - kilometers (can abbreviate to
km
) - nauticalmiles (can abbreviate to
NM
ornmi
) - miles (can abbreviate to
mi
) - inches (can abbreviate to
in
) - millimeters (can abbreviate to
mm
) - centimeters (can abbreviate to
cm
) - feet (can abbreviate to
ft
)
- meters (can abbreviate to
-
-
geoBox
runs a geo bounding box query, checks if point is within boxtop_left
geo pointbottom_right
geo point
-
geoPolygon
runs a geo polygon query, checks if point is within polygon shapepoints
list of geo points that make up the polygon
NOTE: since geo syntax is a grammar primitive no types are needed, it can automatically infer it.
const data1 = { location: '33.435967,-111.867710' };
const data2 = { location: '22.435967,-150.867710' };
const geoBoundingBoxTypeMatcher = new DocumentMatcher('location: geoBox(top_left:"33.906320,-112.758421", bottom_right:"32.813646,-111.058902")');
geoBoundingBoxTypeMatcher.match(data1); // true
geoBoundingBoxTypeMatcher.match(data2); // false
const geoDistanceTypeMatcher = new DocumentMatcher('location:geoDistance(point:"33.435518,-111.873616" distance:"5000m")');
geoDistanceTypeMatcher.match(data1) // true
geoDistanceTypeMatcher.match(data2) // false
const geoDistanceTypeMatcher = new DocumentMatcher('location:geoPolygon(points:["32.536967,-113.968710", "33.435967,-111.867710", "33.435967,-109.867710"])');
geoDistanceTypeMatcher.match(data1) // true
geoDistanceTypeMatcher.match(data2) // false
Regex and Wildcard queries
For this types DO NOT need to be specified and is done by the query itself. A wildcard query can use the ?
to represent a single non empty char and a *
to match anything. A regex value must be wrapped in a / expression_here /
and follows the regular expression standard. NOTE: all regex expressions are anchored!!! Design you regex accordingly
ie "abcde":
ab.* // match abcd // no match
const data6 = { key : 'abbccc' };
const data7 = { key : 'abc' };
const data8 = { key : 'zabcde' };
const data9 = { key : 'abcccde' };
// regex based queries
const regexMatcher = new DocumentMatcher('key:/ab{2}c{3}/');
regexMatcher.match(data6) // true
regexMatcher.match(data7) // false
regexMatcher.match(data8) // false
regexMatcher.match(data9) // false
// regex based queries
const regexMatcher2 = new DocumentMatcher('key:/ab*c*/');
regexMatcher2.match(data6) // true
regexMatcher2.match(data7) // true
regexMatcher2.match(data8) // false
regexMatcher2.match(data9) // false
// regex based queries
const regexMatcher3 = new DocumentMatcher('key:/.*abcd?e?/');
regexMatcher3.match(data6) // false
regexMatcher3.match(data7) // true
regexMatcher3.match(data8) // true
regexMatcher3.match(data9) // false
// wildcard query
const wildcardMatcher = new DocumentMatcher('key:?abc*');
wildcardMatcher.match(data6) // false
wildcardMatcher.match(data7) // false
wildcardMatcher.match(data8) // true
wildcardMatcher.match(data9) // false
const wildcardMatcher2 = new DocumentMatcher('key:abc??de');
wildcardMatcher2.match(data6) // false
wildcardMatcher2.match(data7) // false
wildcardMatcher2.match(data8) // false
wildcardMatcher2.match(data9) // true